@dxos/plugin-assistant 0.7.5-main.5ae2ba8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +15 -0
- package/dist/lib/browser/AssistantDialog-TX6YYBUG.mjs +116 -0
- package/dist/lib/browser/AssistantDialog-TX6YYBUG.mjs.map +7 -0
- package/dist/lib/browser/ChatContainer-AT3OAUT3.mjs +33 -0
- package/dist/lib/browser/ChatContainer-AT3OAUT3.mjs.map +7 -0
- package/dist/lib/browser/TemplateContainer-B7MQNUPY.mjs +23 -0
- package/dist/lib/browser/TemplateContainer-B7MQNUPY.mjs.map +7 -0
- package/dist/lib/browser/ai-client-RTCGRKZE.mjs +22 -0
- package/dist/lib/browser/ai-client-RTCGRKZE.mjs.map +7 -0
- package/dist/lib/browser/app-graph-builder-AXAIFOGV.mjs +110 -0
- package/dist/lib/browser/app-graph-builder-AXAIFOGV.mjs.map +7 -0
- package/dist/lib/browser/chunk-EUMPBC4T.mjs +81 -0
- package/dist/lib/browser/chunk-EUMPBC4T.mjs.map +7 -0
- package/dist/lib/browser/chunk-FRIKXDDQ.mjs +162 -0
- package/dist/lib/browser/chunk-FRIKXDDQ.mjs.map +7 -0
- package/dist/lib/browser/chunk-G7B54APW.mjs +106 -0
- package/dist/lib/browser/chunk-G7B54APW.mjs.map +7 -0
- package/dist/lib/browser/chunk-NFVIZS3B.mjs +1804 -0
- package/dist/lib/browser/chunk-NFVIZS3B.mjs.map +7 -0
- package/dist/lib/browser/chunk-NV7SVHMV.mjs +20 -0
- package/dist/lib/browser/chunk-NV7SVHMV.mjs.map +7 -0
- package/dist/lib/browser/chunk-VZ4W6SHE.mjs +15 -0
- package/dist/lib/browser/chunk-VZ4W6SHE.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +218 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/intent-resolver-QRVRZL6K.mjs +44 -0
- package/dist/lib/browser/intent-resolver-QRVRZL6K.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/browser/react-surface-JLXNWOI6.mjs +69 -0
- package/dist/lib/browser/react-surface-JLXNWOI6.mjs.map +7 -0
- package/dist/lib/browser/settings-JTT62IHD.mjs +22 -0
- package/dist/lib/browser/settings-JTT62IHD.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +24 -0
- package/dist/lib/browser/types/index.mjs.map +7 -0
- package/dist/lib/node/AssistantDialog-U4GBPZD6.cjs +140 -0
- package/dist/lib/node/AssistantDialog-U4GBPZD6.cjs.map +7 -0
- package/dist/lib/node/ChatContainer-CVHXNHGA.cjs +61 -0
- package/dist/lib/node/ChatContainer-CVHXNHGA.cjs.map +7 -0
- package/dist/lib/node/TemplateContainer-R4BZZP3E.cjs +53 -0
- package/dist/lib/node/TemplateContainer-R4BZZP3E.cjs.map +7 -0
- package/dist/lib/node/ai-client-YANJEPO3.cjs +38 -0
- package/dist/lib/node/ai-client-YANJEPO3.cjs.map +7 -0
- package/dist/lib/node/app-graph-builder-D7SHQTZS.cjs +122 -0
- package/dist/lib/node/app-graph-builder-D7SHQTZS.cjs.map +7 -0
- package/dist/lib/node/chunk-37GI4NYH.cjs +183 -0
- package/dist/lib/node/chunk-37GI4NYH.cjs.map +7 -0
- package/dist/lib/node/chunk-GNPXCHFT.cjs +44 -0
- package/dist/lib/node/chunk-GNPXCHFT.cjs.map +7 -0
- package/dist/lib/node/chunk-IXJCGW7U.cjs +130 -0
- package/dist/lib/node/chunk-IXJCGW7U.cjs.map +7 -0
- package/dist/lib/node/chunk-NV4TQQSU.cjs +111 -0
- package/dist/lib/node/chunk-NV4TQQSU.cjs.map +7 -0
- package/dist/lib/node/chunk-XUTDR7HI.cjs +1781 -0
- package/dist/lib/node/chunk-XUTDR7HI.cjs.map +7 -0
- package/dist/lib/node/chunk-ZGH6F5YA.cjs +34 -0
- package/dist/lib/node/chunk-ZGH6F5YA.cjs.map +7 -0
- package/dist/lib/node/index.cjs +226 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/intent-resolver-YMMAFVOB.cjs +58 -0
- package/dist/lib/node/intent-resolver-YMMAFVOB.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node/react-surface-BSUZQ3HZ.cjs +85 -0
- package/dist/lib/node/react-surface-BSUZQ3HZ.cjs.map +7 -0
- package/dist/lib/node/settings-4YEO7KXF.cjs +36 -0
- package/dist/lib/node/settings-4YEO7KXF.cjs.map +7 -0
- package/dist/lib/node/types/index.cjs +46 -0
- package/dist/lib/node/types/index.cjs.map +7 -0
- package/dist/lib/node-esm/AssistantDialog-5AT5JAZL.mjs +117 -0
- package/dist/lib/node-esm/AssistantDialog-5AT5JAZL.mjs.map +7 -0
- package/dist/lib/node-esm/ChatContainer-VR766C4M.mjs +34 -0
- package/dist/lib/node-esm/ChatContainer-VR766C4M.mjs.map +7 -0
- package/dist/lib/node-esm/TemplateContainer-WSHTZBB5.mjs +24 -0
- package/dist/lib/node-esm/TemplateContainer-WSHTZBB5.mjs.map +7 -0
- package/dist/lib/node-esm/ai-client-66IBZVCX.mjs +23 -0
- package/dist/lib/node-esm/ai-client-66IBZVCX.mjs.map +7 -0
- package/dist/lib/node-esm/app-graph-builder-H2GC2AZA.mjs +111 -0
- package/dist/lib/node-esm/app-graph-builder-H2GC2AZA.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-77ARTFBA.mjs +16 -0
- package/dist/lib/node-esm/chunk-77ARTFBA.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-7JENJTLB.mjs +1805 -0
- package/dist/lib/node-esm/chunk-7JENJTLB.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-7SV6X6XU.mjs +22 -0
- package/dist/lib/node-esm/chunk-7SV6X6XU.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-AMQMVQJO.mjs +107 -0
- package/dist/lib/node-esm/chunk-AMQMVQJO.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CJ4Y3QW5.mjs +163 -0
- package/dist/lib/node-esm/chunk-CJ4Y3QW5.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-LBQGJE5T.mjs +82 -0
- package/dist/lib/node-esm/chunk-LBQGJE5T.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +219 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/intent-resolver-MR7BOKEW.mjs +45 -0
- package/dist/lib/node-esm/intent-resolver-MR7BOKEW.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/react-surface-IGVYAOGL.mjs +70 -0
- package/dist/lib/node-esm/react-surface-IGVYAOGL.mjs.map +7 -0
- package/dist/lib/node-esm/settings-S7P5RWQI.mjs +23 -0
- package/dist/lib/node-esm/settings-S7P5RWQI.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +25 -0
- package/dist/lib/node-esm/types/index.mjs.map +7 -0
- package/dist/types/src/AssistantPlugin.d.ts +2 -0
- package/dist/types/src/AssistantPlugin.d.ts.map +1 -0
- package/dist/types/src/capabilities/ai-client.d.ts +5 -0
- package/dist/types/src/capabilities/ai-client.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/capabilities.d.ts +5 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +183 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings.d.ts.map +1 -0
- package/dist/types/src/components/AmbientDialog/AmbientDialog.d.ts +7 -0
- package/dist/types/src/components/AmbientDialog/AmbientDialog.d.ts.map +1 -0
- package/dist/types/src/components/AmbientDialog/AmbientDialog.stories.d.ts +8 -0
- package/dist/types/src/components/AmbientDialog/AmbientDialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/AmbientDialog/index.d.ts +2 -0
- package/dist/types/src/components/AmbientDialog/index.d.ts.map +1 -0
- package/dist/types/src/components/AssistantDialog.d.ts +7 -0
- package/dist/types/src/components/AssistantDialog.d.ts.map +1 -0
- package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts +5 -0
- package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts.map +1 -0
- package/dist/types/src/components/AssistantSettings/index.d.ts +2 -0
- package/dist/types/src/components/AssistantSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/ChatContainer.d.ts +7 -0
- package/dist/types/src/components/ChatContainer.d.ts.map +1 -0
- package/dist/types/src/components/Prompt/Prompt.d.ts +17 -0
- package/dist/types/src/components/Prompt/Prompt.d.ts.map +1 -0
- package/dist/types/src/components/Prompt/Prompt.stories.d.ts +9 -0
- package/dist/types/src/components/Prompt/Prompt.stories.d.ts.map +1 -0
- package/dist/types/src/components/Prompt/PromptBar.d.ts +10 -0
- package/dist/types/src/components/Prompt/PromptBar.d.ts.map +1 -0
- package/dist/types/src/components/Prompt/autocomplete.d.ts +21 -0
- package/dist/types/src/components/Prompt/autocomplete.d.ts.map +1 -0
- package/dist/types/src/components/Prompt/index.d.ts +3 -0
- package/dist/types/src/components/Prompt/index.d.ts.map +1 -0
- package/dist/types/src/components/ServiceRegistry/ServiceRegistry.d.ts +5 -0
- package/dist/types/src/components/ServiceRegistry/ServiceRegistry.d.ts.map +1 -0
- package/dist/types/src/components/ServiceRegistry/ServiceRegistry.stories.d.ts +8 -0
- package/dist/types/src/components/ServiceRegistry/ServiceRegistry.stories.d.ts.map +1 -0
- package/dist/types/src/components/ServiceRegistry/index.d.ts +2 -0
- package/dist/types/src/components/ServiceRegistry/index.d.ts.map +1 -0
- package/dist/types/src/components/TemplateContainer.d.ts +7 -0
- package/dist/types/src/components/TemplateContainer.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +12 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts +12 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts +10 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts +8 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/index.d.ts +2 -0
- package/dist/types/src/components/TemplateEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/types.d.ts +18 -0
- package/dist/types/src/components/TemplateEditor/types.d.ts.map +1 -0
- package/dist/types/src/components/Thread/Thread.d.ts +17 -0
- package/dist/types/src/components/Thread/Thread.d.ts.map +1 -0
- package/dist/types/src/components/Thread/Thread.stories.d.ts +11 -0
- package/dist/types/src/components/Thread/Thread.stories.d.ts.map +1 -0
- package/dist/types/src/components/Thread/ThreadContainer.d.ts +10 -0
- package/dist/types/src/components/Thread/ThreadContainer.d.ts.map +1 -0
- package/dist/types/src/components/Thread/ThreadContainer.stories.d.ts +15 -0
- package/dist/types/src/components/Thread/ThreadContainer.stories.d.ts.map +1 -0
- package/dist/types/src/components/Thread/ThreadMessage.d.ts +14 -0
- package/dist/types/src/components/Thread/ThreadMessage.d.ts.map +1 -0
- package/dist/types/src/components/Thread/ToolInvocations.d.ts +13 -0
- package/dist/types/src/components/Thread/ToolInvocations.d.ts.map +1 -0
- package/dist/types/src/components/Thread/index.d.ts +3 -0
- package/dist/types/src/components/Thread/index.d.ts.map +1 -0
- package/dist/types/src/components/Thread/reducer.d.ts +12 -0
- package/dist/types/src/components/Thread/reducer.d.ts.map +1 -0
- package/dist/types/src/components/Toolbox/Toolbox.d.ts +19 -0
- package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -0
- package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts +8 -0
- package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbox/index.d.ts +2 -0
- package/dist/types/src/components/Toolbox/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +17 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/hooks/email.d.ts +4 -0
- package/dist/types/src/hooks/email.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +7 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/invocation-handler.d.ts +5 -0
- package/dist/types/src/hooks/invocation-handler.d.ts.map +1 -0
- package/dist/types/src/hooks/processor.d.ts +76 -0
- package/dist/types/src/hooks/processor.d.ts.map +1 -0
- package/dist/types/src/hooks/processor.test.d.ts +2 -0
- package/dist/types/src/hooks/processor.test.d.ts.map +1 -0
- package/dist/types/src/hooks/useChatProcessor.d.ts +8 -0
- package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -0
- package/dist/types/src/hooks/useLocalTriggerManager.d.ts +3 -0
- package/dist/types/src/hooks/useLocalTriggerManager.d.ts.map +1 -0
- package/dist/types/src/hooks/useMessageQueue.d.ts +41 -0
- package/dist/types/src/hooks/useMessageQueue.d.ts.map +1 -0
- package/dist/types/src/hooks/useServices.d.ts +7 -0
- package/dist/types/src/hooks/useServices.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextInputEvents.d.ts +13 -0
- package/dist/types/src/hooks/useTextInputEvents.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +11 -0
- package/dist/types/src/meta.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +3 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/test-functions.d.ts +3 -0
- package/dist/types/src/testing/test-functions.d.ts.map +1 -0
- package/dist/types/src/testing/test-services.d.ts +5 -0
- package/dist/types/src/testing/test-services.d.ts.map +1 -0
- package/dist/types/src/tools/function.d.ts +5 -0
- package/dist/types/src/tools/function.d.ts.map +1 -0
- package/dist/types/src/tools/index.d.ts +3 -0
- package/dist/types/src/tools/index.d.ts.map +1 -0
- package/dist/types/src/tools/openapi.d.ts +10 -0
- package/dist/types/src/tools/openapi.d.ts.map +1 -0
- package/dist/types/src/tools/openapi.test.d.ts +2 -0
- package/dist/types/src/tools/openapi.test.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +82 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types/chat.d.ts +12 -0
- package/dist/types/src/types/chat.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +5 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/service.d.ts +160 -0
- package/dist/types/src/types/service.d.ts.map +1 -0
- package/dist/types/src/types/template.d.ts +40 -0
- package/dist/types/src/types/template.d.ts.map +1 -0
- package/dist/types/src/types/types.d.ts +37 -0
- package/dist/types/src/types/types.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +120 -0
- package/src/AssistantPlugin.tsx +105 -0
- package/src/capabilities/ai-client.ts +19 -0
- package/src/capabilities/app-graph-builder.ts +100 -0
- package/src/capabilities/capabilities.ts +12 -0
- package/src/capabilities/index.ts +13 -0
- package/src/capabilities/intent-resolver.ts +38 -0
- package/src/capabilities/react-surface.tsx +49 -0
- package/src/capabilities/settings.ts +19 -0
- package/src/components/AmbientDialog/AmbientDialog.stories.tsx +81 -0
- package/src/components/AmbientDialog/AmbientDialog.tsx +103 -0
- package/src/components/AmbientDialog/index.ts +5 -0
- package/src/components/AssistantDialog.tsx +31 -0
- package/src/components/AssistantSettings/AssistantSettings.tsx +49 -0
- package/src/components/AssistantSettings/index.ts +5 -0
- package/src/components/ChatContainer.tsx +27 -0
- package/src/components/Prompt/Prompt.stories.tsx +79 -0
- package/src/components/Prompt/Prompt.tsx +100 -0
- package/src/components/Prompt/PromptBar.tsx +100 -0
- package/src/components/Prompt/autocomplete.ts +212 -0
- package/src/components/Prompt/index.ts +6 -0
- package/src/components/ServiceRegistry/ServiceRegistry.stories.tsx +49 -0
- package/src/components/ServiceRegistry/ServiceRegistry.tsx +76 -0
- package/src/components/ServiceRegistry/index.ts +5 -0
- package/src/components/TemplateContainer.tsx +21 -0
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +83 -0
- package/src/components/TemplateEditor/TemplateEditor.tsx +76 -0
- package/src/components/TemplateEditor/TemplateForm.stories.tsx +65 -0
- package/src/components/TemplateEditor/TemplateForm.tsx +184 -0
- package/src/components/TemplateEditor/index.ts +5 -0
- package/src/components/TemplateEditor/types.tsx +28 -0
- package/src/components/Thread/Thread.stories.tsx +212 -0
- package/src/components/Thread/Thread.tsx +97 -0
- package/src/components/Thread/ThreadContainer.stories.tsx +268 -0
- package/src/components/Thread/ThreadContainer.tsx +79 -0
- package/src/components/Thread/ThreadMessage.tsx +188 -0
- package/src/components/Thread/ToolInvocations.tsx +104 -0
- package/src/components/Thread/index.ts +6 -0
- package/src/components/Thread/reducer.ts +52 -0
- package/src/components/Toolbox/Toolbox.stories.tsx +69 -0
- package/src/components/Toolbox/Toolbox.tsx +115 -0
- package/src/components/Toolbox/index.ts +5 -0
- package/src/components/index.ts +15 -0
- package/src/hooks/email.ts +49 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/invocation-handler.ts +109 -0
- package/src/hooks/processor.test.ts +15 -0
- package/src/hooks/processor.ts +228 -0
- package/src/hooks/useChatProcessor.tsx +80 -0
- package/src/hooks/useLocalTriggerManager.ts +82 -0
- package/src/hooks/useMessageQueue.ts +23 -0
- package/src/hooks/useServices.ts +28 -0
- package/src/hooks/useTextInputEvents.ts +49 -0
- package/src/index.ts +9 -0
- package/src/meta.ts +18 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/test-functions.ts +11 -0
- package/src/testing/test-services.ts +131 -0
- package/src/tools/function.ts +47 -0
- package/src/tools/index.ts +6 -0
- package/src/tools/openapi.test.ts +224 -0
- package/src/tools/openapi.ts +331 -0
- package/src/translations.ts +49 -0
- package/src/types/chat.ts +11 -0
- package/src/types/index.ts +8 -0
- package/src/types/service.ts +102 -0
- package/src/types/template.ts +34 -0
- package/src/types/types.ts +41 -0
- package/src/typings.d.ts +9 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { AIServiceClientImpl } from '@dxos/assistant';
|
|
8
|
+
import { AI_SERVICE_ENDPOINT } from '@dxos/assistant/testing';
|
|
9
|
+
import { log } from '@dxos/log';
|
|
10
|
+
|
|
11
|
+
import { createToolsFromApi, resolveAuthorization } from './openapi';
|
|
12
|
+
import { ChatProcessor } from '../hooks';
|
|
13
|
+
import type { ApiAuthorization } from '../types';
|
|
14
|
+
|
|
15
|
+
describe.skip('openapi', () => {
|
|
16
|
+
describe.skip('mapping', () => {
|
|
17
|
+
test('amadeus flight availabilities', async () => {
|
|
18
|
+
const tools = await createToolsFromApi(FLIGHT_SEARCH_API);
|
|
19
|
+
|
|
20
|
+
log.info('tools', { tools });
|
|
21
|
+
// for (const tool of tools) {
|
|
22
|
+
// const schema = tool.parameters;
|
|
23
|
+
// // log.info('schema', { schema });
|
|
24
|
+
// }
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('amadeus hotel search', async () => {
|
|
28
|
+
const tools = await createToolsFromApi(HOTEL_SEARCH_API);
|
|
29
|
+
log.info('tools', { tools });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('amadeus hotel name autocomplete', async () => {
|
|
33
|
+
const tools = await createToolsFromApi(HOTEL_NAME_AUTOCOMPLETE_API);
|
|
34
|
+
log.info('tools', { tools });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('weather', async () => {
|
|
38
|
+
const tools = await createToolsFromApi(WEATHER_API, { authorization: VISUAL_CROSSING_CREDENTIALS });
|
|
39
|
+
log.info('tools', { tools });
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe.skip('invoke tools', () => {
|
|
44
|
+
test('amadeus hotel name autocomplete', async () => {
|
|
45
|
+
const tools = await createToolsFromApi(HOTEL_NAME_AUTOCOMPLETE_API, { authorization: AMADEUS_AUTH });
|
|
46
|
+
|
|
47
|
+
const result = await tools[0].execute!({
|
|
48
|
+
keyword: 'William Vale Brooklyn',
|
|
49
|
+
subType: ['HOTEL_LEISURE', 'HOTEL_GDS'],
|
|
50
|
+
countryCode: 'US',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
log.info('result', { result });
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('weather API', async () => {
|
|
57
|
+
const tools = await createToolsFromApi(WEATHER_API, { authorization: VISUAL_CROSSING_CREDENTIALS });
|
|
58
|
+
const forecastTool = tools.find((t) => t.name.includes('forecast'));
|
|
59
|
+
|
|
60
|
+
const result = await forecastTool?.execute!({
|
|
61
|
+
locations: 'Brooklyn, NY',
|
|
62
|
+
aggregateHours: '24',
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
log.info('result', { result });
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe.skip('AI uses tools', () => {
|
|
70
|
+
test('amadeus flight availabilities', { timeout: 60_000 }, async () => {
|
|
71
|
+
const tools = await createToolsFromApi(FLIGHT_SEARCH_API, {
|
|
72
|
+
authorization: AMADEUS_AUTH,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const client = new AIServiceClientImpl({
|
|
76
|
+
endpoint: AI_SERVICE_ENDPOINT.LOCAL,
|
|
77
|
+
});
|
|
78
|
+
const processor = new ChatProcessor(client, tools);
|
|
79
|
+
const reply = await processor.request(
|
|
80
|
+
`What is the cheapest flight from New York to Paris? going on ${new Date().toISOString()} and returning after a week. 1 adult traveler`,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
log.info('reply', { reply });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// TODO(dmaretskyi): Doesn't work.
|
|
87
|
+
test('amadeus hotel name autocomplete', { timeout: 60_000 }, async () => {
|
|
88
|
+
const tools = await createToolsFromApi(HOTEL_NAME_AUTOCOMPLETE_API, { authorization: AMADEUS_AUTH });
|
|
89
|
+
|
|
90
|
+
const client = new AIServiceClientImpl({
|
|
91
|
+
endpoint: AI_SERVICE_ENDPOINT.LOCAL,
|
|
92
|
+
});
|
|
93
|
+
const processor = new ChatProcessor(client, tools);
|
|
94
|
+
const reply = await processor.request('Find me the William Wale in Brooklyn New York');
|
|
95
|
+
|
|
96
|
+
log.info('reply', { reply });
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test.only('weather forecast', { timeout: 60_000 }, async () => {
|
|
100
|
+
const tools = await createToolsFromApi(WEATHER_API, {
|
|
101
|
+
authorization: VISUAL_CROSSING_CREDENTIALS,
|
|
102
|
+
instructions: WEATHER_INSTRUCTIONS,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const client = new AIServiceClientImpl({
|
|
106
|
+
endpoint: AI_SERVICE_ENDPOINT.LOCAL,
|
|
107
|
+
});
|
|
108
|
+
const processor = new ChatProcessor(client, tools);
|
|
109
|
+
const reply = await processor.request(
|
|
110
|
+
`Today's date is ${new Date().toISOString().split('T')[0]}. Give me weather forecast for Warsaw for next 5 days.`,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
log.info('reply', { reply });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe.skip('invoke api directly', { timeout: 10_000 }, () => {
|
|
118
|
+
test('amadeus flight availabilities', async () => {
|
|
119
|
+
const response = await fetch('https://test.api.amadeus.com/v1/shopping/availability/flight-availabilities', {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
headers: {
|
|
122
|
+
accept: 'application/vnd.amadeus+json',
|
|
123
|
+
'X-HTTP-Method-Override': 'GET',
|
|
124
|
+
'Content-Type': 'application/vnd.amadeus+json',
|
|
125
|
+
Authorization: await resolveAuthorization(AMADEUS_AUTH),
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
originDestinations: [
|
|
129
|
+
{
|
|
130
|
+
departureDateTime: {
|
|
131
|
+
date: new Date().toISOString().split('T')[0],
|
|
132
|
+
time: new Date().toTimeString().split(' ')[0],
|
|
133
|
+
},
|
|
134
|
+
destinationLocationCode: 'MAD',
|
|
135
|
+
id: '1',
|
|
136
|
+
originLocationCode: 'BOS',
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
sources: ['GDS'],
|
|
140
|
+
travelers: [
|
|
141
|
+
{
|
|
142
|
+
id: '1',
|
|
143
|
+
travelerType: 'ADULT',
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
}),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
log.info('response', { status: response.status, body: await response.json() });
|
|
150
|
+
expect(response.status).toBe(200);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test.only('amadeus hotel name autocomplete', async () => {
|
|
154
|
+
const response = await fetch(
|
|
155
|
+
'https://test.api.amadeus.com/v1/reference-data/locations/hotel?keyword=PARI&subtype=HOTEL_LEISURE,HOTEL_GDS',
|
|
156
|
+
{
|
|
157
|
+
method: 'GET',
|
|
158
|
+
headers: {
|
|
159
|
+
// accept: 'application/vnd.amadeus+json',
|
|
160
|
+
// 'X-HTTP-Method-Override': 'GET',
|
|
161
|
+
Authorization: await resolveAuthorization(AMADEUS_AUTH),
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
log.info('response', { status: response.status, body: await response.json() });
|
|
167
|
+
expect(response.status).toBe(200);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe.skip('rapidapi', () => {
|
|
172
|
+
test('amadeus flight availabilities', async () => {
|
|
173
|
+
const departureDate = new Date().toISOString().split('T')[0];
|
|
174
|
+
const arrivalDate = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
|
|
175
|
+
|
|
176
|
+
const url = `https://amadeus-api2.p.rapidapi.com/serpapi-flight-search?departure_id=PEK&arrival_id=AUS&outbound_date=${departureDate}&return_date=${arrivalDate}¤cy=USD&hl=en`;
|
|
177
|
+
const options = {
|
|
178
|
+
method: 'GET',
|
|
179
|
+
headers: {
|
|
180
|
+
'x-rapidapi-key': RAPID_API_CREDENTIALS.key,
|
|
181
|
+
'x-rapidapi-host': 'amadeus-api2.p.rapidapi.com',
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const response = await fetch(url, options);
|
|
186
|
+
log.info('response', { status: response.status, body: await response.json() });
|
|
187
|
+
expect(response.status).toBe(200);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const FLIGHT_SEARCH_API =
|
|
193
|
+
'https://api.apis.guru/v2/specs/amadeus.com/amadeus-flight-availabilities-search/1.0.2/swagger.json';
|
|
194
|
+
const HOTEL_SEARCH_API = 'https://api.apis.guru/v2/specs/amadeus.com/amadeus-hotel-search/3.0.8/swagger.json';
|
|
195
|
+
const HOTEL_NAME_AUTOCOMPLETE_API =
|
|
196
|
+
'https://api.apis.guru/v2/specs/amadeus.com/amadeus-hotel-name-autocomplete/1.0.3/swagger.json';
|
|
197
|
+
const WEATHER_API = 'https://api.apis.guru/v2/specs/visualcrossing.com/weather/4.6/openapi.json';
|
|
198
|
+
|
|
199
|
+
const WEATHER_INSTRUCTIONS = `
|
|
200
|
+
If the user doesn't provide a date, use today's date.
|
|
201
|
+
Make sure to provide the start and end dates when possible to reduce the amount of data returned.
|
|
202
|
+
Use the tool that accepts the date parameters.
|
|
203
|
+
`;
|
|
204
|
+
|
|
205
|
+
const AMADEUS_AUTH: ApiAuthorization = {
|
|
206
|
+
type: 'oauth',
|
|
207
|
+
clientId: 'BOEnpLd1sMyKjAPGKYeAPFFy60u53QEG',
|
|
208
|
+
clientSecret: 'n4qldSN7usvD57gm',
|
|
209
|
+
tokenUrl: 'https://test.api.amadeus.com/v1/security/oauth2/token',
|
|
210
|
+
grantType: 'client_credentials',
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const VISUAL_CROSSING_CREDENTIALS: ApiAuthorization = {
|
|
214
|
+
type: 'api-key',
|
|
215
|
+
key: 'FDPRVS953KB4GQQLD25GRT975',
|
|
216
|
+
placement: {
|
|
217
|
+
type: 'query',
|
|
218
|
+
name: 'key',
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const RAPID_API_CREDENTIALS = {
|
|
223
|
+
key: '92271b6740msh32fd821d70f050dp16665bjsna69195c9e838',
|
|
224
|
+
};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import jsonpointer from 'jsonpointer';
|
|
6
|
+
import { type OpenAPIV2, type OpenAPIV3_1 } from 'openapi-types';
|
|
7
|
+
|
|
8
|
+
import { ToolResult, type Tool } from '@dxos/artifact';
|
|
9
|
+
import { JsonSchemaType, normalizeSchema, S, toEffectSchema } from '@dxos/echo-schema';
|
|
10
|
+
import { invariant } from '@dxos/invariant';
|
|
11
|
+
import { log } from '@dxos/log';
|
|
12
|
+
import { deepMapValues } from '@dxos/util';
|
|
13
|
+
|
|
14
|
+
import type { ApiAuthorization, ServiceType } from '../types';
|
|
15
|
+
|
|
16
|
+
export type CreateToolsFromApiOptions = {
|
|
17
|
+
authorization?: ApiAuthorization;
|
|
18
|
+
instructions?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const createToolsFromService = async (service: ServiceType): Promise<Tool[]> => {
|
|
22
|
+
invariant(service.interfaces?.length === 1 && service.interfaces[0].kind === 'api');
|
|
23
|
+
const iface = service.interfaces[0];
|
|
24
|
+
invariant(iface.schemaUrl);
|
|
25
|
+
invariant(iface.schemaUrl);
|
|
26
|
+
return createToolsFromApi(iface.schemaUrl, { authorization: iface.authorization });
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const createToolsFromApi = async (url: string, options?: CreateToolsFromApiOptions): Promise<Tool[]> => {
|
|
30
|
+
const res = await fetch(url);
|
|
31
|
+
const spec = (await res.json()) as OpenAPIV2.Document;
|
|
32
|
+
log('spec', { spec });
|
|
33
|
+
|
|
34
|
+
const tools: Tool[] = [];
|
|
35
|
+
for (const [path, pathItem] of Object.entries(spec.paths)) {
|
|
36
|
+
if (typeof pathItem !== 'object') {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// TODO(burdon): ???
|
|
41
|
+
const { ...methods } = pathItem;
|
|
42
|
+
for (const [method, m] of Object.entries(methods)) {
|
|
43
|
+
const methodItem: OpenAPIV2.OperationObject = m as OpenAPIV2.OperationObject;
|
|
44
|
+
log('methodItem', { path, method, methodItem });
|
|
45
|
+
|
|
46
|
+
const parametersResolved: OpenAPIV2.ParameterObject[] =
|
|
47
|
+
methodItem.parameters?.map((parameter: any) => {
|
|
48
|
+
const resolved = resolveJsonSchema(parameter, spec);
|
|
49
|
+
return resolved;
|
|
50
|
+
}) ?? [];
|
|
51
|
+
|
|
52
|
+
const inputSchema: JsonSchemaType = {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: {},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const endpointParameters: OpenAPIV2.ParameterObject[] = [];
|
|
58
|
+
for (const parameter of parametersResolved) {
|
|
59
|
+
log('parameter', { parameter });
|
|
60
|
+
|
|
61
|
+
if (
|
|
62
|
+
options?.authorization?.type === 'api-key' &&
|
|
63
|
+
options.authorization.placement.type === 'query' &&
|
|
64
|
+
parameter.in === 'query' &&
|
|
65
|
+
parameter.name === options.authorization.placement.name
|
|
66
|
+
) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
endpointParameters.push(parameter);
|
|
71
|
+
|
|
72
|
+
if (parameter.schema) {
|
|
73
|
+
inputSchema.properties![parameter.name] = normalizeSchema(parameter.schema);
|
|
74
|
+
} else if (typeof parameter.type === 'string') {
|
|
75
|
+
const { name, in: _in, required, ...schema } = parameter;
|
|
76
|
+
inputSchema.properties![name] = normalizeSchema(schema);
|
|
77
|
+
if (required) {
|
|
78
|
+
inputSchema.required ??= [];
|
|
79
|
+
inputSchema.required!.push(name);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
log('inputSchema', { inputSchema });
|
|
85
|
+
S.validateSync(JsonSchemaType)(inputSchema);
|
|
86
|
+
|
|
87
|
+
const description = methodItem.description ?? methodItem.summary;
|
|
88
|
+
if (!description) {
|
|
89
|
+
log.warn('no description', { path, method });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const endpoint: EndpointDescriptor = {
|
|
94
|
+
document: spec,
|
|
95
|
+
path,
|
|
96
|
+
method,
|
|
97
|
+
parameters: endpointParameters,
|
|
98
|
+
authorization: options?.authorization,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
tools.push({
|
|
102
|
+
name: getToolName(path, method, methodItem),
|
|
103
|
+
description: options?.instructions ? `${options.instructions}\n\n${description}` : description,
|
|
104
|
+
parameters: inputSchema,
|
|
105
|
+
execute: async (input) => {
|
|
106
|
+
const response = await callApiEndpoint(endpoint, input);
|
|
107
|
+
return ToolResult.Success(response);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return tools;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const getToolName = (path: string, method: string, methodItem: OpenAPIV2.OperationObject) => {
|
|
117
|
+
if (methodItem.operationId) {
|
|
118
|
+
return methodItem.operationId;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Generate a name from the path and method.
|
|
122
|
+
let name = `${method.toLowerCase()}_${path.replaceAll(/[{}/]/g, '_')}`;
|
|
123
|
+
while (name.length > MAX_TOOL_NAME_LENGTH) {
|
|
124
|
+
const lengthBefore = name.length;
|
|
125
|
+
|
|
126
|
+
for (const word of GENERIC_WORDS) {
|
|
127
|
+
if (name.includes(word)) {
|
|
128
|
+
name = name.replace(word, '');
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
name = name.replaceAll('__', '_').replace(/_$/, '');
|
|
133
|
+
|
|
134
|
+
const lengthAfter = name.length;
|
|
135
|
+
if (lengthBefore === lengthAfter) {
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
name = name.replaceAll('__', '_').replace(/_$/, '').replace(/^_/, '');
|
|
140
|
+
|
|
141
|
+
return name.slice(0, MAX_TOOL_NAME_LENGTH);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const MAX_TOOL_NAME_LENGTH = 64;
|
|
145
|
+
const GENERIC_WORDS = [
|
|
146
|
+
'services',
|
|
147
|
+
'service',
|
|
148
|
+
'api',
|
|
149
|
+
'rest',
|
|
150
|
+
'endpoint',
|
|
151
|
+
'get',
|
|
152
|
+
'post',
|
|
153
|
+
'put',
|
|
154
|
+
'delete',
|
|
155
|
+
'patch',
|
|
156
|
+
'head',
|
|
157
|
+
'options',
|
|
158
|
+
'trace',
|
|
159
|
+
'service',
|
|
160
|
+
'api',
|
|
161
|
+
'endpoint',
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
type EndpointDescriptor = {
|
|
165
|
+
document: OpenAPIV3_1.Document | OpenAPIV2.Document;
|
|
166
|
+
path: string;
|
|
167
|
+
method: string;
|
|
168
|
+
parameters: OpenAPIV2.ParameterObject[];
|
|
169
|
+
authorization?: ApiAuthorization;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const callApiEndpoint = async (endpoint: EndpointDescriptor, input: any) => {
|
|
173
|
+
log.info('endpoint', { method: endpoint.method, name: endpoint.path, input });
|
|
174
|
+
|
|
175
|
+
let url = getEndpointUrl(endpoint);
|
|
176
|
+
const request: RequestInit = {
|
|
177
|
+
method: endpoint.method,
|
|
178
|
+
headers: {},
|
|
179
|
+
};
|
|
180
|
+
const query = new URLSearchParams();
|
|
181
|
+
let body: any;
|
|
182
|
+
for (const parameter of endpoint.parameters) {
|
|
183
|
+
if (input[parameter.name] === undefined) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
switch (parameter.in) {
|
|
188
|
+
case 'header': {
|
|
189
|
+
if (parameter.example) {
|
|
190
|
+
(request.headers as any)[parameter.name] = parameter.default;
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case 'path': {
|
|
195
|
+
url = url.replace(`{${parameter.name}}`, encodeURIComponent(input[parameter.name]));
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case 'body': {
|
|
199
|
+
const value = input[parameter.name];
|
|
200
|
+
|
|
201
|
+
// Client-side validation
|
|
202
|
+
const effectSchema = toEffectSchema(parameter.schema);
|
|
203
|
+
S.validateSync(effectSchema)(value);
|
|
204
|
+
|
|
205
|
+
if (body) {
|
|
206
|
+
throw new Error(`Duplicate body parameter: ${parameter.name}`);
|
|
207
|
+
}
|
|
208
|
+
body = value;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case 'query': {
|
|
212
|
+
query.set(parameter.name, input[parameter.name]);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (
|
|
219
|
+
(endpoint.authorization?.type === 'api-key' && endpoint.authorization.placement.type === 'authorization-header') ||
|
|
220
|
+
endpoint.authorization?.type === 'oauth'
|
|
221
|
+
) {
|
|
222
|
+
(request.headers as any).Authorization = await resolveAuthorization(endpoint.authorization);
|
|
223
|
+
} else if (endpoint.authorization?.type === 'api-key' && endpoint.authorization.placement.type === 'query') {
|
|
224
|
+
query.set(endpoint.authorization.placement.name, endpoint.authorization.key);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (query.size > 0) {
|
|
228
|
+
url += `?${query.toString()}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (body) {
|
|
232
|
+
request.body = JSON.stringify(body);
|
|
233
|
+
(request.headers as any)['Content-Type'] = 'application/json';
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
log.info('request', { url, request });
|
|
237
|
+
const response = await fetch(url, request);
|
|
238
|
+
|
|
239
|
+
log.info('response', { ok: response.ok, status: response.status, statusText: response.statusText });
|
|
240
|
+
|
|
241
|
+
if (response.ok) {
|
|
242
|
+
const contentType = response.headers.get('Content-Type');
|
|
243
|
+
if (contentType?.includes('application/json')) {
|
|
244
|
+
return await response.json();
|
|
245
|
+
} else {
|
|
246
|
+
return await response.text();
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
if (response.headers.get('Content-Type')?.includes('application/json')) {
|
|
250
|
+
const responseBody = await response.text();
|
|
251
|
+
let error: any;
|
|
252
|
+
try {
|
|
253
|
+
error = JSON.parse(responseBody);
|
|
254
|
+
} catch {
|
|
255
|
+
error = responseBody;
|
|
256
|
+
}
|
|
257
|
+
log.error('error', { error });
|
|
258
|
+
throw new Error(error.message);
|
|
259
|
+
} else {
|
|
260
|
+
const error = await response.text();
|
|
261
|
+
log.error('error', { error });
|
|
262
|
+
throw new Error(error);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const getEndpointUrl = (endpoint: EndpointDescriptor) => {
|
|
268
|
+
let url = '';
|
|
269
|
+
if (isV3_1(endpoint.document) && endpoint.document.servers && endpoint.document.servers.length > 0) {
|
|
270
|
+
url = endpoint.document.servers[0].url;
|
|
271
|
+
} else {
|
|
272
|
+
invariant(!isV3_1(endpoint.document));
|
|
273
|
+
url = `${endpoint.document.schemes?.[0] ?? 'https'}://${endpoint.document.host}`;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!isV3_1(endpoint.document) && endpoint.document.basePath) {
|
|
277
|
+
url += endpoint.document.basePath;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
url += endpoint.path;
|
|
281
|
+
|
|
282
|
+
return url;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
export const resolveAuthorization = async (authorization: ApiAuthorization): Promise<string> => {
|
|
286
|
+
switch (authorization.type) {
|
|
287
|
+
case 'api-key': {
|
|
288
|
+
invariant(authorization.placement.type === 'authorization-header');
|
|
289
|
+
return `Bearer ${authorization.key}`;
|
|
290
|
+
}
|
|
291
|
+
case 'oauth': {
|
|
292
|
+
const response = await fetch(authorization.tokenUrl, {
|
|
293
|
+
method: 'POST',
|
|
294
|
+
headers: {
|
|
295
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
296
|
+
},
|
|
297
|
+
body: `grant_type=${authorization.grantType}&client_id=${authorization.clientId}&client_secret=${authorization.clientSecret}`,
|
|
298
|
+
});
|
|
299
|
+
const data = await response.json();
|
|
300
|
+
return `Bearer ${data.access_token}`;
|
|
301
|
+
}
|
|
302
|
+
default: {
|
|
303
|
+
throw new Error(`Unknown authorization type: ${(authorization as any).type}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Resolves all $ref properties in a JSON schema.
|
|
310
|
+
* Doesn't assume the structure of the schema.
|
|
311
|
+
* The function looks from $ref properties in the schema and resolves them to their values in the base object.
|
|
312
|
+
*/
|
|
313
|
+
const resolveJsonSchema = (schema: any, base: any) => {
|
|
314
|
+
return deepMapValues(schema, (value, recurse) => {
|
|
315
|
+
if (typeof value === 'object' && value !== null && '$ref' in value && typeof value.$ref === 'string') {
|
|
316
|
+
if (value.$ref.startsWith('#')) {
|
|
317
|
+
const resolved = jsonpointer.get(base, value.$ref.slice(1));
|
|
318
|
+
if (resolved) {
|
|
319
|
+
return recurse(resolved);
|
|
320
|
+
} else {
|
|
321
|
+
log.warn('unresolved', { ref: value.$ref, base });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return recurse(value);
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const isV3_1 = (document: OpenAPIV3_1.Document | OpenAPIV2.Document): document is OpenAPIV3_1.Document => {
|
|
330
|
+
return (document as any).openapi === '3.0.1';
|
|
331
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ASSISTANT_PLUGIN } from './meta';
|
|
6
|
+
import { AIChatType, TemplateType } from './types';
|
|
7
|
+
|
|
8
|
+
export default [
|
|
9
|
+
{
|
|
10
|
+
'en-US': {
|
|
11
|
+
[AIChatType.typename]: {
|
|
12
|
+
'typename label': 'AI Chat',
|
|
13
|
+
},
|
|
14
|
+
[TemplateType.typename]: {
|
|
15
|
+
'typename label': 'Template',
|
|
16
|
+
},
|
|
17
|
+
[ASSISTANT_PLUGIN]: {
|
|
18
|
+
'chat title placeholder': 'AI Chat',
|
|
19
|
+
'template title placeholder': 'Template',
|
|
20
|
+
|
|
21
|
+
'open ambient chat label': 'Open AI chat',
|
|
22
|
+
'plugin name': 'Assistant',
|
|
23
|
+
'object placeholder': 'New prompt',
|
|
24
|
+
'create object label': 'Create prompt',
|
|
25
|
+
'create trigger label': 'Create trigger',
|
|
26
|
+
'create stack section label': 'Create prompt',
|
|
27
|
+
'command placeholder': 'Enter slash command...',
|
|
28
|
+
'template placeholder': 'Enter template...',
|
|
29
|
+
'value placeholder': 'Enter value...',
|
|
30
|
+
'select preset template placeholder': 'Select preset',
|
|
31
|
+
'service registry label': 'Service Registry',
|
|
32
|
+
|
|
33
|
+
'assistant dialog title': 'Assistant',
|
|
34
|
+
'open assistant label': 'Open assistant',
|
|
35
|
+
|
|
36
|
+
'chat input placeholder': 'Ask a question...',
|
|
37
|
+
'chat stop': 'Cancel request.',
|
|
38
|
+
|
|
39
|
+
'prompt placeholder': 'Ask a question...',
|
|
40
|
+
'microphone button': 'Click to speak',
|
|
41
|
+
'cancel processing button': 'Stop processing',
|
|
42
|
+
|
|
43
|
+
'settings custom prompts label': 'Custom prompts',
|
|
44
|
+
'settings llm model label': 'LLM model',
|
|
45
|
+
'settings default llm model label': 'Default Model',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Expando, Ref, S, TypedObject } from '@dxos/echo-schema';
|
|
6
|
+
|
|
7
|
+
export class AIChatType extends TypedObject({ typename: 'dxos.org/type/AIChat', version: '0.1.0' })({
|
|
8
|
+
name: S.optional(S.String),
|
|
9
|
+
// TODO(wittjosiah): Should be a ref to a Queue.
|
|
10
|
+
queue: Ref(Expando),
|
|
11
|
+
}) {}
|