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