emrg: gui renderer Batch 2 — chat transcript store + TranscriptView component - #994
Merged
Conversation
…omponent Port chat.js logic to a pure per-session state machine (lib/transcript.ts): delta/done/toolStart/toolEnd/clearTyping/clear with sid buckets (P3), tool-group merge (rant 21:28:49: summary + collapse + user-expanded) — 15 vitest tests mirroring the old tool-group.test.js assertions. Add React TranscriptView component: streaming plain-text -> markdown-on-done via injectable renderer, tool rows running/done/failed with elapsed and expandable output, merge-group bar, remote label — 7 component tests. Vanilla renderer stays live until Batch 5 switch (design D3).
argszero
commented
Aug 26, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-150007
Re-verified the full diff vs master (15b2c7d):
lib/transcript.tsis a faithful pure-logic port of chat.js: per-session state buckets (P3), delta accumulation per rid with sealed-segment reopening (rant 21:57:10), doneRids late-delta drop (rant 14:11), consecutive-tool merge groups with summary/collapse/user-expanded (rant 21:28:49), timeout/max-rounds hints via injected t. No DOM side effects; subscribe/getVersion contract for useSyncExternalStore.- 15 store tests mirror the old tool-group.test.js assertions (merge → 1 group/3 rows/1.9s summary/collapse, bar-click expand + user-expanded persistence, text-interleave no-merge) plus delta/done/isolation/clear/subscription coverage.
TranscriptView.tsxrenders the store with vanilla-matching class names (CSS reuse at Batch 5), streaming plain-text → markdown-on-done via injectable renderer (✦ outside markdown text), tool-row lifecycle with elapsed + expandable output, merge-group bar, remote-client label.- 7 component tests with a fake markdown renderer (store mutations wrapped in act()).
- Agent.md renderer count synced 56→78 (breakdown sums correctly; doc-count guard #511 passes).
CI: test + test-windows both pass (run 32940129214). Clean to merge after 3 votes.
argszero
commented
Aug 26, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-150924
Second independent review pass:
- head f74cc9c unchanged since the 1/3 vote; diff vs master still +1085 lines across the 5 expected files.
- Re-spot-checked transcript.ts: P3 per-session buckets, doneRids late-delta guard (>500 clear), segment sealing on tool interleave, merge-group collapse/user-expanded logic — all faithful to chat.js semantics.
- CI: test + test-windows both pass (run 32940129214).
- Agent.md count 56→78 with breakdown summing to 78 (doc-count guard #511 satisfied).
2/3 — one more vote to merge.
argszero
commented
Aug 26, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-151642
Third consecutive vote (150007 → 150924 → 151642, no ❌ in between).
- head f74cc9c unchanged; CI test + test-windows still green (run 32940129214); CLEAN/MERGEABLE.
- Full diff re-confirmed (+1085 lines / 5 files: transcript.ts store, 15 store tests, TranscriptView, 7 component tests, Agent.md count 56→78).
3/3 — merging.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 26, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GUI renderer React migration — Batch 2 (chat area core)
Part of the staged React migration (design
~/.emrg/designs/gui-react-migration-design.md, Batch 2). Vanilla renderer stays live until the Batch 5 switch (design D3) — this batch adds the React-side modules independently, exactly like Batches 0–1.What's in this PR
1.
renderer/src/lib/transcript.ts— pure chat transcript state machine (port ofrenderer/js/chat.js, 471 lines)sid(P3:entries/groupIndex/toolRowIndex/doneRids);sid=nullkeeps the legacy single-session bucket behavior.request_idinto the active text segment; deltas arriving afterdoneare dropped (rant 14:11); a text segment sealed by a following tool call opens a new segment on the next delta (rant 21:57:10 / 21:09, preserves TUI interleaving order and removes the typing cursor on sealed segments).running → done/failed, elapsed only recorded on success (feeds group summary sums), content captured for the 2000-char truncation + expand behavior (G91/G131).userExpanded, rule 5).donefinalizes segments (typing off), tracksdoneRids(>500 → cleared), and pushes timeout / max-rounds hint system messages via an injectedt(same injectable-i18n pattern ascopywriting.ts).useSyncExternalStore; no DOM/scroll/empty-state side effects (component layer owns those).2.
renderer/src/lib/transcript.test.ts— 15 vitest testsMirrors the old
emrg/gui/test/tool-group.test.jsassertions (merge → 1 group with 3 rows + summary3 个工具执行 · 1.9s+ collapse, bar click → expand +user-expanded, new tool stays expanded; text interleave → no merge, 2 independent rows) plus delta accumulation, segment sealing, late-delta drop, done/timeout/maxRounds, per-session isolation, unregister, clear/clearTyping, row output toggle, failed-row elapsed absence, and the subscribe/version contract.3.
renderer/src/components/TranscriptView.tsx— React chat area componentuseSyncExternalStore(version snapshot); class names match the vanilla DOM (.msg.user/.msg.assistant/.tool-row/.tool-group/.history-load-bar), so the existing CSS applies unchanged at the Batch 5 switch.donethey render full markdown through the injectablecreateMarkdownRenderer(no marked/DOMPurify/hljs bundled yet — falls back to escaped text without vendors). The ✦ marker is rendered outside the markdown text so it never breaks block syntax.toolPhrases, intent line,· Nselapsed, hidden-by-default output toggled by row click, expand-full-text button for >2000 chars.user-expandedpersistence; remote-client broadcast label when the stream is not own.4.
renderer/src/components/TranscriptView.test.tsx— 7 component testsRendering of user/system/history/load-bar, streaming → markdown-on-done (injected fake renderer), tool-row lifecycle with elapsed + output toggle, failed rows, group summary + collapse + expand persistence, remote label for broadcast streams / absent for own streams, and the
sid=nulldefault bucket.Verification
cd emrg/gui/renderer && npm run typecheck✅ (TS strict)cd emrg/gui/renderer && npm test✅ 78 passed (was 56: +15 transcript +7 TranscriptView)cd emrg/gui/renderer && npm run build✅ (dist/index.html + assets, CSP-safe)cd emrg/gui && npm test✅ 265 (257 pass / 8 skipped — unchanged)pytest tests/✅ 1094 passed + 1 skipped (doc-count guard emrg: sync test counts to 484 + guard test against doc drift (recurs #426/#430/#510) #511: Agent.md renderer count synced to 78)python -c "from emrg.client.app import run_client"✅ ·python -m emrg --help✅No changes to the daemon,
window.emrgpreload bridge (53 members), main.js/preload.js, or the daemon protocol.