diff options
| author | Adam Malczewski <[email protected]> | 2026-10-22 17:51:15 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-10-22 17:51:15 +0900 |
| commit | 75680eac7071c6968eaa5470686ad102a82103db (patch) | |
| tree | fa3a11a100136f102d5ee26404cb2ec5192ce43a /src/core/chunks/reducer.ts | |
| parent | 53686ae6446c5c59928244f65c08150fb564b375 (diff) | |
| download | dispatch-web-75680eac7071c6968eaa5470686ad102a82103db.tar.gz dispatch-web-75680eac7071c6968eaa5470686ad102a82103db.zip | |
feat(chunks): split live thinking at reasoning-end block boundaries
Diffstat (limited to 'src/core/chunks/reducer.ts')
| -rw-r--r-- | src/core/chunks/reducer.ts | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/core/chunks/reducer.ts b/src/core/chunks/reducer.ts index 35bb1bb..71df4dd 100644 --- a/src/core/chunks/reducer.ts +++ b/src/core/chunks/reducer.ts @@ -284,6 +284,8 @@ export function applyHistory( * optimistic echo) so a watcher renders it mid-turn. * - `text-delta` extends the current accumulating TextChunk (or starts one). * - `reasoning-delta` extends the current accumulating ThinkingChunk (or starts one). + * - `reasoning-end` closes the open ThinkingChunk as its own chunk; with none open + * (a redacted/empty block) it appends an empty thinking chunk, mirroring history. * - `tool-call` / `tool-result` / `error` finalize any accumulating chunk and * add a new provisional chunk. * - `steering` appends a user bubble mid-turn (drained from the message queue @@ -415,6 +417,30 @@ function reduceEvent(state: TranscriptState, event: AgentEvent): TranscriptState }; } + case "reasoning-end": { + const acc = state.accumulating; + // Close the open thinking block of this turn: flush it as its own provisional chunk. + if (acc !== null && acc.kind === "thinking" && acc.turnId === event.turnId) { + return { + ...state, + provisional: flushAccumulating(state.provisional, acc), + accumulating: null, + generating: true, + }; + } + // No open thinking (a redacted/empty block with no deltas): history persists an + // EMPTY thinking chunk for it, so mirror that 1:1. + return { + ...state, + provisional: [ + ...flushAccumulating(state.provisional, acc), + { role: "assistant", chunk: { type: "thinking", text: "" }, turnId: event.turnId }, + ], + accumulating: null, + generating: true, + }; + } + case "tool-call": { const provisional = flushAccumulating(state.provisional, state.accumulating); const chunk: Chunk = { @@ -568,6 +594,7 @@ const RETRY_CLEARING_EVENTS: ReadonlySet<AgentEvent["type"]> = new Set([ "turn-start", "text-delta", "reasoning-delta", + "reasoning-end", "tool-call", "tool-result", "error", |
