You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(sessions): add ACP session resume and sidebar playback
Implement thread-level ACP session selection and resume across backend
providers and the Web UI. Persist agentOptions.sessionId, add thread
session listing, bind effective session IDs during turns, and emit
session_bound so selected sessions survive across turns.
Update prompt construction and chat replay to be session-aware, including
session-scoped history filtering, transcript merge fallback behavior, and
a paginated right-side session sidebar with switch/new-session actions.
This prevents duplicated context after session/load and makes resumed
sessions visible and controllable in the UI.
Copy file name to clipboardExpand all lines: PROGRESS.md
+29Lines changed: 29 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -575,3 +575,32 @@ This file is the source of milestone progress, validation commands, and next act
575
575
- 2026-03-09: hid the Web UI Reasoning switch when the active agent exposes fewer than two reasoning choices, so agents without switchable reasoning no longer show a dead control.
576
576
- 2026-03-09: switched Kimi model/reasoning catalog queries to local `config.toml` when available, so startup catalog refresh and thread config/model operations no longer create empty Kimi sessions; real prompt turns still use ACP.
577
577
- 2026-03-11: added opt-in `--debug` startup flag; when enabled, stderr now emits sanitized `acp.message` traces for ACP stdio and embedded-runtime request/response traffic, including session prompts, updates, and permission flows.
578
+
- 2026-03-11: added ACP session browsing/resume support across built-in agents:
579
+
- introduced shared agent session abstractions for `session/list`, bound-session reporting, and initialize capability parsing.
580
+
- built-in providers now:
581
+
- list sessions through ACP `session/list` when supported.
582
+
- load persisted `agentOptions.sessionId` through ACP `session/load` before prompting.
583
+
- report the effective session id back to HTTP turns so the server can persist it.
584
+
- added `GET /v1/threads/{threadId}/sessions` with cursor passthrough and graceful `supported=false` fallback for agents without ACP session-history support.
585
+
- turn SSE now emits `session_bound`, and the server persists the thread session id without closing the active provider.
586
+
- once a thread is bound to an ACP session, prompt building skips local recent-turn injection to avoid duplicating already-loaded ACP context.
587
+
- Web UI now renders a right-side session sidebar with first-page load, `Show more`, active-session highlighting, and `New session` reset.
588
+
- executed validation:
589
+
- pass: `cd internal/webui/web && npm run build`
590
+
- pass: `go test ./internal/httpapi -run 'TestThreadSessionsListEndpoint|TestTurnSessionBoundPersistsSessionIDAndSkipsContextInjection' -count=1`
591
+
- pass: `go test ./...`
592
+
593
+
- 2026-03-11: fixed Web UI session playback when selecting an existing ACP session from the right sidebar.
594
+
- the active chat view now treats `(threadId, sessionId)` as its render scope instead of refreshing only on `threadId` changes.
595
+
-`loadHistory()` now filters locally persisted turns by each turn's `session_bound` event so the center chat panel replays the selected session's ngent-recorded turns instead of leaving the previous session on screen.
596
+
- session changes reported mid-stream by `session_bound` defer the full chat refresh until the active turn completes, so the live streaming bubble is not destroyed.
597
+
- executed validation:
598
+
- pass: `cd internal/webui/web && npm run build`
599
+
- pass: `go test ./...`
600
+
601
+
- 2026-03-11: fixed Web UI history replay for legacy session threads whose `/history` data lacks per-turn `session_bound` events.
602
+
- session-scoped history filtering now falls back to showing all turns when a thread has no annotated session markers at all, instead of rendering an empty chat pane despite non-empty `/history`.
603
+
- when a thread has exactly one annotated session, the selected session view also keeps older unannotated turns so pre-annotation history is still visible for that same session.
- expose raw unredacted ACP dumps (rejected: conflicts with repository logging/redaction requirements).
717
+
718
+
## ADR-036: Persist thread-level ACP session selection and resume through provider sessions
719
+
720
+
- Status: Accepted
721
+
- Date: 2026-03-11
722
+
- Context:
723
+
- users need to browse an agent's historical ACP sessions and continue a conversation from an existing provider-owned session.
724
+
- hub threads already persist local turn history, but blindly injecting that history into prompts duplicates context once ACP `session/load` has restored the provider's own transcript.
725
+
- the frontend needs paginated session discovery and a lightweight way to switch between "new session" and "existing session" without changing the SQLite schema.
726
+
- Decision:
727
+
- persist the selected ACP session id in `threads.agent_options_json` as `sessionId`.
728
+
- expose `GET /v1/threads/{threadId}/sessions` backed by ACP `session/list`, using a fresh provider instance so sidebar discovery does not disturb cached turn runtimes.
729
+
- extend built-in providers to:
730
+
- load `sessionId` through ACP `session/load` when present.
731
+
- create a fresh session through `session/new` otherwise.
732
+
- report the effective session id back during turn setup so the server can persist it and emit SSE `session_bound`.
733
+
- once `sessionId` is present on a thread, skip local recent-turn prompt injection and rely on ACP session state for continuation.
734
+
- keep Web UI session selection as a thread metadata mutation (`PATCH /v1/threads/{threadId}`) and model the "New session" action as clearing `sessionId`.
735
+
- Consequences:
736
+
- session continuation survives provider restart/server restart when the agent supports ACP `session/load`.
737
+
- right-sidebar session browsing stays paginated (`nextCursor`/`Show more`) and does not require schema changes.
738
+
- local SQLite history remains a hub-local view and is no longer the source of truth for resumed ACP context on bound threads.
739
+
- historical ACP transcript import is deferred and tracked separately as a known limitation.
740
+
- Alternatives considered:
741
+
- import the full ACP transcript from `session/load` into SQLite immediately (rejected: larger behavioral change, requires reliable transcript reconstruction).
742
+
- keep relying on hub prompt injection even after binding to an ACP session (rejected: duplicates already-restored conversation context).
743
+
- add a dedicated sessions table instead of reusing `agentOptions` JSON (rejected: unnecessary schema churn for a single thread-scoped selection value).
744
+
745
+
## ADR-037: Scope Web UI chat playback to the selected ACP session
746
+
747
+
- Status: Accepted
748
+
- Date: 2026-03-11
749
+
- Context:
750
+
- the Web UI session sidebar switches `agentOptions.sessionId` on the active thread without changing `threadId`.
751
+
- local history remains stored per thread, and each turn's effective ACP session is persisted through the `session_bound` event stream.
752
+
- refreshing the chat area only on thread changes leaves stale messages visible after choosing a different session from the sidebar.
753
+
- Decision:
754
+
- treat `(threadId, sessionId)` as the client-side chat render scope.
755
+
- when the active thread's selected session changes outside an active turn, rebuild the chat area and reload history for that scope.
756
+
- filter locally persisted turns by their `session_bound` event so the center chat panel renders only turns recorded for the selected session; an empty `sessionId` shows only unbound turns.
757
+
- Consequences:
758
+
- clicking a session in the sidebar replays that session's ngent-recorded turns instead of keeping the previously rendered session on screen.
759
+
- session changes reported during a live turn do not wipe the streaming bubble; the full refresh is deferred until the turn finishes.
760
+
- transcript content that predates ngent participation is still not imported from the provider and remains covered by KI-021.
761
+
- Alternatives considered:
762
+
- add a session-scoped history endpoint immediately (rejected: larger server contract change while turn events already contain the session discriminator).
763
+
- keep all thread turns visible regardless of selected session (rejected: does not meet the expected session playback behavior).
Copy file name to clipboardExpand all lines: docs/KNOWN_ISSUES.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -189,3 +189,12 @@
189
189
- Follow-up plan:
190
190
- add richer preflight diagnostics for Kimi auth/runtime readiness beyond PATH existence.
191
191
- keep validating future Kimi CLI releases and narrow the fallback path once upstream command syntax stabilizes.
192
+
193
+
- ID: KI-021
194
+
- Title: Resumed ACP sessions do not backfill prior transcript into hub history
195
+
- Status: Open
196
+
- Severity: Medium
197
+
- Affects: threads that select an existing ACP `sessionId` from the Web UI/API
198
+
- Symptom: after choosing an existing session, ngent resumes context through ACP `session/load`, but the center chat/history panel still shows only turns created through ngent itself; earlier provider-owned transcript is not imported into SQLite or rendered in the chat area.
199
+
- Workaround: select the target session before starting new hub turns, and rely on the provider's restored context for continuity even though older messages are not shown locally.
200
+
- Follow-up plan: evaluate reconstructing/importing transcript data from `session/load` replayed `session/update` events into local hub history without duplicating future turns.
0 commit comments