summaryrefslogtreecommitdiffhomepage
path: root/src/core/chunks/reducer.test.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-07 17:14:40 +0900
committerAdam Malczewski <[email protected]>2026-06-07 17:14:40 +0900
commit2e79dd122e5664353e02e0d33715ae8c1041a379 (patch)
tree737822344118e5c1c840b8399a554a1898f07093 /src/core/chunks/reducer.test.ts
parentc8c86dbc3fd23001cca7904791ab539300ec60f4 (diff)
downloaddispatch-web-2e79dd122e5664353e02e0d33715ae8c1041a379.tar.gz
dispatch-web-2e79dd122e5664353e02e0d33715ae8c1041a379.zip
feat(chat): restyle thinking — visible bubble, collapse, title swap, persisted open
Thinking renders inside a visible rounded-card bubble (like tool calls), capped to the same max-w-5xl column as assistant text. Uses a DaisyUI checkbox collapse (no arrow/plus icon) with smooth animation. Title reads "Thinking" + loading-dots while the model is actively generating, then flips to "Thoughts" with no dots once done. Open/closed state persists across the generating→completed→sealed transition via stable ordinal keys (per-conversation isolation via {#key} in App). Added optional streaming flag to RenderedChunk (pure selector, only on the accumulating chunk).
Diffstat (limited to 'src/core/chunks/reducer.test.ts')
-rw-r--r--src/core/chunks/reducer.test.ts15
1 files changed, 15 insertions, 0 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", () => {