| <script lang="ts"> |
| import { getContext, onMount } from 'svelte'; |
| import { models, config, toolServers, tools, terminalServers } from '$lib/stores'; |
| |
| import { toast } from 'svelte-sonner'; |
| import { deleteSharedChatById, getChatById, shareChatById } from '$lib/apis/chats'; |
| import { copyToClipboard } from '$lib/utils'; |
| |
| import Modal from '../common/Modal.svelte'; |
| import Link from '../icons/Link.svelte'; |
| import Collapsible from '../common/Collapsible.svelte'; |
| import XMark from '$lib/components/icons/XMark.svelte'; |
| |
| export let show = false; |
| export let selectedToolIds = []; |
| |
| let selectedTools = []; |
| |
| $: selectedTools = ($tools ?? []).filter((tool) => selectedToolIds.includes(tool.id)); |
| |
| const i18n = getContext('i18n'); |
| </script> |
|
|
| <Modal bind:show size="md"> |
| <div> |
| <div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-0.5"> |
| <div class=" text-lg font-medium self-center">{$i18n.t('Available Tools')}</div> |
| <button |
| class="self-center" |
| aria-label={$i18n.t('Close')} |
| on:click={() => { |
| show = false; |
| }} |
| > |
| <XMark className={'size-5'} /> |
| </button> |
| </div> |
|
|
| {#if selectedTools.length > 0} |
| {#if $toolServers.length > 0} |
| <div class=" flex justify-between dark:text-gray-300 px-5 pb-1"> |
| <div class=" text-base font-medium self-center">{$i18n.t('Tools')}</div> |
| </div> |
| {/if} |
|
|
| <div class="px-5 pb-3 w-full flex flex-col justify-center"> |
| <div class=" text-sm dark:text-gray-300 mb-1"> |
| {#each selectedTools as tool} |
| <Collapsible buttonClassName="w-full mb-0.5"> |
| <div class="truncate"> |
| <div class="text-sm font-medium dark:text-gray-100 text-gray-800 truncate"> |
| {tool?.name} |
| </div> |
|
|
| {#if tool?.meta?.description} |
| <div class="text-xs text-gray-500"> |
| {tool?.meta?.description} |
| </div> |
| {/if} |
| </div> |
|
|
| |
| |
| |
| </Collapsible> |
| {/each} |
| </div> |
| </div> |
| {/if} |
|
|
| {#if $toolServers.length > 0} |
| <div class=" flex justify-between dark:text-gray-300 px-5 pb-0.5"> |
| <div class=" text-base font-medium self-center">{$i18n.t('Tool Servers')}</div> |
| </div> |
|
|
| <div class="px-5 pb-5 w-full flex flex-col justify-center"> |
| <div class=" text-xs text-gray-600 dark:text-gray-300 mb-2"> |
| {$i18n.t('Omnichat can use tools provided by any OpenAPI server.')} <br /><a |
| class="underline" |
| href="https://github.com/open-webui/openapi-servers" |
| target="_blank">{$i18n.t('Learn more about OpenAPI tool servers.')}</a |
| > |
| </div> |
| <div class=" text-sm dark:text-gray-300 mb-1"> |
| {#each $toolServers as toolServer} |
| <Collapsible buttonClassName="w-full" chevron> |
| <div> |
| <div class="text-sm font-medium dark:text-gray-100 text-gray-800"> |
| {toolServer?.openapi?.info?.title} - v{toolServer?.openapi?.info?.version} |
| </div> |
|
|
| <div class="text-xs text-gray-500"> |
| {toolServer?.openapi?.info?.description} |
| </div> |
|
|
| <div class="text-xs text-gray-500"> |
| {toolServer?.url} |
| </div> |
| </div> |
|
|
| <div slot="content"> |
| {#each toolServer?.specs ?? [] as tool_spec} |
| <div class="my-1"> |
| <div class="font-medium text-gray-800 dark:text-gray-100"> |
| {tool_spec?.name} |
| </div> |
|
|
| <div> |
| {tool_spec?.description} |
| </div> |
| </div> |
| {/each} |
| </div> |
| </Collapsible> |
| {/each} |
| </div> |
| </div> |
| {/if} |
| </div> |
| </Modal> |
|
|