summaryrefslogtreecommitdiffhomepage
path: root/src/core/chunks/reducer.test.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-07 16:22:31 +0900
committerAdam Malczewski <[email protected]>2026-06-07 16:22:31 +0900
commit17bc0a2cdaeefd4974f785c907d3515a38d45363 (patch)
tree1834867d2f0ad5e82fbb985d7f602d8e1dffdb42 /src/core/chunks/reducer.test.ts
parent635cb6de7342ac87b27243652b1ad3b3a133d6a4 (diff)
downloaddispatch-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.ts12
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",
});
});