skybridge 0.0.0-dev.a955b71 → 0.0.0-dev.a961973
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/README.md +11 -17
- package/dist/cli/build-helpers.d.ts +6 -2
- package/dist/cli/build-helpers.js +39 -14
- package/dist/cli/build-helpers.js.map +1 -1
- package/dist/cli/build-helpers.test.js +73 -5
- package/dist/cli/build-helpers.test.js.map +1 -1
- package/dist/cli/build-steps.d.ts +2 -0
- package/dist/cli/build-steps.js +73 -0
- package/dist/cli/build-steps.js.map +1 -0
- package/dist/cli/build-steps.test.js +52 -0
- package/dist/cli/build-steps.test.js.map +1 -0
- package/dist/cli/detect-port.js +0 -1
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/header.d.ts +1 -1
- package/dist/cli/resolve-skybridge-config.d.ts +5 -0
- package/dist/cli/{resolve-views-dir.js → resolve-skybridge-config.js} +4 -3
- package/dist/cli/resolve-skybridge-config.js.map +1 -0
- package/dist/cli/run-plain.d.ts +18 -0
- package/dist/cli/run-plain.js +90 -0
- package/dist/cli/run-plain.js.map +1 -0
- package/dist/cli/use-execute-steps.d.ts +1 -1
- package/dist/cli/use-nodemon.d.ts +25 -1
- package/dist/cli/use-nodemon.js +96 -63
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-typescript-check.d.ts +8 -2
- package/dist/cli/use-typescript-check.js +70 -67
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.d.ts +0 -2
- package/dist/commands/build.js +2 -61
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +38 -6
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/start.js.map +1 -1
- package/dist/context-warnings.d.ts +5 -0
- package/dist/context-warnings.js +31 -0
- package/dist/context-warnings.js.map +1 -0
- package/dist/context-warnings.test.js +28 -0
- package/dist/context-warnings.test.js.map +1 -0
- package/dist/server/app.d.ts +194 -0
- package/dist/server/app.js +266 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/app.test.js +97 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/auth/discovery.d.ts +2 -1
- package/dist/server/auth/discovery.js +2 -2
- package/dist/server/auth/discovery.js.map +1 -1
- package/dist/server/auth/index.d.ts +35 -5
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/auth/providers/auth0.d.ts +25 -3
- package/dist/server/auth/providers/auth0.js +13 -8
- package/dist/server/auth/providers/auth0.js.map +1 -1
- package/dist/server/auth/providers/auth0.test.js +5 -3
- package/dist/server/auth/providers/auth0.test.js.map +1 -1
- package/dist/server/auth/providers/authplane.d.ts +49 -0
- package/dist/server/auth/providers/authplane.js +57 -0
- package/dist/server/auth/providers/authplane.js.map +1 -0
- package/dist/server/auth/providers/authplane.test.js +143 -0
- package/dist/server/auth/providers/authplane.test.js.map +1 -0
- package/dist/server/auth/providers/clerk.d.ts +40 -3
- package/dist/server/auth/providers/clerk.js +4 -1
- package/dist/server/auth/providers/clerk.js.map +1 -1
- package/dist/server/auth/providers/clerk.test.js +5 -3
- package/dist/server/auth/providers/clerk.test.js.map +1 -1
- package/dist/server/auth/providers/custom.d.ts +20 -4
- package/dist/server/auth/providers/custom.js +33 -11
- package/dist/server/auth/providers/custom.js.map +1 -1
- package/dist/server/auth/providers/custom.test.js +71 -17
- package/dist/server/auth/providers/custom.test.js.map +1 -1
- package/dist/server/auth/providers/descope.d.ts +32 -3
- package/dist/server/auth/providers/descope.js +13 -2
- package/dist/server/auth/providers/descope.js.map +1 -1
- package/dist/server/auth/providers/descope.test.js +42 -17
- package/dist/server/auth/providers/descope.test.js.map +1 -1
- package/dist/server/auth/providers/stytch.d.ts +16 -3
- package/dist/server/auth/providers/stytch.js +4 -1
- package/dist/server/auth/providers/stytch.js.map +1 -1
- package/dist/server/auth/providers/verify-spy.d.ts +12 -0
- package/dist/server/auth/providers/verify-spy.js +21 -0
- package/dist/server/auth/providers/verify-spy.js.map +1 -0
- package/dist/server/auth/providers/workos.d.ts +25 -3
- package/dist/server/auth/providers/workos.js +4 -1
- package/dist/server/auth/providers/workos.js.map +1 -1
- package/dist/server/auth/security-schemes.d.ts +23 -0
- package/dist/server/auth/security-schemes.js +64 -0
- package/dist/server/auth/security-schemes.js.map +1 -0
- package/dist/server/auth/security-schemes.test.d.ts +1 -0
- package/dist/server/auth/security-schemes.test.js +99 -0
- package/dist/server/auth/security-schemes.test.js.map +1 -0
- package/dist/server/auth/setup.d.ts +3 -1
- package/dist/server/auth/setup.js +66 -26
- package/dist/server/auth/setup.js.map +1 -1
- package/dist/server/auth/setup.test.js +349 -20
- package/dist/server/auth/setup.test.js.map +1 -1
- package/dist/server/auth/verify.d.ts +37 -3
- package/dist/server/auth/verify.js +27 -3
- package/dist/server/auth/verify.js.map +1 -1
- package/dist/server/auth/verify.test.js +49 -0
- package/dist/server/auth/verify.test.js.map +1 -1
- package/dist/server/auth-extra.test-d.js +130 -0
- package/dist/server/auth-extra.test-d.js.map +1 -0
- package/dist/server/auth.d.ts +43 -6
- package/dist/server/auth.js +4 -5
- package/dist/server/auth.js.map +1 -1
- package/dist/server/build-manifest.test.js +7 -6
- package/dist/server/build-manifest.test.js.map +1 -1
- package/dist/server/content-helpers.d.ts +1 -1
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/express.d.ts +23 -3
- package/dist/server/express.js +38 -32
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +220 -103
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/file-ref.d.ts +1 -1
- package/dist/server/file-ref.js +1 -1
- package/dist/server/file-ref.js.map +1 -1
- package/dist/server/host.d.ts +2 -0
- package/dist/server/host.js +11 -0
- package/dist/server/host.js.map +1 -0
- package/dist/server/host.test.d.ts +1 -0
- package/dist/server/host.test.js +13 -0
- package/dist/server/host.test.js.map +1 -0
- package/dist/server/index.d.ts +16 -9
- package/dist/server/index.js +9 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-errors.test.d.ts +1 -0
- package/dist/server/mcp-errors.test.js +41 -0
- package/dist/server/mcp-errors.test.js.map +1 -0
- package/dist/server/middleware.d.ts +35 -10
- package/dist/server/middleware.js +33 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js +242 -134
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +27 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/server.d.ts +138 -129
- package/dist/server/server.js +210 -272
- package/dist/server/server.js.map +1 -1
- package/dist/server/skills-integration.test.d.ts +1 -0
- package/dist/server/skills-integration.test.js +86 -0
- package/dist/server/skills-integration.test.js.map +1 -0
- package/dist/server/skills.d.ts +27 -0
- package/dist/server/skills.js +188 -0
- package/dist/server/skills.js.map +1 -0
- package/dist/server/skills.test.d.ts +1 -0
- package/dist/server/skills.test.js +243 -0
- package/dist/server/skills.test.js.map +1 -0
- package/dist/server/templateHelper.d.ts +0 -3
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.js +4 -8
- package/dist/server/templates.generated.js.map +1 -1
- package/dist/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +88 -0
- package/dist/server/tool-extra.test.js.map +1 -0
- package/dist/server/view-name.test-d.d.ts +1 -0
- package/dist/server/view-name.test-d.js +8 -0
- package/dist/server/view-name.test-d.js.map +1 -0
- package/dist/server/view-resource-resolution.test.js +81 -8
- package/dist/server/view-resource-resolution.test.js.map +1 -1
- package/dist/server/viewsDevServer.js +4 -1
- package/dist/server/viewsDevServer.js.map +1 -1
- package/dist/test/utils.d.ts +9 -11
- package/dist/test/utils.js +220 -201
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +44 -40
- package/dist/test/view.test.js.map +1 -1
- package/dist/views/index.d.ts +10 -0
- package/dist/views/index.js +3 -0
- package/dist/views/index.js.map +1 -0
- package/dist/{web/plugin → views}/scan-views.js +1 -1
- package/dist/views/scan-views.js.map +1 -0
- package/dist/views/scan-views.test.d.ts +1 -0
- package/dist/views/scan-views.test.js.map +1 -0
- package/dist/views/validate-view.d.ts +1 -0
- package/dist/{web/plugin → views}/validate-view.js +2 -2
- package/dist/views/validate-view.js.map +1 -0
- package/dist/views/validate-view.test.d.ts +1 -0
- package/dist/views/validate-view.test.js.map +1 -0
- package/dist/web/bridges/adaptor.js +22 -5
- package/dist/web/bridges/adaptor.js.map +1 -1
- package/dist/web/bridges/adaptor.test.js +34 -6
- package/dist/web/bridges/adaptor.test.js.map +1 -1
- package/dist/web/bridges/apps-sdk/bridge.js +1 -1
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +4 -4
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +4 -4
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.test.js +2 -2
- package/dist/web/bridges/get-adaptor.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.js +6 -4
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.test.js +2 -2
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/types.d.ts +2 -0
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.js +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +18 -13
- package/dist/web/bridges/types.js +1 -1
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/components/modal-provider.d.ts +1 -1
- package/dist/web/create-store.test.js +2 -2
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +1 -1
- package/dist/web/data-llm.test.js +11 -2
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +22 -18
- package/dist/web/generate-helpers.js +19 -15
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +3 -3
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/generate-helpers.test.js +2 -2
- package/dist/web/generate-helpers.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +2 -1
- package/dist/web/hooks/index.js +2 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.d.ts +2 -1
- package/dist/web/hooks/test/utils.js +1 -1
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +2 -2
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +1 -1
- package/dist/web/hooks/use-display-mode.js +1 -1
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +1 -1
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +1 -3
- package/dist/web/hooks/use-download.js +1 -2
- package/dist/web/hooks/use-download.js.map +1 -1
- package/dist/web/hooks/use-download.test.js +7 -7
- package/dist/web/hooks/use-download.test.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +1 -1
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-host.d.ts +22 -0
- package/dist/web/hooks/use-host.js +30 -0
- package/dist/web/hooks/use-host.js.map +1 -0
- package/dist/web/hooks/use-host.test.d.ts +1 -0
- package/dist/web/hooks/use-host.test.js +59 -0
- package/dist/web/hooks/use-host.test.js.map +1 -0
- package/dist/web/hooks/use-open-external.test.js +2 -2
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-register-view-tool.d.ts +3 -4
- package/dist/web/hooks/use-register-view-tool.js +1 -1
- package/dist/web/hooks/use-register-view-tool.js.map +1 -1
- package/dist/web/hooks/use-request-close.test.js +1 -1
- package/dist/web/hooks/use-request-close.test.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +1 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.d.ts +1 -1
- package/dist/web/hooks/use-request-size.js +1 -1
- package/dist/web/hooks/use-request-size.js.map +1 -1
- package/dist/web/hooks/use-request-size.test.js +1 -1
- package/dist/web/hooks/use-request-size.test.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +2 -8
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +1 -20
- package/dist/web/hooks/use-tool-info.js +0 -1
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +0 -5
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +2 -7
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +3 -2
- package/dist/web/hooks/use-user.js +4 -3
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +5 -3
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.js +19 -9
- package/dist/web/hooks/use-view-state.js.map +1 -1
- package/dist/web/hooks/use-view-state.test.js +33 -2
- package/dist/web/hooks/use-view-state.test.js.map +1 -1
- package/dist/web/hooks/use-viewport.d.ts +20 -0
- package/dist/web/hooks/use-viewport.js +21 -0
- package/dist/web/hooks/use-viewport.js.map +1 -0
- package/dist/web/hooks/use-viewport.test.d.ts +1 -0
- package/dist/web/hooks/{use-layout.test.js → use-viewport.test.js} +12 -32
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/web/mount-view.d.ts +3 -2
- package/dist/web/mount-view.js +5 -8
- package/dist/web/mount-view.js.map +1 -1
- package/package.json +31 -28
- package/dist/cli/resolve-views-dir.d.ts +0 -1
- package/dist/cli/resolve-views-dir.js.map +0 -1
- package/dist/web/hooks/use-layout.d.ts +0 -24
- package/dist/web/hooks/use-layout.js +0 -25
- package/dist/web/hooks/use-layout.js.map +0 -1
- package/dist/web/hooks/use-layout.test.js.map +0 -1
- package/dist/web/plugin/data-llm.test.js +0 -81
- package/dist/web/plugin/data-llm.test.js.map +0 -1
- package/dist/web/plugin/plugin.d.ts +0 -33
- package/dist/web/plugin/plugin.js +0 -189
- package/dist/web/plugin/plugin.js.map +0 -1
- package/dist/web/plugin/scan-views.js.map +0 -1
- package/dist/web/plugin/scan-views.test.js.map +0 -1
- package/dist/web/plugin/transform-data-llm.d.ts +0 -12
- package/dist/web/plugin/transform-data-llm.js +0 -96
- package/dist/web/plugin/transform-data-llm.js.map +0 -1
- package/dist/web/plugin/transform-data-llm.test.js +0 -81
- package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
- package/dist/web/plugin/validate-view.d.ts +0 -1
- package/dist/web/plugin/validate-view.js.map +0 -1
- package/dist/web/plugin/validate-view.test.js.map +0 -1
- /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
- /package/dist/{web/plugin/data-llm.test.d.ts → context-warnings.test.d.ts} +0 -0
- /package/dist/{web/plugin/scan-views.test.d.ts → server/app.test.d.ts} +0 -0
- /package/dist/{web/plugin/validate-view.test.d.ts → server/auth/providers/authplane.test.d.ts} +0 -0
- /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
- /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
- /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
- /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-download.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-download.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,MAAM,GAAmB;IAC7B,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE;gBACR,GAAG,EAAE,qBAAqB;gBAC1B,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,mBAAmB;aAC1B;SACF;KACF;CACF,CAAC;AAEF,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC5B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-download.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-download.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport type { DownloadParams } from \"../bridges/types.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useDownload } from \"./use-download.js\";\n\nconst params: DownloadParams = {\n contents: [\n {\n type: \"resource\",\n resource: {\n uri: \"file:///export.json\",\n mimeType: \"application/json\",\n text: '{\"hello\":\"world\"}',\n },\n },\n ],\n};\n\ndescribe(\"useDownload\", () => {\n describe(\"apps-sdk host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", {});\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.stubGlobal(\"parent\", { postMessage: getMcpAppHostPostMessageMock() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"returns { isError: true } and logs an error\", async () => {\n const errorSpy = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const { result } = renderHook(() => useDownload());\n\n const res = await result.current(params);\n\n expect(res).toEqual({ isError: true });\n expect(errorSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"does not support ui/download-file\"),\n );\n });\n });\n\n describe(\"mcp-app host without downloadFile capability\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.stubGlobal(\"parent\", { postMessage: getMcpAppHostPostMessageMock() });\n });\n\n afterEach(async () => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"returns { isError: true } and logs an error\", async () => {\n const errorSpy = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const { result } = renderHook(() => useDownload());\n\n const res = await result.current(params);\n\n expect(res).toEqual({ isError: true });\n expect(errorSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"does not support ui/download-file\"),\n );\n });\n });\n\n describe(\"mcp-app host with downloadFile capability\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock(\n {},\n { hostCapabilities: { downloadFile: {} } },\n );\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends ui/download-file with the provided contents\", async () => {\n const { result } = renderHook(() => useDownload());\n\n const res = await result.current(params);\n\n expect(res).toEqual({});\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/download-file\",\n params,\n }),\n \"*\",\n );\n });\n });\n\n it(\"returns { isError: true } when the host denies the request\", async () => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n postMessageMock = getMcpAppHostPostMessageMock(\n {},\n {\n hostCapabilities: { downloadFile: {} },\n downloadFileResult: { isError: true },\n },\n );\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n\n const { result } = renderHook(() => useDownload());\n\n const res = await result.current(params);\n\n expect(res).toEqual({ isError: true });\n });\n });\n});\n"]}
|
|
@@ -17,7 +17,7 @@ describe("useFiles", () => {
|
|
|
17
17
|
HostAdaptor.resetInstance();
|
|
18
18
|
McpAppBridge.resetInstance();
|
|
19
19
|
AppsSdkBridge.resetInstance();
|
|
20
|
-
vi.stubGlobal("skybridge", {
|
|
20
|
+
vi.stubGlobal("skybridge", {});
|
|
21
21
|
vi.stubGlobal("openai", OpenaiMock);
|
|
22
22
|
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
23
23
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-files.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-files.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,MAAM,UAAU,GAA4B;QAC1C,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACpC,MAAM,EAAE,wBAAwB;SACjC,CAAC;QACF,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;QAC3B,WAAW,EAAE,IAAI;QACjB,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;KACxB,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,aAAa,CAAC,aAAa,EAAE,CAAC;QAC9B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-files.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-files.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useFiles } from \"./use-files.js\";\n\ndescribe(\"useFiles\", () => {\n const OpenaiMock: Record<string, unknown> = {\n uploadFile: vi.fn().mockResolvedValue({\n fileId: `sediment://file_abc123`,\n }),\n getFileDownloadUrl: vi.fn(),\n widgetState: null,\n setWidgetState: vi.fn(),\n };\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", OpenaiMock);\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.clearAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n const dummyFile = new File([], \"test.txt\");\n\n it(\"should upload a file to ChatGPT\", () => {\n const { result } = renderHook(() => useFiles());\n\n result.current.upload(dummyFile);\n expect(OpenaiMock.uploadFile).toHaveBeenCalledWith(dummyFile, undefined);\n });\n\n it(\"should upload a file with library option\", () => {\n const { result } = renderHook(() => useFiles());\n\n result.current.upload(dummyFile, { library: true });\n expect(OpenaiMock.uploadFile).toHaveBeenCalledWith(dummyFile, {\n library: true,\n });\n });\n\n it(\"should select files from ChatGPT\", async () => {\n const selectedFiles = [\n { fileId: \"file_1\", fileName: \"doc.pdf\", mimeType: \"application/pdf\" },\n ];\n OpenaiMock.selectFiles = vi.fn().mockResolvedValue(selectedFiles);\n\n const { result } = renderHook(() => useFiles());\n\n const files = await result.current.selectFiles();\n expect(OpenaiMock.selectFiles).toHaveBeenCalled();\n expect(files).toEqual(selectedFiles);\n\n delete OpenaiMock.selectFiles;\n });\n\n it(\"should download a file from ChatGPT\", () => {\n const fileId = \"123\";\n const { result } = renderHook(() => useFiles());\n\n result.current.getDownloadUrl({ fileId });\n expect(OpenaiMock.getFileDownloadUrl).toHaveBeenCalledWith({ fileId });\n });\n});\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known host applications, as normalized slugs. Unrecognized hosts surface
|
|
3
|
+
* their raw `hostInfo.name` string instead.
|
|
4
|
+
*/
|
|
5
|
+
export type Host = "chatgpt" | "claude" | "cursor" | "goose" | "mistral-vibe" | "alpic";
|
|
6
|
+
export type HostInfo = {
|
|
7
|
+
name: Host | (string & {}) | undefined;
|
|
8
|
+
version: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Identity of the host application rendering the view, from the MCP Apps
|
|
12
|
+
* `ui/initialize` handshake. `name` is normalized to a {@link Host} slug when
|
|
13
|
+
* recognized, otherwise the raw string; both fields are `undefined` until the
|
|
14
|
+
* handshake resolves (the view renders first and re-renders once it lands).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const { name } = useHost();
|
|
19
|
+
* if (name === "claude") return <ClaudeLayout />;
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function useHost(): HostInfo;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useMcpAppContext } from "../bridges/index.js";
|
|
2
|
+
const HOST_BY_REPORTED_NAME = {
|
|
3
|
+
chatgpt: "chatgpt",
|
|
4
|
+
Claude: "claude",
|
|
5
|
+
Cursor: "cursor",
|
|
6
|
+
"MCP-UI Host": "goose",
|
|
7
|
+
"Le Chat": "mistral-vibe",
|
|
8
|
+
"alpic-playground": "alpic",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Identity of the host application rendering the view, from the MCP Apps
|
|
12
|
+
* `ui/initialize` handshake. `name` is normalized to a {@link Host} slug when
|
|
13
|
+
* recognized, otherwise the raw string; both fields are `undefined` until the
|
|
14
|
+
* handshake resolves (the view renders first and re-renders once it lands).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const { name } = useHost();
|
|
19
|
+
* if (name === "claude") return <ClaudeLayout />;
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function useHost() {
|
|
23
|
+
const hostInfo = useMcpAppContext("hostInfo");
|
|
24
|
+
const name = hostInfo?.name;
|
|
25
|
+
return {
|
|
26
|
+
name: name !== undefined ? (HOST_BY_REPORTED_NAME[name] ?? name) : undefined,
|
|
27
|
+
version: hostInfo?.version,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=use-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-host.js","sourceRoot":"","sources":["../../../src/web/hooks/use-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAcvD,MAAM,qBAAqB,GAAyB;IAClD,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,aAAa,EAAE,OAAO;IACtB,SAAS,EAAE,cAAc;IACzB,kBAAkB,EAAE,OAAO;CAC5B,CAAC;AAOF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;IAE5B,OAAO;QACL,IAAI,EACF,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QACxE,OAAO,EAAE,QAAQ,EAAE,OAAO;KAC3B,CAAC;AACJ,CAAC","sourcesContent":["import { useMcpAppContext } from \"../bridges/index.js\";\n\n/**\n * Known host applications, as normalized slugs. Unrecognized hosts surface\n * their raw `hostInfo.name` string instead.\n */\nexport type Host =\n | \"chatgpt\"\n | \"claude\"\n | \"cursor\"\n | \"goose\"\n | \"mistral-vibe\"\n | \"alpic\";\n\nconst HOST_BY_REPORTED_NAME: Record<string, Host> = {\n chatgpt: \"chatgpt\",\n Claude: \"claude\",\n Cursor: \"cursor\",\n \"MCP-UI Host\": \"goose\",\n \"Le Chat\": \"mistral-vibe\",\n \"alpic-playground\": \"alpic\",\n};\n\nexport type HostInfo = {\n name: Host | (string & {}) | undefined;\n version: string | undefined;\n};\n\n/**\n * Identity of the host application rendering the view, from the MCP Apps\n * `ui/initialize` handshake. `name` is normalized to a {@link Host} slug when\n * recognized, otherwise the raw string; both fields are `undefined` until the\n * handshake resolves (the view renders first and re-renders once it lands).\n *\n * @example\n * ```tsx\n * const { name } = useHost();\n * if (name === \"claude\") return <ClaudeLayout />;\n * ```\n */\nexport function useHost(): HostInfo {\n const hostInfo = useMcpAppContext(\"hostInfo\");\n const name = hostInfo?.name;\n\n return {\n name:\n name !== undefined ? (HOST_BY_REPORTED_NAME[name] ?? name) : undefined,\n version: hostInfo?.version,\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { HostAdaptor } from "../bridges/adaptor.js";
|
|
4
|
+
import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
|
|
5
|
+
import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
|
|
6
|
+
import { useHost } from "./use-host.js";
|
|
7
|
+
const stubHost = (hostInfo) => {
|
|
8
|
+
vi.stubGlobal("parent", {
|
|
9
|
+
postMessage: getMcpAppHostPostMessageMock({}, { hostInfo }),
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
describe("useHost", () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
HostAdaptor.resetInstance();
|
|
15
|
+
McpAppBridge.resetInstance();
|
|
16
|
+
vi.stubGlobal("openai", undefined);
|
|
17
|
+
vi.stubGlobal("skybridge", {});
|
|
18
|
+
vi.stubGlobal("ResizeObserver", MockResizeObserver);
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
vi.unstubAllGlobals();
|
|
22
|
+
vi.resetAllMocks();
|
|
23
|
+
McpAppBridge.resetInstance();
|
|
24
|
+
HostAdaptor.resetInstance();
|
|
25
|
+
});
|
|
26
|
+
it("is undefined before the handshake resolves, then populated after", async () => {
|
|
27
|
+
stubHost({ name: "Claude", version: "1.2.3" });
|
|
28
|
+
const { result } = renderHook(() => useHost());
|
|
29
|
+
expect(result.current.name).toBeUndefined();
|
|
30
|
+
expect(result.current.version).toBeUndefined();
|
|
31
|
+
await waitFor(() => {
|
|
32
|
+
expect(result.current.name).toBe("claude");
|
|
33
|
+
expect(result.current.version).toBe("1.2.3");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it.each([
|
|
37
|
+
["chatgpt", "chatgpt"],
|
|
38
|
+
["Claude", "claude"],
|
|
39
|
+
["Cursor", "cursor"],
|
|
40
|
+
["MCP-UI Host", "goose"],
|
|
41
|
+
["Le Chat", "mistral-vibe"],
|
|
42
|
+
["alpic-playground", "alpic"],
|
|
43
|
+
])("normalizes reported name %j to slug %j", async (reported, slug) => {
|
|
44
|
+
stubHost({ name: reported, version: "1.0.0" });
|
|
45
|
+
const { result } = renderHook(() => useHost());
|
|
46
|
+
await waitFor(() => {
|
|
47
|
+
expect(result.current.name).toBe(slug);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
it("preserves an unrecognized reported name as-is", async () => {
|
|
51
|
+
stubHost({ name: "Some Future Host", version: "9.9.9" });
|
|
52
|
+
const { result } = renderHook(() => useHost());
|
|
53
|
+
await waitFor(() => {
|
|
54
|
+
expect(result.current.name).toBe("Some Future Host");
|
|
55
|
+
expect(result.current.version).toBe("9.9.9");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=use-host.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-host.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-host.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { type Host, useHost } from \"./use-host.js\";\n\nconst stubHost = (hostInfo?: { name: string; version: string }) => {\n vi.stubGlobal(\"parent\", {\n postMessage: getMcpAppHostPostMessageMock({}, { hostInfo }),\n });\n};\n\ndescribe(\"useHost\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n McpAppBridge.resetInstance();\n HostAdaptor.resetInstance();\n });\n\n it(\"is undefined before the handshake resolves, then populated after\", async () => {\n stubHost({ name: \"Claude\", version: \"1.2.3\" });\n const { result } = renderHook(() => useHost());\n\n expect(result.current.name).toBeUndefined();\n expect(result.current.version).toBeUndefined();\n\n await waitFor(() => {\n expect(result.current.name).toBe(\"claude\");\n expect(result.current.version).toBe(\"1.2.3\");\n });\n });\n\n it.each<[string, Host]>([\n [\"chatgpt\", \"chatgpt\"],\n [\"Claude\", \"claude\"],\n [\"Cursor\", \"cursor\"],\n [\"MCP-UI Host\", \"goose\"],\n [\"Le Chat\", \"mistral-vibe\"],\n [\"alpic-playground\", \"alpic\"],\n ])(\"normalizes reported name %j to slug %j\", async (reported, slug) => {\n stubHost({ name: reported, version: \"1.0.0\" });\n const { result } = renderHook(() => useHost());\n\n await waitFor(() => {\n expect(result.current.name).toBe(slug);\n });\n });\n\n it(\"preserves an unrecognized reported name as-is\", async () => {\n stubHost({ name: \"Some Future Host\", version: \"9.9.9\" });\n const { result } = renderHook(() => useHost());\n\n await waitFor(() => {\n expect(result.current.name).toBe(\"Some Future Host\");\n expect(result.current.version).toBe(\"9.9.9\");\n });\n });\n});\n"]}
|
|
@@ -13,7 +13,7 @@ describe("useOpenExternal", () => {
|
|
|
13
13
|
vi.stubGlobal("openai", {
|
|
14
14
|
openExternal: openExternalMock,
|
|
15
15
|
});
|
|
16
|
-
vi.stubGlobal("skybridge", {
|
|
16
|
+
vi.stubGlobal("skybridge", {});
|
|
17
17
|
vi.stubGlobal("ResizeObserver", MockResizeObserver);
|
|
18
18
|
postMessageMock = getMcpAppHostPostMessageMock();
|
|
19
19
|
vi.stubGlobal("parent", { postMessage: postMessageMock });
|
|
@@ -47,7 +47,7 @@ describe("useOpenExternal", () => {
|
|
|
47
47
|
let postMessageMock;
|
|
48
48
|
beforeEach(() => {
|
|
49
49
|
vi.stubGlobal("openai", undefined);
|
|
50
|
-
vi.stubGlobal("skybridge", {
|
|
50
|
+
vi.stubGlobal("skybridge", {});
|
|
51
51
|
vi.stubGlobal("ResizeObserver", MockResizeObserver);
|
|
52
52
|
postMessageMock = getMcpAppHostPostMessageMock();
|
|
53
53
|
vi.stubGlobal("parent", { postMessage: postMessageMock });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,IAAI,gBAA0C,CAAC;QAC/C,IAAI,eAAgE,CAAC;QAErE,UAAU,CAAC,GAAG,EAAE;YACd,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACtB,YAAY,EAAE,gBAAgB;aAC/B,CAAC,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useOpenExternal } from \"./use-open-external.js\";\n\ndescribe(\"useOpenExternal\", () => {\n describe(\"apps-sdk host\", () => {\n let openExternalMock: ReturnType<typeof vi.fn>;\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n openExternalMock = vi.fn();\n vi.stubGlobal(\"openai\", {\n openExternal: openExternalMock,\n });\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should call window.openai.openExternal even without a redirectUrl option\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href);\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({ href });\n expect(postMessageMock).not.toHaveBeenCalledWith(\n expect.objectContaining({ method: \"ui/open-link\" }),\n \"*\",\n );\n });\n\n it(\"should call window.openai.openExternal when redirectUrl is false\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({\n href,\n redirectUrl: false,\n });\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return a function that sends ui/open-link request to the MCP host\", async () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/open-link\",\n params: { url: href },\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
|
|
1
|
+
import type { ViewToolConfig, ViewToolHandler, ViewToolInputShape } from "../bridges/types.js";
|
|
3
2
|
/**
|
|
4
3
|
* Register a tool the view exposes to the host and model — the MCP Apps
|
|
5
4
|
* "app-provided tools" feature. A view tool runs *inside the view*: the host
|
|
@@ -8,7 +7,7 @@ import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
|
|
|
8
7
|
* {@link useCallTool} (which calls a server tool). Registered on mount, removed
|
|
9
8
|
* on unmount; re-registered when `config.name` changes.
|
|
10
9
|
*
|
|
11
|
-
* MCP Apps only — on the
|
|
10
|
+
* MCP Apps only — on the ChatGPT (`window.openai`) runtime it is a no-op.
|
|
12
11
|
*
|
|
13
12
|
* @example
|
|
14
13
|
* ```tsx
|
|
@@ -35,4 +34,4 @@ import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
|
|
|
35
34
|
*
|
|
36
35
|
* @see https://docs.skybridge.tech/api-reference/use-register-view-tool
|
|
37
36
|
*/
|
|
38
|
-
export declare const useRegisterViewTool: <TInput extends
|
|
37
|
+
export declare const useRegisterViewTool: <TInput extends ViewToolInputShape = ViewToolInputShape>(config: ViewToolConfig<TInput>, handler: ViewToolHandler<TInput>) => void;
|
|
@@ -8,7 +8,7 @@ import { getAdaptor } from "../bridges/index.js";
|
|
|
8
8
|
* {@link useCallTool} (which calls a server tool). Registered on mount, removed
|
|
9
9
|
* on unmount; re-registered when `config.name` changes.
|
|
10
10
|
*
|
|
11
|
-
* MCP Apps only — on the
|
|
11
|
+
* MCP Apps only — on the ChatGPT (`window.openai`) runtime it is a no-op.
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* ```tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-register-view-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-register-view-tool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-register-view-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-register-view-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAGjC,MAA8B,EAC9B,OAAgC,EAChC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAuB,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,OAAO,CAAC,IAA8C,CAAC,CAAC;QAErE,OAAO,OAAO,CAAC,gBAAgB,CAC7B,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAC9B,cAAc,CACf,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC,CAAC","sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type {\n AnyViewToolHandler,\n ViewToolConfig,\n ViewToolHandler,\n ViewToolInputShape,\n} from \"../bridges/types.js\";\n\n/**\n * Register a tool the view exposes to the host and model — the MCP Apps\n * \"app-provided tools\" feature. A view tool runs *inside the view*: the host\n * discovers it via `tools/list` and invokes it via `tools/call`, and the\n * handler executes against the view's live state. It is the inverse of\n * {@link useCallTool} (which calls a server tool). Registered on mount, removed\n * on unmount; re-registered when `config.name` changes.\n *\n * MCP Apps only — on the ChatGPT (`window.openai`) runtime it is a no-op.\n *\n * @example\n * ```tsx\n * import * as z from \"zod\";\n * import { useRegisterViewTool } from \"skybridge/web\";\n *\n * useRegisterViewTool(\n * {\n * name: \"chess_make_move\",\n * description: \"Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.\",\n * inputSchema: { san: z.string() },\n * annotations: { readOnlyHint: false },\n * },\n * ({ san }) => {\n * const move = game.move(san);\n * return {\n * content: [{ type: \"text\", text: move ? `Played ${move.san}` : \"Illegal move\" }],\n * structuredContent: { fen: game.fen() },\n * isError: !move,\n * };\n * },\n * );\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-register-view-tool\n */\nexport const useRegisterViewTool = <\n TInput extends ViewToolInputShape = ViewToolInputShape,\n>(\n config: ViewToolConfig<TInput>,\n handler: ViewToolHandler<TInput>,\n) => {\n const { name } = config;\n const configRef = useRef(config);\n configRef.current = config;\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n const adaptor = getAdaptor();\n const wrappedHandler: AnyViewToolHandler = (args) =>\n handlerRef.current(args as Parameters<ViewToolHandler<TInput>>[0]);\n\n return adaptor.registerViewTool(\n { ...configRef.current, name },\n wrappedHandler,\n );\n }, [name]);\n};\n"]}
|
|
@@ -8,7 +8,7 @@ describe("useRequestClose", () => {
|
|
|
8
8
|
beforeEach(() => {
|
|
9
9
|
HostAdaptor.resetInstance();
|
|
10
10
|
McpAppBridge.resetInstance();
|
|
11
|
-
vi.stubGlobal("skybridge", {
|
|
11
|
+
vi.stubGlobal("skybridge", {});
|
|
12
12
|
vi.stubGlobal("openai", undefined);
|
|
13
13
|
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
14
14
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { getAdaptor } from \"../bridges/get-adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestClose } from \"./use-request-close.js\";\n\ndescribe(\"useRequestClose\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"calls app.requestTeardown via the MCP path\", async () => {\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n\n it(\"calls app.requestTeardown even when window.openai is present\", async () => {\n vi.stubGlobal(\"openai\", { requestClose: vi.fn() });\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n});\n"]}
|
|
@@ -11,7 +11,7 @@ describe("useRequestModal", () => {
|
|
|
11
11
|
McpAppBridge.resetInstance();
|
|
12
12
|
AppsSdkBridge.resetInstance();
|
|
13
13
|
requestModalMock = vi.fn();
|
|
14
|
-
vi.stubGlobal("skybridge", {
|
|
14
|
+
vi.stubGlobal("skybridge", {});
|
|
15
15
|
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
16
16
|
vi.stubGlobal("openai", {
|
|
17
17
|
requestModal: requestModalMock,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,gBAA0C,CAAC;IAE/C,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,aAAa,CAAC,aAAa,EAAE,CAAC;QAC9B,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,gBAA0C,CAAC;IAE/C,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,aAAa,CAAC,aAAa,EAAE,CAAC;QAC9B,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;YACtB,YAAY,EAAE,gBAAgB;YAC9B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,aAAa,CAAC,aAAa,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+GAA+G,EAAE,GAAG,EAAE;QACvH,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;QAEvD,MAAM,CAAC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;QAChD,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;YACtB,YAAY,EAAE,gBAAgB;YAC9B,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;SACxB,CAAC,CAAC;QAEH,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;QACvD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;QAElC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAC3C,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;YACtB,YAAY,EAAE,gBAAgB;YAC9B,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE;SAC5C,CAAC,CAAC;QAEH,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;QACvD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;QAElC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;QACvD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;QAEhC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;YACtB,QAAQ,EAAE,+BAA+B;SAC1C,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,CAAC;QAEd,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestModal } from \"./use-request-modal.js\";\n\ndescribe(\"useRequestModal\", () => {\n let requestModalMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n requestModalMock = vi.fn();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"inline\" },\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal\", () => {\n const { result } = renderHook(() => useRequestModal());\n\n expect(typeof result.current).toBe(\"object\");\n expect(result.current).toHaveProperty(\"open\");\n expect(result.current).toHaveProperty(\"isOpen\");\n expect(result.current).toHaveProperty(\"params\");\n\n const { open, isOpen, params } = result.current;\n expect(typeof open).toBe(\"function\");\n expect(isOpen).toBe(false);\n expect(params).toBeUndefined();\n });\n\n it(\"should return isOpen as true when mode is modal\", () => {\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\" },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { isOpen } = result.current;\n\n expect(isOpen).toBe(true);\n });\n\n it(\"should return params from view when available\", () => {\n const testParams = { foo: \"bar\", baz: 42 };\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\", params: testParams },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { params } = result.current;\n\n expect(params).toEqual(testParams);\n });\n\n it(\"should call window.openai.requestModal with the options when open is called\", () => {\n const { result } = renderHook(() => useRequestModal());\n const { open } = result.current;\n\n const options = {\n title: \"Test Modal\",\n params: { foo: \"bar\" },\n template: \"ui://view/modal-template.html\",\n };\n open(options);\n\n expect(requestModalMock).toHaveBeenCalledTimes(1);\n expect(requestModalMock).toHaveBeenCalledWith(options);\n });\n});\n"]}
|
|
@@ -3,7 +3,7 @@ import type { RequestSizeOptions } from "../bridges/types.js";
|
|
|
3
3
|
export type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;
|
|
4
4
|
/**
|
|
5
5
|
* Ask the host to resize the view iframe. The applied size is host-driven —
|
|
6
|
-
* the host decides whether and how to honor the request, and {@link
|
|
6
|
+
* the host decides whether and how to honor the request, and {@link useViewport}
|
|
7
7
|
* still reports the final `maxHeight` it allows.
|
|
8
8
|
*
|
|
9
9
|
* Pair with a `ResizeObserver` on your root element to react to content size
|
|
@@ -2,7 +2,7 @@ import { useCallback } from "react";
|
|
|
2
2
|
import { getAdaptor } from "../bridges/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Ask the host to resize the view iframe. The applied size is host-driven —
|
|
5
|
-
* the host decides whether and how to honor the request, and {@link
|
|
5
|
+
* the host decides whether and how to honor the request, and {@link useViewport}
|
|
6
6
|
* still reports the final `maxHeight` it allows.
|
|
7
7
|
*
|
|
8
8
|
* Pair with a `ResizeObserver` on your root element to react to content size
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\n/** Function that asks the host to resize the view, returned by {@link useRequestSize}. */\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\n/**\n * Ask the host to resize the view iframe. The applied size is host-driven —\n * the host decides whether and how to honor the request, and {@link
|
|
1
|
+
{"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\n/** Function that asks the host to resize the view, returned by {@link useRequestSize}. */\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\n/**\n * Ask the host to resize the view iframe. The applied size is host-driven —\n * the host decides whether and how to honor the request, and {@link useViewport}\n * still reports the final `maxHeight` it allows.\n *\n * Pair with a `ResizeObserver` on your root element to react to content size\n * changes without hard-coded values.\n *\n * @example\n * ```tsx\n * const requestSize = useRequestSize();\n * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-size\n */\nexport function useRequestSize(): RequestSizeFn {\n const adaptor = getAdaptor();\n const requestSize = useCallback(\n (size: RequestSizeOptions) => adaptor.requestSize(size),\n [adaptor],\n );\n\n return requestSize;\n}\n"]}
|
|
@@ -9,7 +9,7 @@ describe("useRequestSize", () => {
|
|
|
9
9
|
beforeEach(() => {
|
|
10
10
|
HostAdaptor.resetInstance();
|
|
11
11
|
McpAppBridge.resetInstance();
|
|
12
|
-
vi.stubGlobal("skybridge", {
|
|
12
|
+
vi.stubGlobal("skybridge", {});
|
|
13
13
|
vi.stubGlobal("openai", undefined);
|
|
14
14
|
vi.stubGlobal("ResizeObserver", MockResizeObserver);
|
|
15
15
|
postMessageMock = getMcpAppHostPostMessageMock();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,eAAgE,CAAC;IAErE,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,eAAgE,CAAC;IAErE,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,eAAe,GAAG,4BAA4B,EAAE,CAAC;QACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+BAA+B;gBACvC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;aACpC,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAEtC,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+BAA+B;gBACvC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;aACxB,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestSize } from \"./use-request-size.js\";\n\ndescribe(\"useRequestSize\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends a ui/notifications/size-changed notification with width and height\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ width: 800, height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { width: 800, height: 400 },\n }),\n \"*\",\n );\n });\n });\n\n it(\"forwards height-only payloads as-is\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { height: 400 },\n }),\n \"*\",\n );\n });\n });\n});\n"]}
|
|
@@ -20,10 +20,7 @@ describe("useSetOpenInAppUrl", () => {
|
|
|
20
20
|
vi.stubGlobal("openai", {
|
|
21
21
|
setOpenInAppUrl: setOpenInAppUrlMock,
|
|
22
22
|
});
|
|
23
|
-
vi.stubGlobal("skybridge", {
|
|
24
|
-
hostType: "apps-sdk",
|
|
25
|
-
serverUrl: "https://example.com",
|
|
26
|
-
});
|
|
23
|
+
vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
|
|
27
24
|
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
28
25
|
});
|
|
29
26
|
it("should return a function that calls window.openai.setOpenInAppUrl with the href", async () => {
|
|
@@ -48,10 +45,7 @@ describe("useSetOpenInAppUrl", () => {
|
|
|
48
45
|
describe("mcp-app host", () => {
|
|
49
46
|
beforeEach(() => {
|
|
50
47
|
vi.stubGlobal("openai", undefined);
|
|
51
|
-
vi.stubGlobal("skybridge", {
|
|
52
|
-
hostType: "mcp-app",
|
|
53
|
-
serverUrl: "https://example.com",
|
|
54
|
-
});
|
|
48
|
+
vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
|
|
55
49
|
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
56
50
|
});
|
|
57
51
|
it("should throw NotSupportedError when called from an MCP App runtime", async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,aAAa,CAAC,aAAa,EAAE,CAAC;QAC9B,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,IAAI,mBAA6C,CAAC;QAElD,UAAU,CAAC,GAAG,EAAE;YACd,mBAAmB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YAC3D,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACtB,eAAe,EAAE,mBAAmB;aACrC,CAAC,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { NotSupportedError } from \"../bridges/types.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n AppsSdkBridge.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should reject when href is empty\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(result.current(\"\")).rejects.toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n\n describe(\"mcp-app host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should throw NotSupportedError when called from an MCP App runtime\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(\n result.current(\"https://example.com/path\"),\n ).rejects.toBeInstanceOf(NotSupportedError);\n });\n });\n});\n"]}
|
|
@@ -1,21 +1,4 @@
|
|
|
1
1
|
import type { UnknownObject } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* {@link useToolInfo} state before the tool has been invoked.
|
|
4
|
-
*
|
|
5
|
-
* @deprecated `useToolInfo` no longer returns the idle state — it starts in
|
|
6
|
-
* `"pending"` and transitions to `"success"`, so `isIdle` is always `false` at
|
|
7
|
-
* runtime. This type is retained in {@link ToolState} for backwards
|
|
8
|
-
* compatibility and will be removed in the next major.
|
|
9
|
-
*/
|
|
10
|
-
export type ToolIdleState = {
|
|
11
|
-
status: "idle";
|
|
12
|
-
isIdle: true;
|
|
13
|
-
isPending: false;
|
|
14
|
-
isSuccess: false;
|
|
15
|
-
input: undefined;
|
|
16
|
-
output: undefined;
|
|
17
|
-
responseMetadata: undefined;
|
|
18
|
-
};
|
|
19
2
|
/**
|
|
20
3
|
* {@link useToolInfo} state while the tool is executing — `output` is not yet
|
|
21
4
|
* available.
|
|
@@ -25,7 +8,6 @@ export type ToolIdleState = {
|
|
|
25
8
|
*/
|
|
26
9
|
export type ToolPendingState<ToolInput extends UnknownObject> = {
|
|
27
10
|
status: "pending";
|
|
28
|
-
isIdle: false;
|
|
29
11
|
isPending: true;
|
|
30
12
|
isSuccess: false;
|
|
31
13
|
input: ToolInput | undefined;
|
|
@@ -40,7 +22,6 @@ export type ToolPendingState<ToolInput extends UnknownObject> = {
|
|
|
40
22
|
*/
|
|
41
23
|
export type ToolSuccessState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = {
|
|
42
24
|
status: "success";
|
|
43
|
-
isIdle: false;
|
|
44
25
|
isPending: false;
|
|
45
26
|
isSuccess: true;
|
|
46
27
|
input: ToolInput | undefined;
|
|
@@ -51,7 +32,7 @@ export type ToolSuccessState<ToolInput extends UnknownObject, ToolOutput extends
|
|
|
51
32
|
* Discriminated union describing the tool invocation that triggered the
|
|
52
33
|
* current view render. Use `isPending` / `isSuccess` to narrow.
|
|
53
34
|
*/
|
|
54
|
-
export type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> =
|
|
35
|
+
export type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = ToolPendingState<ToolInput> | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;
|
|
55
36
|
type ToolSignature = {
|
|
56
37
|
input: UnknownObject;
|
|
57
38
|
output: UnknownObject;
|