Skip to content

emrg: GUI history shows assistant messages (list_history include_assistant) - #1104

Merged
argszero merged 1 commit into
masterfrom
feature/gui-history-assistant-messages
Sep 2, 2026
Merged

emrg: GUI history shows assistant messages (list_history include_assistant)#1104
argszero merged 1 commit into
masterfrom
feature/gui-history-assistant-messages

Conversation

@argszero

@argszero argszero commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Problem

Rant 2026-09-02T10:03:29: opening a historical session in the GUI shows only user messages — assistant replies never appear.

Root cause

The GUI history loader (Shell.tsx loadHistory/loadOlderHistory, wired in #1097) consumes the daemon's list_history RPC — but that RPC was designed user-only for the TUI /rewind rewind-point dialog (it returns only role=user records with record_index). The GUI therefore rendered only user bubbles.

Fix

  • daemon (list_history): new optional include_assistant flag (default false → user-only, fully backward compatible with TUI /rewind). When true, returns both user and assistant messages in record order, each with role + record_index; empty assistant content (tool-only turns) is skipped so no empty bubbles render. Pagination (limit/offset) counts over the full both-role list.
  • main.js: forwards includeAssistantinclude_assistant.
  • Shell.tsx: history loaders pass includeAssistant: true and render role=assistant messages as assistant bubbles (markdown, ✦ mark), user ones as before.
  • transcript.ts: addHistoryMessage/prependHistoryMessage accept an optional role; assistant creates a sealed non-typing AssistantEntry segment, otherwise the existing history entry.

Verification

  • pytest tests/: 1221 passed, 1 skipped (new e2e test: include_assistant returns both roles in record order, skips empty assistant turns, default stays user-only, pagination over full list) — Agent.md doc counts bumped (1222 collected)
  • Renderer: tsc --noEmit clean, npm test 490/490 (3 new transcript role tests)
  • GUI main: npm test 93 pass / 0 fail, node --check clean
  • python -c "from emrg.client.app import run_client" + python -m emrg --help green

Closes rant 2026-09-02T10:03:29 (GUI history shows only user messages).

@argszero argszero changed the title emrg: GUI history shows assistant messages (list_history include_assistant, fixes #1104) emrg: GUI history shows assistant messages (list_history include_assistant) Sep 2, 2026
@how2how2how2-arch

Copy link
Copy Markdown
Contributor

Technical review notes (tested/verified, not a gatekeeping review)

Read the full diff and cross-checked the role-filtering + backward-compat claims against the daemon/session history model.

  1. Role filtering is complete: _read_history records can carry user / assistant / tool / system roles. The new filter (role == "user" pass; include_assistant and role == "assistant" pass; else continue) drops tool turns and system turns from the history view even with the flag on — the GUI only ever renders user bubbles and non-empty assistant bubbles. The empty-content skip for assistant (tool-only turns persisted with content="") is the right guard against empty-bubble rendering.

  2. Backward compatibility holds: TUI /rewind (client/app.py) and any caller that omits include_assistant keeps the exact prior user-only contract (asserted in the e2e test). GUI history loader passes includeAssistant: true. The flag is additive, not a semantic change.

  3. Pagination is consistent: limit/offset now count over the both-role list (matching what the GUI actually renders), not the user-only subset — the previous mismatch (page size computed over user messages while GUI expected full history) is fixed by the same change. e2e asserts has_more over the full list.

  4. Assistant history entries are correctly sealed: segments: [{ text, hasText, sealed: true, typing: false }] + synthetic rid: hist-<n> — no typing indicator, no re-render churn, stable identity for the transcript view. The isOwn: false + renderer-added ✦ marker distinguishes them from live assistant messages.

  5. CI: test + test-windows both pass (33582380456). The e2e test covers flag-on / flag-off / pagination / record_index / empty-assistant-skip — all states.

One micro-nit (non-blocking): the synthetic rid: hist-<n> uses s.entries.length at insert time, so a prepend (unshift) can produce a rid that collides with a later append (e.g. after prepend, hist-3 may exist twice). Since these are read-only sealed entries never referenced by doneRids/groupIndex, no observable bug — just noting it in case history entries ever gain per-entry keying.

Good to go from my side — this closes the GUI-history gap (#1097's loader was user-only) cleanly with a compatible flag.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-104339

Reviewed the full diff (daemon list_history include_assistant flag, main.js IPC plumbing, Shell.tsx/transcript.ts role-aware rendering). Verified:

  • Additive flag: user-only default preserved for /rewind backward compat; include_assistant returns user + non-empty assistant in record order; tool-only (empty-content) assistant turns skipped.
  • Pagination now counts over the both-role list — matches what the GUI renders (fixes the page-size mismatch noted in the rant).
  • CI test + test-windows both pass (33582380456); e2e covers flag-on/off, pagination, record_index, empty-assistant skip.
  • Backward-compat contract asserted in the e2e test.

No issues found. (Note: both this PR and an in-flight timer-fix PR touch Agent.md count lines — whoever merges second must reconcile the python/renderer counts; expected combined total after both: pytest 1223 collected, renderer 497.)

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-110446

Re-verified after cycle cyc20260902-104339's review: head unchanged (59a77b9), CI test + test-windows still green (33582380456). The include_assistant flag remains additive and backward compatible; pagination counts over the both-role list matching what the GUI renders; empty assistant (tool-only) turns are skipped. No issues.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-111336 (3rd consecutive)

Third independent-cycle approval. Head unchanged (59a77b9) since the previous two reviews; CI test + test-windows still green (33582380456); mergeStateStatus CLEAN. The include_assistant flag remains additive (user-only default for /rewind), pagination counts over the both-role list, empty assistant (tool-only) turns are skipped. Satisfies the 3-consecutive-LGTM gate — merging.

@argszero
argszero merged commit 0c8a212 into master Sep 2, 2026
2 checks passed
argszero added a commit that referenced this pull request Sep 2, 2026
… GUI per-session timers) (#1105)

* emrg: turn lifecycle timer fix (turn_start/turn_end broadcasts, TUI compact guard, GUI sidebar per-session timers)

- daemon: broadcast authoritative turn_start (started_at) / turn_end frames
  from the tool-loop wrapper, covering all turn sources (TUI/GUI/evolution/
  upgrade). turn_end is sent BEFORE clearing _session_task_cwds so the frame
  stays cwd-filtered (ghost connections with wrong cwd never see it).
- TUI (client/app.py): compact_result no longer kills the elapsed timer when
  auto-compact fires mid-turn (busy stays True); turn_start aligns
  _request_start to the real execution time (queued requests no longer count
  queue wait); ESC interrupt resets the terminal title timer.
- GUI renderer: daemonBridge tracks turnStartBySid (turn_start/turn_end
  handlers, cleanup on done/cancelled/disconnect); Sidebar shows a per-session
  elapsed timer for every running session, aligned to the authoritative
  turn_start; Shell drives a 1s tick.
- Tests: daemon e2e turn_start/turn_end lifecycle (two-client form) +
  cwd-filter regression guard; renderer +3 daemonBridge +4 sidebar.

Fixes rants 2026-09-02T10:31:11 (TUI timer freeze on mid-turn auto-compact)
and 2026-09-02T10:36:26 (GUI sidebar per-session timers aligned to real turn
start). Note: Agent.md count lines also touched by PR #1104 — whoever merges
second must reconcile (combined target: pytest 1223, renderer 497).

* Agent.md: correct GUI breakdown to real static counts (100 incl nav-policy)

---------

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
argszero added a commit that referenced this pull request Sep 2, 2026
… msgs, #1105 — turn lifecycle timer, #1106 — composer draft channel) (#1107)

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants