]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
acf2de12ac645a4c8b58cb11c763c0b46e90cc3f
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 // Fall-through renderer for tool calls without a dedicated block.
3 // Renders section.toolArgs / section.toolResult directly using the
4 // shared chrome shell.
5
6 import { Loader2 } from '@lucide/svelte';
7 import { MarkdownContent, SyntaxHighlightedCode } from '$lib/components/app';
8 import { FileTypeText, ToolResultKind } from '$lib/enums';
9 import { MAX_HEIGHT_CODE_BLOCK } from '$lib/constants';
10 import {
11 classifyToolResult,
12 formatJsonPretty,
13 parseToolResultWithImages,
14 type AgenticSection,
15 type ToolResultLine
16 } from '$lib/utils';
17 import { getBuiltinToolUi } from '$lib/constants/built-in-tools';
18 import type { DatabaseMessageExtra } from '$lib/types';
19 import ToolCallBlock from './ToolCallBlock.svelte';
20
21 interface Props {
22 section: AgenticSection;
23 open: boolean;
24 isStreaming: boolean;
25 attachments?: DatabaseMessageExtra[];
26 onToggle?: () => void;
27 }
28
29 let { section, open, isStreaming, attachments, onToggle }: Props = $props();
30
31 const title = $derived(getBuiltinToolUi(section.toolName)?.label ?? section.toolName ?? '');
32
33 const parsedLines: ToolResultLine[] = $derived(
34 section.toolResult ? parseToolResultWithImages(section.toolResult, attachments) : []
35 );
36 const outputKind = $derived(classifyToolResult(section.toolResult));
37 </script>
38
39 <ToolCallBlock {section} {open} {isStreaming} meta={null} {title} {onToggle}>
40 {#snippet children(_meta, ctx)}
41 {#if ctx.isStreamingCall}
42 <div class="mb-2 flex items-center gap-2 text-xs text-muted-foreground/70">
43 <span>Input</span>
44 {#if ctx.isStreaming}
45 <Loader2 class="h-3 w-3 animate-spin" />
46 {/if}
47 </div>
48 {#if section.toolArgs}
49 <SyntaxHighlightedCode
50 code={formatJsonPretty(section.toolArgs)}
51 language={FileTypeText.JSON}
52 maxHeight={MAX_HEIGHT_CODE_BLOCK}
53 streaming={ctx.isCodeStreaming}
54 />
55 {:else if ctx.isStreaming}
56 <div class="rounded bg-muted/20 p-2 text-xs text-muted-foreground/70 italic">
57 Receiving arguments...
58 </div>
59 {:else}
60 <div
61 class="rounded bg-yellow-500/10 p-2 text-xs text-yellow-600 italic dark:text-yellow-400"
62 >
63 Response was truncated
64 </div>
65 {/if}
66 {:else}
67 {@const showInput = Boolean(section.toolArgs)}
68 {#if showInput}
69 <div class="mb-1.5 flex items-center gap-2 text-xs text-muted-foreground/70">
70 <span>Input</span>
71 </div>
72 <SyntaxHighlightedCode
73 code={formatJsonPretty(section.toolArgs ?? '')}
74 language={FileTypeText.JSON}
75 maxHeight={MAX_HEIGHT_CODE_BLOCK}
76 streaming={ctx.isCodeStreaming}
77 />
78 {/if}
79 <div
80 class={showInput
81 ? 'mt-4 mb-1.5 flex items-center gap-2 text-xs text-muted-foreground/70'
82 : 'mb-1.5 flex items-center gap-2 text-xs text-muted-foreground/70'}
83 >
84 <span>Output</span>
85 {#if ctx.isPending}
86 <Loader2 class="h-3 w-3 animate-spin" />
87 {/if}
88 </div>
89 {#if ctx.isPending}
90 <div class="rounded bg-muted/20 p-2 text-xs text-muted-foreground/70 italic">
91 Waiting for result...
92 </div>
93 {:else if section.toolResult}
94 {#if outputKind === ToolResultKind.JSON}
95 <SyntaxHighlightedCode
96 code={formatJsonPretty(section.toolResult)}
97 language={FileTypeText.JSON}
98 maxHeight={MAX_HEIGHT_CODE_BLOCK}
99 />
100 {:else if outputKind === ToolResultKind.MARKDOWN}
101 <MarkdownContent content={section.toolResult} {attachments} />
102 {:else}
103 <div class="overflow-auto">
104 {#each parsedLines as line, i (i)}
105 <div class="font-mono text-[11px] leading-relaxed whitespace-pre-wrap">
106 {line.text}
107 </div>
108 {#if line.image}
109 <img
110 src={line.image.base64Url}
111 alt={line.image.name}
112 class="mt-2 mb-2 h-auto max-w-full rounded-lg"
113 loading="lazy"
114 />
115 {/if}
116 {/each}
117 </div>
118 {/if}
119 {:else}
120 <div class="rounded bg-muted/20 p-2 text-xs text-muted-foreground/70 italic">No output</div>
121 {/if}
122 {/if}
123 {/snippet}
124 </ToolCallBlock>