|
19 | 19 | import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte'; |
20 | 20 | import Photo from '$lib/components/icons/Photo.svelte'; |
21 | 21 | import Terminal from '$lib/components/icons/Terminal.svelte'; |
22 | | - import ChevronRight from '$lib/components/icons/ChevronRight.svelte'; |
23 | | - import ChevronLeft from '$lib/components/icons/ChevronLeft.svelte'; |
24 | 22 |
|
25 | 23 | const i18n = getContext('i18n'); |
26 | 24 |
|
|
62 | 60 | if ($_tools === null) { |
63 | 61 | await _tools.set(await getTools(localStorage.token)); |
64 | 62 | } |
| 63 | + console.log('------ Tools: ------', localStorage.token, $_tools); |
65 | 64 |
|
66 | 65 | if ($_tools) { |
67 | 66 | tools = $_tools.reduce((a, tool, i, arr) => { |
|
116 | 115 | <div in:fly={{ x: -20, duration: 150 }}> |
117 | 116 | {#if tools} |
118 | 117 | {#if Object.keys(tools).length > 0} |
119 | | - <button |
120 | | - class="flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50" |
121 | | - on:click={() => { |
122 | | - tab = 'tools'; |
123 | | - }} |
124 | | - > |
125 | | - <Wrench /> |
| 118 | + {#each Object.keys(tools) as toolId} |
| 119 | + <button |
| 120 | + class="relative flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50" |
| 121 | + on:click={async (e) => { |
| 122 | + if (!(tools[toolId]?.authenticated ?? true)) { |
| 123 | + e.preventDefault(); |
| 124 | + |
| 125 | + let parts = toolId.split(':'); |
| 126 | + let serverId = parts?.at(-1) ?? toolId; |
126 | 127 |
|
127 | | - <div class="flex items-center w-full justify-between"> |
128 | | - <div class=" line-clamp-1"> |
129 | | - {$i18n.t('Tools')} |
130 | | - <span class="ml-0.5 text-gray-500">{Object.keys(tools).length}</span> |
| 128 | + const authUrl = getOAuthClientAuthorizationUrl(serverId, 'mcp'); |
| 129 | + window.open(authUrl, '_self', 'noopener'); |
| 130 | + } else { |
| 131 | + tools[toolId].enabled = !tools[toolId].enabled; |
| 132 | + |
| 133 | + const state = tools[toolId].enabled; |
| 134 | + await tick(); |
| 135 | + |
| 136 | + if (state) { |
| 137 | + selectedToolIds = [...selectedToolIds, toolId]; |
| 138 | + } else { |
| 139 | + selectedToolIds = selectedToolIds.filter((id) => id !== toolId); |
| 140 | + } |
| 141 | + } |
| 142 | + }} |
| 143 | + > |
| 144 | + {#if !(tools[toolId]?.authenticated ?? true)} |
| 145 | + <!-- make it slighly darker and not clickable --> |
| 146 | + <div class="absolute inset-0 opacity-50 rounded-xl cursor-pointer z-10" /> |
| 147 | + {/if} |
| 148 | + <div class="flex-1 truncate"> |
| 149 | + <div class="flex flex-1 gap-2 items-center"> |
| 150 | + <Tooltip content={tools[toolId]?.name ?? ''} placement="top"> |
| 151 | + <div class="shrink-0"> |
| 152 | + <Wrench /> |
| 153 | + </div> |
| 154 | + </Tooltip> |
| 155 | + <Tooltip content={tools[toolId]?.description ?? ''} placement="top-start"> |
| 156 | + <div class=" truncate">{tools[toolId].name}</div> |
| 157 | + </Tooltip> |
| 158 | + </div> |
131 | 159 | </div> |
132 | 160 |
|
133 | | - <div class="text-gray-500"> |
134 | | - <ChevronRight /> |
| 161 | + {#if tools[toolId]?.has_user_valves} |
| 162 | + <div class=" shrink-0"> |
| 163 | + <Tooltip content={$i18n.t('Valves')}> |
| 164 | + <button |
| 165 | + class="self-center w-fit text-sm text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition rounded-full" |
| 166 | + type="button" |
| 167 | + on:click={(e) => { |
| 168 | + e.stopPropagation(); |
| 169 | + e.preventDefault(); |
| 170 | + onShowValves({ |
| 171 | + type: 'tool', |
| 172 | + id: toolId |
| 173 | + }); |
| 174 | + }} |
| 175 | + > |
| 176 | + <Knobs /> |
| 177 | + </button> |
| 178 | + </Tooltip> |
| 179 | + </div> |
| 180 | + {/if} |
| 181 | + |
| 182 | + <div class=" shrink-0"> |
| 183 | + <Switch state={tools[toolId].enabled} /> |
135 | 184 | </div> |
136 | | - </div> |
137 | | - </button> |
| 185 | + </button> |
| 186 | + {/each} |
138 | 187 | {/if} |
139 | 188 | {:else} |
140 | 189 | <div class="py-4"> |
|
310 | 359 | </Tooltip> |
311 | 360 | {/if} |
312 | 361 | </div> |
313 | | - {:else if tab === 'tools' && tools} |
314 | | - <div in:fly={{ x: 20, duration: 150 }}> |
315 | | - <button |
316 | | - class="flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50" |
317 | | - on:click={() => { |
318 | | - tab = ''; |
319 | | - }} |
320 | | - > |
321 | | - <ChevronLeft /> |
322 | | - |
323 | | - <div class="flex items-center w-full justify-between"> |
324 | | - <div> |
325 | | - {$i18n.t('Tools')} |
326 | | - <span class="ml-0.5 text-gray-500">{Object.keys(tools).length}</span> |
327 | | - </div> |
328 | | - </div> |
329 | | - </button> |
330 | | - |
331 | | - {#each Object.keys(tools) as toolId} |
332 | | - <button |
333 | | - class="relative flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50" |
334 | | - on:click={async (e) => { |
335 | | - if (!(tools[toolId]?.authenticated ?? true)) { |
336 | | - e.preventDefault(); |
337 | | - |
338 | | - let parts = toolId.split(':'); |
339 | | - let serverId = parts?.at(-1) ?? toolId; |
340 | | - |
341 | | - const authUrl = getOAuthClientAuthorizationUrl(serverId, 'mcp'); |
342 | | - window.open(authUrl, '_self', 'noopener'); |
343 | | - } else { |
344 | | - tools[toolId].enabled = !tools[toolId].enabled; |
345 | | - |
346 | | - const state = tools[toolId].enabled; |
347 | | - await tick(); |
348 | | - |
349 | | - if (state) { |
350 | | - selectedToolIds = [...selectedToolIds, toolId]; |
351 | | - } else { |
352 | | - selectedToolIds = selectedToolIds.filter((id) => id !== toolId); |
353 | | - } |
354 | | - } |
355 | | - }} |
356 | | - > |
357 | | - {#if !(tools[toolId]?.authenticated ?? true)} |
358 | | - <!-- make it slighly darker and not clickable --> |
359 | | - <div class="absolute inset-0 opacity-50 rounded-xl cursor-pointer z-10" /> |
360 | | - {/if} |
361 | | - <div class="flex-1 truncate"> |
362 | | - <div class="flex flex-1 gap-2 items-center"> |
363 | | - <Tooltip content={tools[toolId]?.name ?? ''} placement="top"> |
364 | | - <div class="shrink-0"> |
365 | | - <Wrench /> |
366 | | - </div> |
367 | | - </Tooltip> |
368 | | - <Tooltip content={tools[toolId]?.description ?? ''} placement="top-start"> |
369 | | - <div class=" truncate">{tools[toolId].name}</div> |
370 | | - </Tooltip> |
371 | | - </div> |
372 | | - </div> |
373 | | - |
374 | | - {#if tools[toolId]?.has_user_valves} |
375 | | - <div class=" shrink-0"> |
376 | | - <Tooltip content={$i18n.t('Valves')}> |
377 | | - <button |
378 | | - class="self-center w-fit text-sm text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition rounded-full" |
379 | | - type="button" |
380 | | - on:click={(e) => { |
381 | | - e.stopPropagation(); |
382 | | - e.preventDefault(); |
383 | | - onShowValves({ |
384 | | - type: 'tool', |
385 | | - id: toolId |
386 | | - }); |
387 | | - }} |
388 | | - > |
389 | | - <Knobs /> |
390 | | - </button> |
391 | | - </Tooltip> |
392 | | - </div> |
393 | | - {/if} |
394 | | - |
395 | | - <div class=" shrink-0"> |
396 | | - <Switch state={tools[toolId].enabled} /> |
397 | | - </div> |
398 | | - </button> |
399 | | - {/each} |
400 | | - </div> |
401 | 362 | {/if} |
402 | 363 | </DropdownMenu.Content> |
403 | 364 | </div> |
|
0 commit comments