]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
87208e2daa61e0dcab64230eb821a9f02287aaff
[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 { AttachmentType, FileTypeText, MimeTypeAudio, ToolResultKind } from '$lib/enums';
12 import type { DatabaseMessageExtra } from '$lib/types';
13 import {
14 type AgenticSection,
15 classifyToolResult,
16 formatJsonPretty,
17 parseToolResultWithMedia,
18 type ToolResultLine
19 } from '$lib/utils';
20 import { createBase64DataUrl } from '$lib/utils/data-url';
21
22 interface Props {
23 section: AgenticSection;
24 open: boolean;
25 isStreaming: boolean;
26 attachments?: DatabaseMessageExtra[];
27 onToggle?: () => void;
28 }
29
30 let { attachments, isStreaming, onToggle, open, section }: Props = $props();
31
32 const title = $derived(getBuiltinToolUi(section.toolName)?.label ?? section.toolName ?? '');
33 const outputKind = $derived(classifyToolResult(section.toolResult));
34 const parsedLines: ToolResultLine[] = $derived(
35 section.toolResult ? parseToolResultWithMedia(section.toolResult, attachments) : []
36 );
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.media}
109 {#if line.media.type === AttachmentType.AUDIO}
110 {@const audioMimeType = line.media.mimeType ?? MimeTypeAudio.MP3_MPEG}
111 <div class="mt-2 mb-2">
112 <audio controls class="w-full rounded-lg">
113 <source
114 src={createBase64DataUrl(audioMimeType, line.media.base64Data)}
115 type={audioMimeType}
116 />
117 Your browser does not support the audio element.
118 </audio>
119 </div>
120 {:else}
121 <img
122 src={line.media.base64Url}
123 alt={line.media.name}
124 class="mt-2 mb-2 h-auto max-w-full rounded-lg"
125 loading="lazy"
126 />
127 {/if}
128 {/if}
129 {/each}
130 </div>
131 {/if}
132 {:else}
133 <div class="rounded bg-muted/20 p-2 text-xs text-muted-foreground/70 italic">No output</div>
134 {/if}
135 {/if}
136 {/snippet}
137 </ToolCallBlock>