diff options
| author | Adam Malczewski <[email protected]> | 2026-06-07 16:22:31 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-07 16:22:31 +0900 |
| commit | 17bc0a2cdaeefd4974f785c907d3515a38d45363 (patch) | |
| tree | 1834867d2f0ad5e82fbb985d7f602d8e1dffdb42 /src/core/chunks/reducer.test.ts | |
| parent | 635cb6de7342ac87b27243652b1ad3b3a133d6a4 (diff) | |
| download | dispatch-web-17bc0a2cdaeefd4974f785c907d3515a38d45363.tar.gz dispatch-web-17bc0a2cdaeefd4974f785c907d3515a38d45363.zip | |
feat(chat): group batched tool calls into one DaisyUI list
Consume the backend's new stepId grouping key (wire/transport-contract
0.1.0 -> 0.2.0). foldEvent copies event.stepId onto live tool chunks so
live and replay group identically. New pure selector groupRenderedChunks
(core/chunks) folds a step's 2+ tool calls into one tool-batch group,
pairing each call with its result by toolCallId; single/no-stepId calls
stay as cards. ChatView renders a batch as a DaisyUI list (list-row per
pair). Fixtures updated for the now-required event stepId.
Diffstat (limited to 'src/core/chunks/reducer.test.ts')
| -rw-r--r-- | src/core/chunks/reducer.test.ts | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/core/chunks/reducer.test.ts b/src/core/chunks/reducer.test.ts index b7165e4..7ecc349 100644 --- a/src/core/chunks/reducer.test.ts +++ b/src/core/chunks/reducer.test.ts @@ -1,4 +1,5 @@ import type { + StepId, StoredChunk, TurnDoneEvent, TurnErrorEvent, @@ -39,6 +40,7 @@ const toolCall = ( toolCallId: string, toolName: string, input: unknown, + stepId = "s0", ): TurnToolCallEvent => ({ type: "tool-call", conversationId: "c1", @@ -46,6 +48,7 @@ const toolCall = ( toolCallId, toolName, input, + stepId: stepId as StepId, }); const toolResult = ( @@ -53,6 +56,7 @@ const toolResult = ( toolCallId: string, toolName: string, content: string, + stepId = "s0", ): TurnToolResultEvent => ({ type: "tool-result", conversationId: "c1", @@ -61,6 +65,7 @@ const toolResult = ( toolName, content, isError: false, + stepId: stepId as StepId, }); const usageEvent = (turnId: string, inputTokens: number, outputTokens: number): TurnUsageEvent => ({ @@ -161,15 +166,17 @@ describe("foldEvent — tool-call then tool-result", () => { it("tool-call then tool-result render in order", () => { let s = initialState(); s = foldEvent(s, turnStart("t1")); - s = foldEvent(s, toolCall("t1", "tc1", "bash", { cmd: "ls" })); - s = foldEvent(s, toolResult("t1", "tc1", "bash", "file.txt")); + s = foldEvent(s, toolCall("t1", "tc1", "bash", { cmd: "ls" }, "t1#0")); + s = foldEvent(s, toolResult("t1", "tc1", "bash", "file.txt", "t1#0")); expect(s.provisional).toHaveLength(2); expect(s.provisional[0]?.role).toBe("assistant"); + // foldEvent copies the event's stepId onto the chunk (grouping key). expect(s.provisional[0]?.chunk).toEqual({ type: "tool-call", toolCallId: "tc1", toolName: "bash", input: { cmd: "ls" }, + stepId: "t1#0", }); expect(s.provisional[1]?.role).toBe("tool"); expect(s.provisional[1]?.chunk).toEqual({ @@ -178,6 +185,7 @@ describe("foldEvent — tool-call then tool-result", () => { toolName: "bash", content: "file.txt", isError: false, + stepId: "t1#0", }); }); |
