]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
5ca5973668cc4d6909a4c1f4f3172f3da17ce4f5
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import type { Snippet } from 'svelte';
3 import * as Tooltip from '$lib/components/ui/tooltip';
4 import * as Sheet from '$lib/components/ui/sheet';
5 import { TOOLTIP_DELAY_DURATION } from '$lib/constants';
6 import {
7 ATTACHMENT_FILE_ITEMS,
8 ATTACHMENT_EXTRA_ITEMS,
9 ATTACHMENT_MCP_ITEMS
10 } from '$lib/constants/attachment-menu';
11 import { McpLogo } from '$lib/components/app';
12 import { useAttachmentMenu } from '$lib/hooks/use-attachment-menu.svelte';
13 import { AttachmentMenuItemId } from '$lib/enums';
14 import { PencilRuler } from '@lucide/svelte';
15 import { ROUTES, SETTINGS_SECTION_SLUGS } from '$lib/constants/routes';
16 import { RouterService } from '$lib/services/router.service';
17
18 interface Props {
19 class?: string;
20 disabled?: boolean;
21 hasAudioModality?: boolean;
22 hasVideoModality?: boolean;
23 hasVisionModality?: boolean;
24 hasMcpPromptsSupport?: boolean;
25 hasMcpResourcesSupport?: boolean;
26 onFileUpload?: () => void;
27 onSystemPromptClick?: () => void;
28 onMcpPromptClick?: () => void;
29 onMcpResourcesClick?: () => void;
30 trigger: Snippet<[{ disabled: boolean; onclick?: () => void }]>;
31 }
32
33 let {
34 class: className = '',
35 disabled = false,
36 hasAudioModality = false,
37 hasVisionModality = false,
38 hasVideoModality = false,
39 hasMcpPromptsSupport = false,
40 hasMcpResourcesSupport = false,
41 onFileUpload,
42 onSystemPromptClick,
43 onMcpPromptClick,
44 onMcpResourcesClick,
45 trigger
46 }: Props = $props();
47
48 let sheetOpen = $state(false);
49
50 const attachmentMenu = useAttachmentMenu(
51 () => ({
52 hasVisionModality,
53 hasAudioModality,
54 hasVideoModality,
55 hasMcpPromptsSupport,
56 hasMcpResourcesSupport
57 }),
58 () => ({ onFileUpload, onSystemPromptClick, onMcpPromptClick, onMcpResourcesClick }),
59 () => {
60 sheetOpen = false;
61 }
62 );
63
64 const sheetItemClass =
65 'flex w-full items-center gap-3 rounded-md px-3 py-2.5 text-left text-sm transition-colors hover:bg-accent active:bg-accent disabled:cursor-not-allowed disabled:opacity-50';
66 </script>
67
68 <div class="flex items-center gap-1 {className}">
69 <Sheet.Root bind:open={sheetOpen}>
70 {@render trigger({ disabled, onclick: () => (sheetOpen = true) })}
71 <!-- <ChatFormActionAddButton {disabled} onclick={() => (sheetOpen = true)} /> -->
72
73 <Sheet.Content side="bottom" class="max-h-[85vh] gap-0 overflow-y-auto">
74 <Sheet.Header>
75 <Sheet.Title>Add to chat</Sheet.Title>
76
77 <Sheet.Description class="sr-only">
78 Add files, system prompt or configure MCP servers
79 </Sheet.Description>
80 </Sheet.Header>
81
82 <div class="flex flex-col gap-1 px-1.5 pb-2">
83 {#each ATTACHMENT_FILE_ITEMS as item (item.id)}
84 {@const enabled = attachmentMenu.isItemEnabled(item.enabledWhen)}
85 {#if enabled}
86 <button
87 type="button"
88 class={sheetItemClass}
89 onclick={() => attachmentMenu.callbacks[item.action]()}
90 >
91 <item.icon class="h-4 w-4 shrink-0" />
92
93 <span>{item.label}</span>
94 </button>
95 {:else if item.disabledTooltip}
96 <Tooltip.Root delayDuration={TOOLTIP_DELAY_DURATION}>
97 <Tooltip.Trigger>
98 <button type="button" class={sheetItemClass} disabled>
99 <item.icon class="h-4 w-4 shrink-0" />
100
101 <span>{item.label}</span>
102 </button>
103 </Tooltip.Trigger>
104
105 <Tooltip.Content side="right">
106 <p>{item.disabledTooltip}</p>
107 </Tooltip.Content>
108 </Tooltip.Root>
109 {/if}
110 {/each}
111
112 {#if !attachmentMenu.isItemEnabled('hasVisionModality')}
113 {@const pdfItem = ATTACHMENT_FILE_ITEMS.find((i) => i.id === AttachmentMenuItemId.PDF)}
114 {#if pdfItem}
115 <Tooltip.Root delayDuration={TOOLTIP_DELAY_DURATION}>
116 <Tooltip.Trigger>
117 <button
118 type="button"
119 class={sheetItemClass}
120 onclick={() => attachmentMenu.callbacks[pdfItem.action]()}
121 >
122 <pdfItem.icon class="h-4 w-4 shrink-0" />
123
124 <span>{pdfItem.label}</span>
125 </button>
126 </Tooltip.Trigger>
127
128 <Tooltip.Content side="right">
129 <p>PDFs will be converted to text. Image-based PDFs may not work properly.</p>
130 </Tooltip.Content>
131 </Tooltip.Root>
132 {/if}
133 {/if}
134
135 {#each ATTACHMENT_EXTRA_ITEMS as item (item.id)}
136 {#if item.id === AttachmentMenuItemId.SYSTEM_MESSAGE}
137 <Tooltip.Root delayDuration={TOOLTIP_DELAY_DURATION}>
138 <Tooltip.Trigger>
139 <button
140 type="button"
141 class={sheetItemClass}
142 onclick={() => attachmentMenu.callbacks[item.action]()}
143 >
144 <item.icon class="h-4 w-4 shrink-0" />
145
146 <span>{item.label}</span>
147 </button>
148 </Tooltip.Trigger>
149
150 <Tooltip.Content side="right">
151 <p>{attachmentMenu.getSystemMessageTooltip()}</p>
152 </Tooltip.Content>
153 </Tooltip.Root>
154 {/if}
155 {/each}
156
157 <div class="my-2 border-t"></div>
158
159 <a href={ROUTES.MCP_SERVERS} class="flex items-center gap-3 px-3 py-2">
160 <McpLogo class="inline h-4 w-4" />
161
162 <span class="text-sm">MCP Servers</span>
163 </a>
164
165 <a
166 href={RouterService.settings(SETTINGS_SECTION_SLUGS.TOOLS)}
167 class="flex items-center gap-3 px-3 py-2"
168 >
169 <PencilRuler class="inline h-4 w-4" />
170
171 <span class="text-sm">Tools</span>
172 </a>
173
174 {#each ATTACHMENT_MCP_ITEMS as item (item.id)}
175 {#if attachmentMenu.isItemVisible(item.visibleWhen)}
176 <button
177 type="button"
178 class={sheetItemClass}
179 onclick={() => attachmentMenu.callbacks[item.action]()}
180 >
181 <item.icon class="h-4 w-4 shrink-0" />
182
183 <span>{item.label}</span>
184 </button>
185 {/if}
186 {/each}
187 </div>
188 </Sheet.Content>
189 </Sheet.Root>
190 </div>