diff options
| author | Adam Malczewski <[email protected]> | 2026-05-19 21:29:08 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-19 21:29:08 +0900 |
| commit | 0ae805b28b5160b8d9fb43635fa172961f6550cc (patch) | |
| tree | e9fb7cbad0755cd7608ea56012c986a4a47b2aaf /packages/frontend/src/lib/components | |
| parent | de6df4abdd8a6eb9a0217050ce17e0925f04602b (diff) | |
| download | dispatch-0ae805b28b5160b8d9fb43635fa172961f6550cc.tar.gz dispatch-0ae805b28b5160b8d9fb43635fa172961f6550cc.zip | |
feat: inline tool display and thinking/reasoning support
- Tool calls now appear at their stream position within messages (ContentSegment model)
- Added reasoning/thinking display: collapsible <details> block above content
- Set DeepSeek V4 Flash reasoningEffort to max via providerOptions
- ChatMessage.content changed from string to ContentSegment[] (text | tool-call)
- Agent handles AI SDK reasoning events, yields reasoning-delta
- Fixed duplicate key in ChatMessage.svelte each block
Diffstat (limited to 'packages/frontend/src/lib/components')
| -rw-r--r-- | packages/frontend/src/lib/components/ChatMessage.svelte | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/packages/frontend/src/lib/components/ChatMessage.svelte b/packages/frontend/src/lib/components/ChatMessage.svelte index 447bb29..5212790 100644 --- a/packages/frontend/src/lib/components/ChatMessage.svelte +++ b/packages/frontend/src/lib/components/ChatMessage.svelte @@ -9,18 +9,21 @@ const isUser = $derived(message.role === "user"); <div class="chat {isUser ? 'chat-end' : 'chat-start'} mb-2"> <div class="chat-bubble {isUser ? 'chat-bubble-primary' : 'chat-bubble-secondary'} max-w-[80%] break-words"> - {#if message.content} - <span>{message.content}</span> + {#if message.thinking} + <details class="mb-2"> + <summary class="cursor-pointer text-sm text-base-content/60 italic">Thinking...</summary> + <p class="text-sm text-base-content/60 italic mt-1 whitespace-pre-wrap">{message.thinking}</p> + </details> {/if} + {#each message.content as segment, i (segment.type === "tool-call" ? segment.id : i)} + {#if segment.type === "text"} + <span>{segment.text}</span> + {:else if segment.type === "tool-call"} + <ToolCallDisplay toolCall={segment} /> + {/if} + {/each} {#if message.isStreaming} <span class="inline-block w-2 h-4 bg-current animate-pulse ml-0.5 align-middle">▌</span> {/if} - {#if message.toolCalls && message.toolCalls.length > 0} - <div class="mt-2"> - {#each message.toolCalls as toolCall (toolCall.id)} - <ToolCallDisplay {toolCall} /> - {/each} - </div> - {/if} </div> </div> |
