]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
433a3662df2ea60f5b0cde1a289bcb5e958d2648
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import { Plus, File, MessageSquare, Zap, FolderOpen } from '@lucide/svelte';
3 import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
4 import * as Tooltip from '$lib/components/ui/tooltip';
5 import { buttonVariants } from '$lib/components/ui/button';
6 import { cn } from '$lib/components/ui/utils';
7 import {
8 ATTACHMENT_FILE_ITEMS,
9 ATTACHMENT_TOOLTIP_TEXT,
10 TOOLTIP_DELAY_DURATION
11 } from '$lib/constants';
12 import {
13 ChatFormActionAddToolsSubmenu,
14 ChatFormActionAddMcpServersSubmenu,
15 ChatFormActionAddReasoningSubmenu
16 } from '$lib/components/app';
17 import { useAttachmentMenu } from '$lib/hooks/use-attachment-menu.svelte';
18
19 interface Props {
20 class?: string;
21 disabled?: boolean;
22 hasAudioModality?: boolean;
23 hasVideoModality?: boolean;
24 hasVisionModality?: boolean;
25 hasMcpPromptsSupport?: boolean;
26 hasMcpResourcesSupport?: boolean;
27 onFileUpload?: () => void;
28 onSystemPromptClick?: () => void;
29 onMcpPromptClick?: () => void;
30 onMcpSettingsClick?: () => void;
31 onMcpResourcesClick?: () => void;
32 }
33
34 let {
35 class: className = '',
36 disabled = false,
37 hasAudioModality = false,
38 hasVideoModality = false,
39 hasVisionModality = false,
40 hasMcpPromptsSupport = false,
41 hasMcpResourcesSupport = false,
42 onFileUpload,
43 onSystemPromptClick,
44 onMcpPromptClick,
45 onMcpSettingsClick,
46 onMcpResourcesClick
47 }: Props = $props();
48
49 let dropdownOpen = $state(false);
50
51 function handleMcpSettingsClick() {
52 dropdownOpen = false;
53 onMcpSettingsClick?.();
54 }
55
56 const attachmentMenu = useAttachmentMenu(
57 () => ({
58 hasVisionModality,
59 hasAudioModality,
60 hasVideoModality,
61 hasMcpPromptsSupport,
62 hasMcpResourcesSupport
63 }),
64 () => ({ onFileUpload, onSystemPromptClick, onMcpPromptClick, onMcpResourcesClick }),
65 () => {
66 dropdownOpen = false;
67 }
68 );
69 </script>
70
71 <div class="flex items-center gap-1 {className}">
72 <DropdownMenu.Root bind:open={dropdownOpen}>
73 <Tooltip.Root>
74 <Tooltip.Trigger>
75 {#snippet child({ props })}
76 <DropdownMenu.Trigger
77 {...props}
78 class={cn(
79 buttonVariants({ variant: 'secondary' }),
80 'file-upload-button h-8 w-8 cursor-pointer rounded-full p-0'
81 )}
82 {disabled}
83 >
84 <span class="sr-only">{ATTACHMENT_TOOLTIP_TEXT}</span>
85
86 <Plus class="h-4 w-4" />
87 </DropdownMenu.Trigger>
88 {/snippet}
89 </Tooltip.Trigger>
90
91 <Tooltip.Content>
92 <p>{ATTACHMENT_TOOLTIP_TEXT}</p>
93 </Tooltip.Content>
94 </Tooltip.Root>
95
96 <DropdownMenu.Content align="start" class="w-52">
97 <ChatFormActionAddReasoningSubmenu />
98
99 <DropdownMenu.Separator />
100
101 <DropdownMenu.Sub>
102 <DropdownMenu.SubTrigger class="flex cursor-pointer items-center gap-2">
103 <File class="h-4 w-4" />
104
105 <span>Add files</span>
106 </DropdownMenu.SubTrigger>
107
108 <DropdownMenu.SubContent class="w-48">
109 {#each ATTACHMENT_FILE_ITEMS as item (item.id)}
110 {@const enabled = attachmentMenu.isItemEnabled(item.enabledWhen)}
111 {#if enabled}
112 <DropdownMenu.Item
113 class="{item.class ?? ''} flex cursor-pointer items-center gap-2"
114 onclick={() => attachmentMenu.callbacks[item.action]()}
115 >
116 <item.icon class="h-4 w-4" />
117
118 <span>{item.label}</span>
119 </DropdownMenu.Item>
120 {:else if item.disabledTooltip}
121 <Tooltip.Root delayDuration={TOOLTIP_DELAY_DURATION}>
122 <Tooltip.Trigger tabindex={-1}>
123 {#snippet child({ props })}
124 <div {...props} class="cursor-default">
125 <DropdownMenu.Item
126 class="{item.class ?? ''} flex items-center gap-2"
127 disabled
128 >
129 <item.icon class="h-4 w-4" />
130
131 <span>{item.label}</span>
132 </DropdownMenu.Item>
133 </div>
134 {/snippet}
135 </Tooltip.Trigger>
136
137 <Tooltip.Content side="right">
138 <p>{item.disabledTooltip}</p>
139 </Tooltip.Content>
140 </Tooltip.Root>
141 {/if}
142 {/each}
143 </DropdownMenu.SubContent>
144 </DropdownMenu.Sub>
145
146 <DropdownMenu.Item
147 class="flex cursor-pointer items-center gap-2"
148 onclick={onSystemPromptClick}
149 >
150 <MessageSquare class="h-4 w-4" />
151
152 <span>System Message</span>
153 </DropdownMenu.Item>
154
155 <ChatFormActionAddToolsSubmenu />
156
157 <ChatFormActionAddMcpServersSubmenu onMcpSettingsClick={handleMcpSettingsClick} />
158
159 {#if hasMcpPromptsSupport}
160 <DropdownMenu.Separator />
161
162 <DropdownMenu.Item
163 class="flex cursor-pointer items-center gap-2"
164 onclick={onMcpPromptClick}
165 >
166 <Zap class="h-4 w-4" />
167
168 <span>MCP Prompt</span>
169 </DropdownMenu.Item>
170 {/if}
171
172 {#if hasMcpResourcesSupport}
173 <DropdownMenu.Item
174 class="flex cursor-pointer items-center gap-2"
175 onclick={onMcpResourcesClick}
176 >
177 <FolderOpen class="h-4 w-4" />
178
179 <span>MCP Resources</span>
180 </DropdownMenu.Item>
181 {/if}
182 </DropdownMenu.Content>
183 </DropdownMenu.Root>
184 </div>