summaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/chunks/reducer.test.ts15
-rw-r--r--src/core/chunks/selectors.ts2
-rw-r--r--src/core/chunks/types.ts7
3 files changed, 23 insertions, 1 deletions
diff --git a/src/core/chunks/reducer.test.ts b/src/core/chunks/reducer.test.ts
index 7ecc349..f2f1b75 100644
--- a/src/core/chunks/reducer.test.ts
+++ b/src/core/chunks/reducer.test.ts
@@ -371,6 +371,21 @@ describe("selectChunks", () => {
expect(chunks[0]?.provisional).toBe(true);
expect(chunks[0]?.chunk).toEqual({ type: "text", text: "building..." });
});
+
+ it("marks ONLY the actively-accumulating chunk as streaming", () => {
+ let s = initialState();
+ s = foldEvent(s, turnStart("t1"));
+ // A flushed-but-still-provisional thinking chunk, then a live accumulating one.
+ s = foldEvent(s, reasoningDelta("t1", "first thought"));
+ s = foldEvent(s, toolCall("t1", "tc1", "bash", {})); // flushes the thinking
+ s = foldEvent(s, textDelta("t1", "now writing"));
+ const chunks = selectChunks(s);
+ const thinking = chunks.find((c) => c.chunk.type === "thinking");
+ const accumulating = chunks.find((c) => c.streaming === true);
+ expect(thinking?.streaming).toBeFalsy(); // flushed → not streaming
+ expect(accumulating?.chunk).toEqual({ type: "text", text: "now writing" });
+ expect(chunks.filter((c) => c.streaming === true)).toHaveLength(1);
+ });
});
describe("selectMessages", () => {
diff --git a/src/core/chunks/selectors.ts b/src/core/chunks/selectors.ts
index 8fb832f..839ba65 100644
--- a/src/core/chunks/selectors.ts
+++ b/src/core/chunks/selectors.ts
@@ -18,7 +18,7 @@ export function selectChunks(state: TranscriptState): readonly RenderedChunk[] {
state.accumulating.kind === "text"
? { type: "text", text: state.accumulating.text }
: { type: "thinking", text: state.accumulating.text };
- result.push({ seq: null, role: "assistant", chunk, provisional: true });
+ result.push({ seq: null, role: "assistant", chunk, provisional: true, streaming: true });
}
return result;
}
diff --git a/src/core/chunks/types.ts b/src/core/chunks/types.ts
index 3792445..e031ce3 100644
--- a/src/core/chunks/types.ts
+++ b/src/core/chunks/types.ts
@@ -28,4 +28,11 @@ export interface RenderedChunk {
readonly role: Role;
readonly chunk: Chunk;
readonly provisional: boolean;
+ /**
+ * True only for the single chunk currently being accumulated from live deltas
+ * (the in-flight text/thinking the model is actively generating). Absent/false
+ * once flushed or committed. Lets the UI show a live indicator (e.g. loading
+ * dots on streaming thinking) and drop it the moment generation moves on.
+ */
+ readonly streaming?: boolean;
}