Repository navigation
feat(desktop): Qoder-style thought/tool activity trail in the conversation - #527
Conversation
Bindy-lbb
left a comment
There was a problem hiding this comment.
Reviewed commit 02727fb. The live SSE path does not yet produce the thought rows shown by the historical adapter, and the advertised 50-entry cap does not apply to tool/agent events. Node 24/macOS also has two stale assertions for the renamed running label; its third failure is the known project-board date fixture described in the PR. Node 24/Ubuntu has an unrelated qoder-engine child-process assertion failure.
…ation Mirror the Qoder client's thinking/execution interaction in the turn thread: - adapter: derive a chronological trail from the persisted event stream. model.delta narration between two trace.activity calls becomes a bounded "thought" item (whitespace-collapsed, 200-char snippet), interleaved with tool/agent activities in event order; tool entries keep their latest status at their first-seen position. A running turn keeps its open narration as a live "thinking" item; a settled turn's trailing narration IS the answer and stays in the output section. Bounded to 50 entries. - TurnThread: merge ProgressTrail and the separate ActivityTrace block into one collapsible trail — running header "Executing" with the total elapsed timer, settled header summarized as tool counts (with a failure-count variant), one line per item with a status word and icon, and the live continuation marker while running. Rows without any trail activity keep the existing milestone steps unchanged. - locales zh/en: thought and tool status copy. - tests: adapter trail cases (interleave, dedupe, live open segment); interaction coverage for interleaved thoughts, failure-count summary and the live thinking item; TurnPanel running-summary copy updated.
02727fb to
afa9639
Compare
|
Rebased onto What changed after the rebase: #523 already carries its own Qoder-style activity line (collapsible header with tool-count summary, live tool naming, elapsed clock), so this PR now only adds the missing half — the thought half:
Note on the previous run's red Node 24 jobs: the failing case was |
… items carry no title TurnTraceActivity.title became optional (thought items carry text instead), so the collapsed-while-running label must fall back to the activity id rather than pass an undefined tool name into the interpolated copy. Caught by the verify job's typecheck, which a local incremental build had skipped.
|
CI note on
I re-ran the two failed jobs rather than changing behaviour. Everything else ( |
… adapter shows Review on #527 found the trail was only half-true. Two fixes: The live SSE projection never opened a narration row: turnStream only folded turn.model.delta into the provisional body text and built the trail from turn.trace.activity alone, so watching a run live showed tool rows while the same run after a history reload also showed the model's narration between them. One 50-entry cap was advertised but only ever applied to thoughts; tool and agent rows were appended unconditionally, so the trail could grow without bound beside it. Both paths now fold through one set of primitives in turns/trail.ts: a delta extends the open narration row, an arriving activity closes it and keeps its first-seen position, and the head is dropped past TRAIL_MAX_ITEMS — the bound the live activity buffer already used, now covering every row type. A settled turn drops its trailing narration because that text is the answer and renders below the trail; a running turn keeps it as the live thinking row. turnStream carries thoughtSeq so row ids stay unique as segments close. Tests: live and persisted folds of the same run must be equal, and the cap must bound interleaved thoughts and steps alike on both paths.
|
Both real findings fixed in 1. The live SSE path now produces the same trail. You were right that I had deferred it — the old PR body even listed it as "a possible follow-up". 2. The cap was not a cap. 3. Stale running-label assertions — fixed before this push ( 4. The project-board date fixture — that was #523's own failure; #523 is now merged into the base, so it is gone from this diff rather than worked around in it. 5. Still technical-only on my side: I have not merged, and the engine/contract surface is untouched ( |
|
Follow-up on the
That advisory was published overnight: the same job on Filed as #528 with the full evidence table. I did not touch dependencies here: fixing it belongs in its own change, and it would bury the trail work in a lockfile diff. For completeness, the two earlier failures on this same commit were also not this diff: attempt 1 was the
|
…lded title A running thought is always the trail tail (an arriving step closes the open narration before it lands), so when narration streams on while a tool is still awaiting its result, the thought is the newest live element and the folded title must read as thinking instead of naming the tool. Check runningThought before runningActivity and cover the coexistence case.
Preflight
main@f2fca7b(feat(desktop): integrate Sept 27 client acceptance #523 merged); head8a23530.Summary
Mirrors the Qoder client's thinking/execution interaction (reference screenshot shared in the DingTalk thread): the turn thread now shows one collapsible chronological trail where the model's narration between tool calls appears as bounded "thought" rows interleaved with tool/agent executions, instead of the previous split between a coarse milestone list and a separate tool-only group.
A run reads the same while it streams and after a history reload: the live SSE projection and the persisted adapter fold the same events through the same primitives.
Change
Renderer (
apps/desktop/renderer)turns/trail.ts(new): the primitives both producers share —thoughtSnippet(single-line, 200-char, prefix-only so re-snippetting a growing segment is idempotent),thoughtItem,putTrailItem(an id keeps its first-seen position and takes the latest state; the head is dropped pastTRAIL_MAX_ITEMS),foldNarration,closeNarration,dropOpenNarration.TRAIL_MAX_ITEMS = 128bounds the whole trail — thoughts, tools and agents alike — and matches the bound the live activity buffer already used.turns/adapter.ts:buildTrail(record)is now the same fold over the persisted events: amodel.deltaextends the open narration row, atrace.activitycloses it and is inserted after it. A running turn keeps its open narration as the live thinking row; a settled turn drops its trailing narration because that text is the answer and already renders in the output section. Presentation-only: no contract, server or engine change.turns/turnStream.ts(was the gap): the live projection previously foldedturn.model.deltainto the provisional body text only and built its trail fromturn.trace.activityalone, so a watched run showed tool rows while the same run after a reload also showed the narration between them. It now folds narrations through the same primitives and carriesthoughtSeqso row ids stay unique as segments close.turns/types.ts:TurnTraceActivitygainskind: "thought"and optionaltext;titlebecomes tool/agent-only.turns/TurnThread.tsx:ProgressTrailand the separateActivityTraceblock merge into one collapsible trail — running header「正在执行中」+ total elapsed timer, settled header summarized as tool counts with a failure-count variant, one line per item with a status word (运行中/已执行/运行失败) and status icon, live continuation marker while running. Rows without any trail activity keep the existing milestone steps unchanged.roleweave-conversation.css:--threadlist variant + thought/state/status styles, same theme-variable conventions.Shared UI (
packages/ui)locales/zh.ts/en.ts:turn.activityRunningExpanded,turn.thoughtDone,turn.thoughtRunning,turn.toolRunning,turn.toolDone,turn.toolFailed,turn.toolsExecutedWithFailures.Evidence
npx tsc -b(full repo)turn-adapter+turn-streamturn-progress-interaction+groups-panel+TurnPanelverifyon8a23530Node 24 / ubuntu-latestfails, but in the infrastructure, not in this diff. All three attempts at8a23530failed on a different non-verify-content cause, and each is reproducible independently of this branch:service-connectionsPAT assertionApp.test.tsx:268:35000ms timeout — the unrelatedcodex/521-desktop-control-facadebranch failed on the same line ten minutes earlier, andmainhas gone red and green the same waysecurity:check(npm audit --audit-level=high) — newly publishedfast-urihigh advisory; 71/71 test files, the production build and 381 electron tests all pass in this same runNode 24 / macos-14, bothUnsigned installers, bothUnpacked staging smokeandLayout parityare green on8a23530.Two tests state the guarantees directly: the live projection and the persisted adapter must produce an equal trail for the same run (closed and open narration), and the cap must bound interleaved thoughts and steps alike on both paths.
Assumptions
trace.activityremains tool/agent only; thoughts are renderer-derived frommodel.delta, so engines need no change and turns recorded before this PR render the same trail retroactively.Acceptance
turn-record.v1.Refs #523, #512, #528