From 17bc0a2cdaeefd4974f785c907d3515a38d45363 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sun, 7 Jun 2026 16:22:31 +0900 Subject: 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. --- src/features/chat/ui/ChatView.svelte | 143 ++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 59 deletions(-) (limited to 'src/features/chat/ui') diff --git a/src/features/chat/ui/ChatView.svelte b/src/features/chat/ui/ChatView.svelte index 0234852..60da571 100644 --- a/src/features/chat/ui/ChatView.svelte +++ b/src/features/chat/ui/ChatView.svelte @@ -1,70 +1,95 @@ -
- {#each chunks as rendered, i (rendered.seq != null ? `c${rendered.seq}` : `p${i}`)} - {#if rendered.role === "user"} - -
-
- {#if rendered.chunk.type === "text"} -

{rendered.chunk.text}

- {/if} -
+{#snippet chunkRow(rendered: RenderedChunk)} + {#if rendered.role === "user"} + +
+
+ {#if rendered.chunk.type === "text"} +

{rendered.chunk.text}

+ {/if}
- {:else if rendered.chunk.type === "tool-call" || rendered.chunk.type === "tool-result"} - -
-
- {#if rendered.chunk.type === "tool-call"} -
- {rendered.chunk.toolName} -
{JSON.stringify(rendered.chunk.input, null, 2)}
-
- {:else} -
- {rendered.chunk.toolName} -
{rendered.chunk.content}
-
- {/if} -
+
+ {:else if rendered.chunk.type === "tool-call" || rendered.chunk.type === "tool-result"} + +
+
+ {#if rendered.chunk.type === "tool-call"} +
+ {rendered.chunk.toolName} +
{JSON.stringify(rendered.chunk.input, null, 2)}
+
+ {:else} +
+ {rendered.chunk.toolName} +
{rendered.chunk.content}
+
+ {/if}
- {:else} - -
-
- {#if rendered.chunk.type === "text"} +
+ {:else} + +
+
+ {#if rendered.chunk.type === "text"} +

{rendered.chunk.text}

+ {:else if rendered.chunk.type === "thinking"} +
+ Thinking

{rendered.chunk.text}

- {:else if rendered.chunk.type === "thinking"} -
- Thinking -

{rendered.chunk.text}

-
- {:else if rendered.chunk.type === "error"} - - {:else if rendered.chunk.type === "system"} -
{rendered.chunk.text}
- {/if} +
+ {:else if rendered.chunk.type === "error"} + + {:else if rendered.chunk.type === "system"} +
{rendered.chunk.text}
+ {/if} +
+
+ {/if} +{/snippet} + +
+ {#each groups as group, i (group.kind === "tool-batch" ? `b${group.stepId}` : group.chunk.seq != null ? `c${group.chunk.seq}` : `p${i}`)} + {#if group.kind === "single"} + {@render chunkRow(group.chunk)} + {:else} + +
+
+
    + {#each group.entries as entry (entry.call.toolCallId)} +
  • +
    + {entry.call.toolName} +
    {JSON.stringify(entry.call.input, null, 2)}
    + {#if entry.result} +
    {entry.result.content}
    + {/if} +
    +
  • + {/each} +
{/if} -- cgit v1.2.3