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