fix: Distinguish streaming vs incomplete tool calls in UI

This commit is contained in:
Aleksander Grygier 2026-01-12 11:14:53 +01:00
parent aa9054367a
commit 528a560a25
2 changed files with 20 additions and 8 deletions

View File

@ -13,13 +13,14 @@
SyntaxHighlightedCode
} from '$lib/components/app';
import { config } from '$lib/stores/settings.svelte';
import { Wrench, Loader2 } from '@lucide/svelte';
import { Wrench, Loader2, AlertTriangle } from '@lucide/svelte';
import { AgenticSectionType } from '$lib/enums';
import { AGENTIC_TAGS, AGENTIC_REGEX } from '$lib/constants/agentic';
import { formatJsonPretty } from '$lib/utils/formatters';
interface Props {
content: string;
isStreaming?: boolean;
}
interface AgenticSection {
@ -30,7 +31,7 @@
toolResult?: string;
}
let { content }: Props = $props();
let { content, isStreaming = false }: Props = $props();
const sections = $derived(parseAgenticContent(content));
@ -186,19 +187,24 @@
<MarkdownContent content={section.content} />
</div>
{:else if section.type === AgenticSectionType.TOOL_CALL_STREAMING}
{@const streamingIcon = isStreaming ? Loader2 : AlertTriangle}
{@const streamingIconClass = isStreaming ? 'h-4 w-4 animate-spin' : 'h-4 w-4 text-yellow-500'}
{@const streamingSubtitle = isStreaming ? 'streaming...' : 'incomplete'}
<CollapsibleContentBlock
open={isExpanded(index, true)}
class="my-2"
icon={Loader2}
iconClass="h-4 w-4 animate-spin"
icon={streamingIcon}
iconClass={streamingIconClass}
title={section.toolName || 'Tool call'}
subtitle="streaming..."
subtitle={streamingSubtitle}
onToggle={() => toggleExpanded(index, true)}
>
<div class="pt-3">
<div class="my-3 flex items-center gap-2 text-xs text-muted-foreground">
<span>Arguments:</span>
<Loader2 class="h-3 w-3 animate-spin" />
{#if isStreaming}
<Loader2 class="h-3 w-3 animate-spin" />
{/if}
</div>
{#if section.toolArgs}
<SyntaxHighlightedCode
@ -207,10 +213,16 @@
maxHeight="20rem"
class="text-xs"
/>
{:else}
{:else if isStreaming}
<div class="rounded bg-muted/30 p-2 text-xs text-muted-foreground italic">
Receiving arguments...
</div>
{:else}
<div
class="rounded bg-yellow-500/10 p-2 text-xs text-yellow-600 italic dark:text-yellow-400"
>
Response was truncated
</div>
{/if}
</div>
</CollapsibleContentBlock>

View File

@ -183,7 +183,7 @@
{#if showRawOutput}
<pre class="raw-output">{messageContent || ''}</pre>
{:else if isAgenticContent}
<AgenticContent content={messageContent || ''} />
<AgenticContent content={messageContent || ''} isStreaming={isChatStreaming()} />
{:else}
<MarkdownContent content={messageContent || ''} />
{/if}