ToolServersModal.svelte 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <script lang="ts">
  2. import { getContext, onMount } from 'svelte';
  3. import { models, config, toolServers, tools } from '$lib/stores';
  4. import { toast } from 'svelte-sonner';
  5. import { deleteSharedChatById, getChatById, shareChatById } from '$lib/apis/chats';
  6. import { copyToClipboard } from '$lib/utils';
  7. import Modal from '../common/Modal.svelte';
  8. import Link from '../icons/Link.svelte';
  9. import Collapsible from '../common/Collapsible.svelte';
  10. export let show = false;
  11. export let selectedToolIds = [];
  12. let selectedTools = [];
  13. $: selectedTools = $tools.filter((tool) => selectedToolIds.includes(tool.id));
  14. const i18n = getContext('i18n');
  15. </script>
  16. <Modal bind:show size="md">
  17. <div>
  18. <div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-0.5">
  19. <div class=" text-lg font-medium self-center">{$i18n.t('Available Tools')}</div>
  20. <button
  21. class="self-center"
  22. on:click={() => {
  23. show = false;
  24. }}
  25. >
  26. <svg
  27. xmlns="http://www.w3.org/2000/svg"
  28. viewBox="0 0 20 20"
  29. fill="currentColor"
  30. class="w-5 h-5"
  31. >
  32. <path
  33. d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
  34. />
  35. </svg>
  36. </button>
  37. </div>
  38. {#if selectedTools.length > 0}
  39. {#if $toolServers.length > 0}
  40. <div class=" flex justify-between dark:text-gray-300 px-5 pb-1">
  41. <div class=" text-base font-medium self-center">{$i18n.t('Tools')}</div>
  42. </div>
  43. {/if}
  44. <div class="px-5 pb-3 w-full flex flex-col justify-center">
  45. <div class=" text-sm dark:text-gray-300 mb-1">
  46. {#each selectedTools as tool}
  47. <Collapsible buttonClassName="w-full mb-0.5">
  48. <div>
  49. <div class="text-sm font-medium dark:text-gray-100 text-gray-800">
  50. {tool?.name}
  51. </div>
  52. {#if tool?.meta?.description}
  53. <div class="text-xs text-gray-500">
  54. {tool?.meta?.description}
  55. </div>
  56. {/if}
  57. </div>
  58. <!-- <div slot="content">
  59. {JSON.stringify(tool, null, 2)}
  60. </div> -->
  61. </Collapsible>
  62. {/each}
  63. </div>
  64. </div>
  65. {/if}
  66. {#if $toolServers.length > 0}
  67. <div class=" flex justify-between dark:text-gray-300 px-5 pb-0.5">
  68. <div class=" text-base font-medium self-center">{$i18n.t('Tool Servers')}</div>
  69. </div>
  70. <div class="px-5 pb-5 w-full flex flex-col justify-center">
  71. <div class=" text-xs text-gray-600 dark:text-gray-300 mb-2">
  72. Open WebUI can use tools provided by any OpenAPI server. <br /><a
  73. class="underline"
  74. href="https://github.com/open-webui/openapi-servers"
  75. target="_blank">Learn more about OpenAPI tool servers.</a
  76. >
  77. </div>
  78. <div class=" text-sm dark:text-gray-300 mb-1">
  79. {#each $toolServers as toolServer}
  80. <Collapsible buttonClassName="w-full" chevron>
  81. <div>
  82. <div class="text-sm font-medium dark:text-gray-100 text-gray-800">
  83. {toolServer?.openapi?.info?.title} - v{toolServer?.openapi?.info?.version}
  84. </div>
  85. <div class="text-xs text-gray-500">
  86. {toolServer?.openapi?.info?.description}
  87. </div>
  88. <div class="text-xs text-gray-500">
  89. {toolServer?.url}
  90. </div>
  91. </div>
  92. <div slot="content">
  93. {#each toolServer?.specs ?? [] as tool_spec}
  94. <div class="my-1">
  95. <div class="font-medium text-gray-800 dark:text-gray-100">
  96. {tool_spec?.name}
  97. </div>
  98. <div>
  99. {tool_spec?.description}
  100. </div>
  101. </div>
  102. {/each}
  103. </div>
  104. </Collapsible>
  105. {/each}
  106. </div>
  107. </div>
  108. {/if}
  109. </div>
  110. </Modal>