skybridge 0.0.0-dev.febf292 → 0.0.0-dev.fec0253
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 +126 -116
- package/dist/cli/build-helpers.d.ts +11 -0
- package/dist/cli/build-helpers.js +107 -0
- package/dist/cli/build-helpers.js.map +1 -0
- package/dist/cli/build-helpers.test.js +132 -0
- package/dist/cli/build-helpers.test.js.map +1 -0
- 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.d.ts +2 -2
- package/dist/cli/detect-port.js +8 -20
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/header.d.ts +1 -1
- package/dist/cli/header.js +1 -1
- package/dist/cli/header.js.map +1 -1
- package/dist/cli/resolve-skybridge-config.d.ts +5 -0
- package/dist/cli/resolve-skybridge-config.js +18 -0
- package/dist/cli/resolve-skybridge-config.js.map +1 -0
- package/dist/cli/run-command.js.map +1 -1
- 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/telemetry.js +2 -0
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/cli/tunnel-control-server.d.ts +9 -0
- package/dist/cli/tunnel-control-server.js +31 -0
- package/dist/cli/tunnel-control-server.js.map +1 -0
- package/dist/cli/tunnel-control-server.test.js +39 -0
- package/dist/cli/tunnel-control-server.test.js.map +1 -0
- package/dist/cli/tunnel-handler.d.ts +3 -0
- package/dist/cli/tunnel-handler.js +48 -0
- package/dist/cli/tunnel-handler.js.map +1 -0
- package/dist/cli/tunnel-handler.test.js +105 -0
- package/dist/cli/tunnel-handler.test.js.map +1 -0
- package/dist/cli/tunnel.d.ts +57 -0
- package/dist/cli/tunnel.js +154 -0
- package/dist/cli/tunnel.js.map +1 -0
- package/dist/cli/tunnel.test.js +190 -0
- package/dist/cli/tunnel.test.js.map +1 -0
- package/dist/cli/types.d.ts +5 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/use-execute-steps.d.ts +1 -1
- package/dist/cli/use-execute-steps.js.map +1 -1
- package/dist/cli/use-messages.d.ts +3 -0
- package/dist/cli/use-messages.js +11 -0
- package/dist/cli/use-messages.js.map +1 -0
- package/dist/cli/use-nodemon.d.ts +26 -7
- package/dist/cli/use-nodemon.js +97 -67
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-open-browser.d.ts +1 -0
- package/dist/cli/use-open-browser.js +44 -0
- package/dist/cli/use-open-browser.js.map +1 -0
- package/dist/cli/use-tunnel.d.ts +14 -0
- package/dist/cli/use-tunnel.js +131 -0
- package/dist/cli/use-tunnel.js.map +1 -0
- package/dist/cli/use-typescript-check.d.ts +9 -2
- package/dist/cli/use-typescript-check.js +89 -51
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.d.ts +0 -3
- package/dist/commands/build.js +3 -18
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/create.d.ts +9 -0
- package/dist/commands/create.js +30 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dev.d.ts +4 -1
- package/dist/commands/dev.js +95 -9
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +13 -10
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/status.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.d.ts +1 -0
- package/dist/server/app.test.js +97 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/asset-base-url-transform-plugin.d.ts +6 -6
- package/dist/server/asset-base-url-transform-plugin.js +25 -11
- package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
- package/dist/server/asset-base-url-transform-plugin.test.js +92 -14
- package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
- package/dist/server/auth/discovery.d.ts +33 -0
- package/dist/server/auth/discovery.js +56 -0
- package/dist/server/auth/discovery.js.map +1 -0
- package/dist/server/auth/discovery.test.d.ts +1 -0
- package/dist/server/auth/discovery.test.js +93 -0
- package/dist/server/auth/discovery.test.js.map +1 -0
- package/dist/server/auth/index.d.ts +48 -0
- package/dist/server/auth/index.js +2 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/server/auth/providers/auth0.d.ts +40 -0
- package/dist/server/auth/providers/auth0.js +36 -0
- package/dist/server/auth/providers/auth0.js.map +1 -0
- package/dist/server/auth/providers/auth0.test.d.ts +1 -0
- package/dist/server/auth/providers/auth0.test.js +50 -0
- package/dist/server/auth/providers/auth0.test.js.map +1 -0
- 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.d.ts +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 +51 -0
- package/dist/server/auth/providers/clerk.js +19 -0
- package/dist/server/auth/providers/clerk.js.map +1 -0
- package/dist/server/auth/providers/clerk.test.d.ts +1 -0
- package/dist/server/auth/providers/clerk.test.js +30 -0
- package/dist/server/auth/providers/clerk.test.js.map +1 -0
- package/dist/server/auth/providers/custom.d.ts +42 -0
- package/dist/server/auth/providers/custom.js +59 -0
- package/dist/server/auth/providers/custom.js.map +1 -0
- package/dist/server/auth/providers/custom.test.d.ts +1 -0
- package/dist/server/auth/providers/custom.test.js +161 -0
- package/dist/server/auth/providers/custom.test.js.map +1 -0
- package/dist/server/auth/providers/descope.d.ts +44 -0
- package/dist/server/auth/providers/descope.js +44 -0
- package/dist/server/auth/providers/descope.js.map +1 -0
- package/dist/server/auth/providers/descope.test.d.ts +1 -0
- package/dist/server/auth/providers/descope.test.js +62 -0
- package/dist/server/auth/providers/descope.test.js.map +1 -0
- package/dist/server/auth/providers/shared.d.ts +2 -0
- package/dist/server/auth/providers/shared.js +6 -0
- package/dist/server/auth/providers/shared.js.map +1 -0
- package/dist/server/auth/providers/shared.test.d.ts +1 -0
- package/dist/server/auth/providers/shared.test.js +10 -0
- package/dist/server/auth/providers/shared.test.js.map +1 -0
- package/dist/server/auth/providers/stytch.d.ts +25 -0
- package/dist/server/auth/providers/stytch.js +16 -0
- package/dist/server/auth/providers/stytch.js.map +1 -0
- 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 +34 -0
- package/dist/server/auth/providers/workos.js +16 -0
- package/dist/server/auth/providers/workos.js.map +1 -0
- 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 +6 -0
- package/dist/server/auth/setup.js +91 -0
- package/dist/server/auth/setup.js.map +1 -0
- package/dist/server/auth/setup.test.d.ts +1 -0
- package/dist/server/auth/setup.test.js +514 -0
- package/dist/server/auth/setup.test.js.map +1 -0
- package/dist/server/auth/verify.d.ts +48 -0
- package/dist/server/auth/verify.js +62 -0
- package/dist/server/auth/verify.js.map +1 -0
- package/dist/server/auth/verify.test.d.ts +1 -0
- package/dist/server/auth/verify.test.js +165 -0
- package/dist/server/auth/verify.test.js.map +1 -0
- package/dist/server/auth-extra.test-d.d.ts +1 -0
- 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 +57 -0
- package/dist/server/auth.js +27 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/build-manifest.test.d.ts +1 -0
- package/dist/server/build-manifest.test.js +28 -0
- package/dist/server/build-manifest.test.js.map +1 -0
- package/dist/server/content-helpers.d.ts +67 -0
- package/dist/server/content-helpers.js +79 -0
- package/dist/server/content-helpers.js.map +1 -0
- package/dist/server/content-helpers.test.d.ts +1 -0
- package/dist/server/content-helpers.test.js +70 -0
- package/dist/server/content-helpers.test.js.map +1 -0
- package/dist/server/events.d.ts +113 -0
- package/dist/server/events.js +318 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/events.test.d.ts +1 -0
- package/dist/server/events.test.js +172 -0
- package/dist/server/events.test.js.map +1 -0
- package/dist/server/express.d.ts +27 -5
- package/dist/server/express.js +83 -43
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +557 -22
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/file-ref.d.ts +28 -0
- package/dist/server/file-ref.js +27 -0
- package/dist/server/file-ref.js.map +1 -0
- package/dist/server/form-input.d.ts +120 -0
- package/dist/server/form-input.js +89 -0
- package/dist/server/form-input.js.map +1 -0
- 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 +23 -3
- package/dist/server/index.js +19 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/inferUtilityTypes.d.ts +6 -6
- package/dist/server/inferUtilityTypes.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/metric.d.ts +14 -0
- package/dist/server/metric.js +62 -0
- package/dist/server/metric.js.map +1 -0
- package/dist/server/middleware.d.ts +162 -0
- package/dist/server/middleware.js +126 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/middleware.test-d.d.ts +1 -0
- package/dist/server/middleware.test-d.js +75 -0
- package/dist/server/middleware.test-d.js.map +1 -0
- package/dist/server/middleware.test.d.ts +1 -0
- package/dist/server/middleware.test.js +601 -0
- package/dist/server/middleware.test.js.map +1 -0
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +230 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/requestOrigin.d.ts +7 -0
- package/dist/server/requestOrigin.js +25 -0
- package/dist/server/requestOrigin.js.map +1 -0
- package/dist/server/server.d.ts +629 -70
- package/dist/server/server.js +758 -165
- 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 +2 -8
- package/dist/server/templateHelper.js +3 -22
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.d.ts +4 -0
- package/dist/server/templates.generated.js +43 -0
- package/dist/server/templates.generated.js.map +1 -0
- package/dist/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +167 -0
- package/dist/server/tool-extra.test.js.map +1 -0
- package/dist/server/tunnel-proxy-router.d.ts +7 -0
- package/dist/server/tunnel-proxy-router.js +110 -0
- package/dist/server/tunnel-proxy-router.js.map +1 -0
- package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
- package/dist/server/tunnel-proxy-router.test.js +229 -0
- package/dist/server/tunnel-proxy-router.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.d.ts +6 -0
- package/dist/server/view-resource-resolution.test.js +176 -0
- package/dist/server/view-resource-resolution.test.js.map +1 -0
- package/dist/server/viewsDevServer.d.ts +14 -0
- package/dist/server/viewsDevServer.js +48 -0
- package/dist/server/viewsDevServer.js.map +1 -0
- package/dist/test/utils.d.ts +21 -31
- package/dist/test/utils.js +222 -198
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.d.ts +1 -0
- package/dist/test/view.test.js +540 -0
- package/dist/test/view.test.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- 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/views/scan-views.d.ts +16 -0
- package/dist/views/scan-views.js +88 -0
- 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 +99 -0
- package/dist/views/scan-views.test.js.map +1 -0
- package/dist/views/validate-view.d.ts +1 -0
- package/dist/views/validate-view.js +9 -0
- 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 +24 -0
- package/dist/views/validate-view.test.js.map +1 -0
- package/dist/web/bridges/adaptor.d.ts +62 -0
- package/dist/web/bridges/adaptor.js +471 -0
- package/dist/web/bridges/adaptor.js.map +1 -0
- package/dist/web/bridges/adaptor.test.d.ts +1 -0
- package/dist/web/bridges/adaptor.test.js +264 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -1
- package/dist/web/bridges/apps-sdk/bridge.js +15 -3
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
- package/dist/web/bridges/apps-sdk/index.js +0 -1
- package/dist/web/bridges/apps-sdk/index.js.map +1 -1
- package/dist/web/bridges/apps-sdk/types.d.ts +18 -6
- package/dist/web/bridges/apps-sdk/types.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.d.ts +7 -0
- package/dist/web/bridges/get-adaptor.js +9 -7
- package/dist/web/bridges/get-adaptor.js.map +1 -1
- package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
- package/dist/web/bridges/get-adaptor.test.js +32 -0
- package/dist/web/bridges/get-adaptor.test.js.map +1 -0
- package/dist/web/bridges/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.d.ts +27 -31
- package/dist/web/bridges/mcp-app/bridge.js +118 -203
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/index.d.ts +0 -1
- package/dist/web/bridges/mcp-app/index.js +0 -1
- package/dist/web/bridges/mcp-app/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/types.d.ts +19 -2
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +17 -3
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +14 -2
- 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 +2 -42
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
- package/dist/web/bridges/types.d.ts +182 -12
- package/dist/web/bridges/types.js +14 -1
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/bridges/types.test.d.ts +1 -0
- package/dist/web/bridges/types.test.js +19 -0
- package/dist/web/bridges/types.test.js.map +1 -0
- package/dist/web/bridges/use-host-context.d.ts +5 -0
- package/dist/web/bridges/use-host-context.js +5 -0
- package/dist/web/bridges/use-host-context.js.map +1 -1
- package/dist/web/components/modal-provider.d.ts +1 -1
- package/dist/web/components/modal-provider.js +5 -6
- package/dist/web/components/modal-provider.js.map +1 -1
- package/dist/web/create-store.d.ts +26 -0
- package/dist/web/create-store.js +43 -3
- package/dist/web/create-store.js.map +1 -1
- package/dist/web/create-store.test.js +27 -24
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +35 -2
- package/dist/web/data-llm.js +34 -5
- package/dist/web/data-llm.js.map +1 -1
- package/dist/web/data-llm.test.js +49 -29
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +40 -32
- package/dist/web/generate-helpers.js +38 -30
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +33 -31
- 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/helpers/state.d.ts +2 -2
- package/dist/web/helpers/state.js +11 -11
- package/dist/web/helpers/state.js.map +1 -1
- package/dist/web/helpers/state.test.js +9 -9
- package/dist/web/helpers/state.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +11 -2
- package/dist/web/hooks/index.js +11 -2
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
- package/dist/web/hooks/openai-extensions.test.js +107 -0
- package/dist/web/hooks/openai-extensions.test.js.map +1 -0
- package/dist/web/hooks/test/utils.d.ts +7 -2
- package/dist/web/hooks/test/utils.js +18 -3
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.d.ts +47 -2
- package/dist/web/hooks/use-call-tool.js +43 -10
- package/dist/web/hooks/use-call-tool.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +75 -29
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-deep-link.d.ts +22 -0
- package/dist/web/hooks/use-deep-link.js +34 -0
- package/dist/web/hooks/use-deep-link.js.map +1 -0
- package/dist/web/hooks/use-display-mode.d.ts +20 -0
- package/dist/web/hooks/use-display-mode.js +20 -0
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +57 -21
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +3 -0
- package/dist/web/hooks/use-download.js +7 -0
- package/dist/web/hooks/use-download.js.map +1 -0
- package/dist/web/hooks/use-download.test.d.ts +1 -0
- package/dist/web/hooks/use-download.test.js +103 -0
- package/dist/web/hooks/use-download.test.js.map +1 -0
- package/dist/web/hooks/use-file-resource.d.ts +37 -0
- package/dist/web/hooks/use-file-resource.js +98 -0
- package/dist/web/hooks/use-file-resource.js.map +1 -0
- package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
- package/dist/web/hooks/use-file-resource.test.js +65 -0
- package/dist/web/hooks/use-file-resource.test.js.map +1 -0
- package/dist/web/hooks/use-files.d.ts +34 -1
- package/dist/web/hooks/use-files.js +33 -0
- package/dist/web/hooks/use-files.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +31 -3
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-host.d.ts +44 -0
- package/dist/web/hooks/use-host.js +45 -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-model-context.d.ts +44 -0
- package/dist/web/hooks/use-model-context.js +63 -0
- package/dist/web/hooks/use-model-context.js.map +1 -0
- package/dist/web/hooks/use-open-external.d.ts +17 -0
- package/dist/web/hooks/use-open-external.js +16 -0
- package/dist/web/hooks/use-open-external.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js +30 -15
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-open-file.d.ts +20 -0
- package/dist/web/hooks/use-open-file.js +25 -0
- package/dist/web/hooks/use-open-file.js.map +1 -0
- package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
- package/dist/web/hooks/use-register-view-tool.js +50 -0
- package/dist/web/hooks/use-register-view-tool.js.map +1 -0
- package/dist/web/hooks/use-request-close.d.ts +16 -0
- package/dist/web/hooks/use-request-close.js +21 -0
- package/dist/web/hooks/use-request-close.js.map +1 -0
- package/dist/web/hooks/use-request-close.test.d.ts +1 -0
- package/dist/web/hooks/use-request-close.test.js +47 -0
- package/dist/web/hooks/use-request-close.test.js.map +1 -0
- package/dist/web/hooks/use-request-modal.d.ts +16 -1
- package/dist/web/hooks/use-request-modal.js +19 -4
- package/dist/web/hooks/use-request-modal.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +16 -2
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.d.ts +20 -0
- package/dist/web/hooks/use-request-size.js +24 -0
- package/dist/web/hooks/use-request-size.js.map +1 -0
- package/dist/web/hooks/use-request-size.test.d.ts +1 -0
- package/dist/web/hooks/use-request-size.test.js +47 -0
- package/dist/web/hooks/use-request-size.test.js.map +1 -0
- package/dist/web/hooks/use-send-follow-up-message.d.ts +25 -1
- package/dist/web/hooks/use-send-follow-up-message.js +25 -2
- package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.d.ts +17 -0
- package/dist/web/hooks/use-set-open-in-app-url.js +17 -0
- package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +26 -12
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +46 -14
- package/dist/web/hooks/use-tool-info.js +29 -7
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +11 -34
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +43 -38
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +5 -2
- package/dist/web/hooks/use-user.js +23 -4
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +105 -29
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.d.ts +25 -0
- package/dist/web/hooks/use-view-state.js +42 -0
- package/dist/web/hooks/use-view-state.js.map +1 -0
- package/dist/web/hooks/use-view-state.test.d.ts +1 -0
- package/dist/web/hooks/use-view-state.test.js +212 -0
- package/dist/web/hooks/use-view-state.test.js.map +1 -0
- 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-viewport.test.js +109 -0
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/web/index.d.ts +1 -2
- package/dist/web/index.js +1 -2
- package/dist/web/index.js.map +1 -1
- package/dist/web/mount-view.d.ts +21 -0
- package/dist/web/mount-view.js +43 -0
- package/dist/web/mount-view.js.map +1 -0
- package/dist/web/proxy.js.map +1 -1
- package/dist/web/types.d.ts +4 -0
- package/dist/web/types.js.map +1 -1
- package/package.json +50 -28
- package/tsconfig.base.json +5 -0
- package/dist/server/const.d.ts +0 -1
- package/dist/server/const.js +0 -2
- package/dist/server/const.js.map +0 -1
- package/dist/server/templates/development.hbs +0 -67
- package/dist/server/templates/production.hbs +0 -6
- package/dist/server/widgetsDevServer.d.ts +0 -12
- package/dist/server/widgetsDevServer.js +0 -63
- package/dist/server/widgetsDevServer.js.map +0 -1
- package/dist/test/widget.test.js +0 -261
- package/dist/test/widget.test.js.map +0 -1
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -22
- package/dist/web/bridges/apps-sdk/adaptor.js +0 -75
- package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -36
- package/dist/web/bridges/mcp-app/adaptor.js +0 -190
- package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
- package/dist/web/hooks/use-layout.d.ts +0 -22
- package/dist/web/hooks/use-layout.js +0 -23
- package/dist/web/hooks/use-layout.js.map +0 -1
- package/dist/web/hooks/use-layout.test.js +0 -96
- package/dist/web/hooks/use-layout.test.js.map +0 -1
- package/dist/web/hooks/use-widget-state.d.ts +0 -4
- package/dist/web/hooks/use-widget-state.js +0 -32
- package/dist/web/hooks/use-widget-state.js.map +0 -1
- package/dist/web/hooks/use-widget-state.test.js +0 -64
- package/dist/web/hooks/use-widget-state.test.js.map +0 -1
- package/dist/web/mount-widget.d.ts +0 -1
- package/dist/web/mount-widget.js +0 -27
- package/dist/web/mount-widget.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 -2
- package/dist/web/plugin/plugin.js +0 -54
- package/dist/web/plugin/plugin.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-widget.d.ts +0 -5
- package/dist/web/plugin/validate-widget.js +0 -27
- package/dist/web/plugin/validate-widget.js.map +0 -1
- package/dist/web/plugin/validate-widget.test.js +0 -42
- package/dist/web/plugin/validate-widget.test.js.map +0 -1
- /package/dist/{test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
- /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
- /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
- /package/dist/{web/plugin/data-llm.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
- /package/dist/{web/plugin/transform-data-llm.test.d.ts → cli/tunnel.test.d.ts} +0 -0
- /package/dist/{web/plugin/validate-widget.test.d.ts → context-warnings.test.d.ts} +0 -0
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import superjson, {} from "superjson";
|
|
2
2
|
import { getAdaptor } from "../bridges/index.js";
|
|
3
|
-
import {
|
|
4
|
-
export function
|
|
3
|
+
import { VIEW_CONTEXT_KEY } from "../data-llm.js";
|
|
4
|
+
export function filterViewContext(state) {
|
|
5
5
|
if (state === null || state === undefined) {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
|
-
const { [
|
|
8
|
+
const { [VIEW_CONTEXT_KEY]: _, ...filteredState } = state;
|
|
9
9
|
return filteredState;
|
|
10
10
|
}
|
|
11
|
-
export function
|
|
11
|
+
export function injectViewContext(newState) {
|
|
12
12
|
if (newState === null) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
const currentState = getAdaptor()
|
|
16
|
-
.getHostContextStore("
|
|
16
|
+
.getHostContextStore("viewState")
|
|
17
17
|
.getSnapshot();
|
|
18
18
|
if (currentState !== null &&
|
|
19
19
|
currentState !== undefined &&
|
|
20
|
-
|
|
20
|
+
VIEW_CONTEXT_KEY in currentState) {
|
|
21
21
|
return {
|
|
22
22
|
...newState,
|
|
23
|
-
[
|
|
23
|
+
[VIEW_CONTEXT_KEY]: currentState[VIEW_CONTEXT_KEY],
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
return newState;
|
|
@@ -32,11 +32,11 @@ export function deserializeState(value) {
|
|
|
32
32
|
return superjson.deserialize(value);
|
|
33
33
|
}
|
|
34
34
|
export function getInitialState(defaultState) {
|
|
35
|
-
const
|
|
36
|
-
.getHostContextStore("
|
|
35
|
+
const viewState = getAdaptor()
|
|
36
|
+
.getHostContextStore("viewState")
|
|
37
37
|
.getSnapshot();
|
|
38
|
-
if (
|
|
39
|
-
return
|
|
38
|
+
if (viewState !== null && viewState !== undefined) {
|
|
39
|
+
return filterViewContext(viewState);
|
|
40
40
|
}
|
|
41
41
|
return typeof defaultState === "function"
|
|
42
42
|
? defaultState()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/web/helpers/state.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAwB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/web/helpers/state.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAwB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,MAAM,UAAU,iBAAiB,CAC/B,KAAgB;IAEhB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,GAAG,aAAa,EAAE,GAAG,KAEnD,CAAC;IAEF,OAAO,aAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAkB;IAElB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,EAAE;SAC9B,mBAAmB,CAAC,WAAW,CAAC;SAChC,WAAW,EAAmD,CAAC;IAElE,IACE,YAAY,KAAK,IAAI;QACrB,YAAY,KAAK,SAAS;QAC1B,gBAAgB,IAAI,YAAY,EAChC,CAAC;QACD,OAAO;YACL,GAAG,QAAQ;YACX,CAAC,gBAAgB,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC;SAC9C,CAAC;IACT,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,OAAO,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB;AACzE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAsB;IACrD,OAAO,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,YAAoC;IAEpC,MAAM,SAAS,GAAG,UAAU,EAAE;SAC3B,mBAAmB,CAAC,WAAW,CAAC;SAChC,WAAW,EAAkB,CAAC;IAEjC,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAClD,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,OAAO,YAAY,KAAK,UAAU;QACvC,CAAC,CAAC,YAAY,EAAE;QAChB,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import superjson, { type SuperJSONResult } from \"superjson\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport { VIEW_CONTEXT_KEY } from \"../data-llm.js\";\nimport type { UnknownObject } from \"../types.js\";\n\nexport function filterViewContext<T extends UnknownObject>(\n state?: T | null,\n): T | null {\n if (state === null || state === undefined) {\n return null;\n }\n\n const { [VIEW_CONTEXT_KEY]: _, ...filteredState } = state as T & {\n [VIEW_CONTEXT_KEY]?: unknown;\n };\n\n return filteredState as T;\n}\n\nexport function injectViewContext<T extends UnknownObject>(\n newState: T | null,\n): T | null {\n if (newState === null) {\n return null;\n }\n\n const currentState = getAdaptor()\n .getHostContextStore(\"viewState\")\n .getSnapshot() as (T & { [VIEW_CONTEXT_KEY]?: unknown }) | null;\n\n if (\n currentState !== null &&\n currentState !== undefined &&\n VIEW_CONTEXT_KEY in currentState\n ) {\n return {\n ...newState,\n [VIEW_CONTEXT_KEY]: currentState[VIEW_CONTEXT_KEY],\n } as T;\n }\n\n return newState;\n}\n\nexport function serializeState(value: UnknownObject) {\n return superjson.parse(superjson.stringify(value)); // Strips functions\n}\n\nexport function deserializeState(value: SuperJSONResult): unknown {\n return superjson.deserialize(value);\n}\n\nexport function getInitialState<State extends UnknownObject>(\n defaultState?: State | (() => State),\n): State | null {\n const viewState = getAdaptor()\n .getHostContextStore(\"viewState\")\n .getSnapshot() as State | null;\n\n if (viewState !== null && viewState !== undefined) {\n return filterViewContext(viewState);\n }\n\n return typeof defaultState === \"function\"\n ? defaultState()\n : (defaultState ?? null);\n}\n"]}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { VIEW_CONTEXT_KEY } from "../data-llm.js";
|
|
3
|
+
import { filterViewContext, serializeState } from "./state.js";
|
|
4
4
|
describe("state helpers", () => {
|
|
5
|
-
describe("
|
|
5
|
+
describe("filterViewContext", () => {
|
|
6
6
|
it("should return null when state is null", () => {
|
|
7
|
-
expect(
|
|
7
|
+
expect(filterViewContext(null)).toBe(null);
|
|
8
8
|
});
|
|
9
9
|
it("should return null when state is undefined", () => {
|
|
10
|
-
expect(
|
|
10
|
+
expect(filterViewContext(undefined)).toBe(null);
|
|
11
11
|
});
|
|
12
|
-
it("should correctly filter
|
|
12
|
+
it("should correctly filter VIEW_CONTEXT_KEY and preserve other properties", () => {
|
|
13
13
|
const stateWithContextAndOthers = {
|
|
14
14
|
a: 1,
|
|
15
15
|
b: "two",
|
|
16
16
|
c: { nested: true },
|
|
17
|
-
[
|
|
17
|
+
[VIEW_CONTEXT_KEY]: "context",
|
|
18
18
|
};
|
|
19
|
-
const filteredWithContextAndOthers =
|
|
19
|
+
const filteredWithContextAndOthers = filterViewContext(stateWithContextAndOthers);
|
|
20
20
|
expect(filteredWithContextAndOthers).toEqual({
|
|
21
21
|
a: 1,
|
|
22
22
|
b: "two",
|
|
23
23
|
c: { nested: true },
|
|
24
24
|
});
|
|
25
25
|
const stateNoContext = { count: 5, name: "test" };
|
|
26
|
-
const filteredNoContext =
|
|
26
|
+
const filteredNoContext = filterViewContext(stateNoContext);
|
|
27
27
|
expect(filteredNoContext).toEqual(stateNoContext);
|
|
28
28
|
});
|
|
29
29
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.test.js","sourceRoot":"","sources":["../../../src/web/helpers/state.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"state.test.js","sourceRoot":"","sources":["../../../src/web/helpers/state.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;YAChF,MAAM,yBAAyB,GAAG;gBAChC,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,KAAK;gBACR,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBACnB,CAAC,gBAAgB,CAAC,EAAE,SAAS;aAC9B,CAAC;YACF,MAAM,4BAA4B,GAAG,iBAAiB,CACpD,yBAAyB,CAC1B,CAAC;YACF,MAAM,CAAC,4BAA4B,CAAC,CAAC,OAAO,CAAC;gBAC3C,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,KAAK;gBACR,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;aACpB,CAAC,CAAC;YAEH,MAAM,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAClD,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC;YAC5D,MAAM,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG;gBACb,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,MAAM;gBACT,CAAC,EAAE,IAAI;gBACP,KAAK;gBACL,IAAI;gBACJ,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;aACvB,CAAC;YACF,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAEtC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACrB,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,MAAM;gBACT,CAAC,EAAE,IAAI;gBACP,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBAC/B,IAAI,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;aAC3C,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { VIEW_CONTEXT_KEY } from \"../data-llm.js\";\nimport { filterViewContext, serializeState } from \"./state.js\";\n\ndescribe(\"state helpers\", () => {\n describe(\"filterViewContext\", () => {\n it(\"should return null when state is null\", () => {\n expect(filterViewContext(null)).toBe(null);\n });\n\n it(\"should return null when state is undefined\", () => {\n expect(filterViewContext(undefined)).toBe(null);\n });\n\n it(\"should correctly filter VIEW_CONTEXT_KEY and preserve other properties\", () => {\n const stateWithContextAndOthers = {\n a: 1,\n b: \"two\",\n c: { nested: true },\n [VIEW_CONTEXT_KEY]: \"context\",\n };\n const filteredWithContextAndOthers = filterViewContext(\n stateWithContextAndOthers,\n );\n expect(filteredWithContextAndOthers).toEqual({\n a: 1,\n b: \"two\",\n c: { nested: true },\n });\n\n const stateNoContext = { count: 5, name: \"test\" };\n const filteredNoContext = filterViewContext(stateNoContext);\n expect(filteredNoContext).toEqual(stateNoContext);\n });\n });\n\n describe(\"serializeState\", () => {\n it(\"should serialize plain objects\", () => {\n const array = [1, \"two\", { three: 3 }];\n const date = new Date(\"2023-01-01T00:00:00Z\");\n const object = {\n a: 1,\n b: \"test\",\n c: true,\n array,\n date,\n function: () => \"test\",\n };\n const result = serializeState(object);\n\n expect(result).toEqual({\n a: 1,\n b: \"test\",\n c: true,\n array: [1, \"two\", { three: 3 }],\n date: new Date(\"2023-01-01T00:00:00.000Z\"),\n });\n });\n });\n});\n"]}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
export { type CallToolAsyncFn, type CallToolFn, type CallToolState, type SideEffects, useCallTool, } from "./use-call-tool.js";
|
|
2
|
+
export { useDeepLink } from "./use-deep-link.js";
|
|
2
3
|
export { useDisplayMode } from "./use-display-mode.js";
|
|
4
|
+
export { type DownloadFn, useDownload } from "./use-download.js";
|
|
5
|
+
export { type FileResourceState, useFileResource, } from "./use-file-resource.js";
|
|
3
6
|
export { useFiles } from "./use-files.js";
|
|
4
|
-
export { type
|
|
7
|
+
export { type Host, type HostInfo, type OpenAIHostCapabilities, useHost, } from "./use-host.js";
|
|
8
|
+
export { type ModelContextState, useModelContext, } from "./use-model-context.js";
|
|
5
9
|
export { type OpenExternalFn, useOpenExternal } from "./use-open-external.js";
|
|
10
|
+
export { useOpenFile } from "./use-open-file.js";
|
|
11
|
+
export { useRegisterViewTool } from "./use-register-view-tool.js";
|
|
12
|
+
export { type RequestCloseFn, useRequestClose } from "./use-request-close.js";
|
|
6
13
|
export { useRequestModal } from "./use-request-modal.js";
|
|
14
|
+
export { type RequestSizeFn, useRequestSize } from "./use-request-size.js";
|
|
7
15
|
export { useSendFollowUpMessage } from "./use-send-follow-up-message.js";
|
|
8
16
|
export { useSetOpenInAppUrl } from "./use-set-open-in-app-url.js";
|
|
9
17
|
export { useToolInfo } from "./use-tool-info.js";
|
|
10
18
|
export { type UserState, useUser } from "./use-user.js";
|
|
11
|
-
export {
|
|
19
|
+
export { useViewState } from "./use-view-state.js";
|
|
20
|
+
export { useViewport, type ViewportState } from "./use-viewport.js";
|
package/dist/web/hooks/index.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
export { useCallTool, } from "./use-call-tool.js";
|
|
2
|
+
export { useDeepLink } from "./use-deep-link.js";
|
|
2
3
|
export { useDisplayMode } from "./use-display-mode.js";
|
|
4
|
+
export { useDownload } from "./use-download.js";
|
|
5
|
+
export { useFileResource, } from "./use-file-resource.js";
|
|
3
6
|
export { useFiles } from "./use-files.js";
|
|
4
|
-
export {
|
|
7
|
+
export { useHost, } from "./use-host.js";
|
|
8
|
+
export { useModelContext, } from "./use-model-context.js";
|
|
5
9
|
export { useOpenExternal } from "./use-open-external.js";
|
|
10
|
+
export { useOpenFile } from "./use-open-file.js";
|
|
11
|
+
export { useRegisterViewTool } from "./use-register-view-tool.js";
|
|
12
|
+
export { useRequestClose } from "./use-request-close.js";
|
|
6
13
|
export { useRequestModal } from "./use-request-modal.js";
|
|
14
|
+
export { useRequestSize } from "./use-request-size.js";
|
|
7
15
|
export { useSendFollowUpMessage } from "./use-send-follow-up-message.js";
|
|
8
16
|
export { useSetOpenInAppUrl } from "./use-set-open-in-app-url.js";
|
|
9
17
|
export { useToolInfo } from "./use-tool-info.js";
|
|
10
18
|
export { useUser } from "./use-user.js";
|
|
11
|
-
export {
|
|
19
|
+
export { useViewState } from "./use-view-state.js";
|
|
20
|
+
export { useViewport } from "./use-viewport.js";
|
|
12
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/web/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/web/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAmB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAEL,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAIL,OAAO,GACR,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAuB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAuB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAsB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAkB,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC","sourcesContent":["export {\n type CallToolAsyncFn,\n type CallToolFn,\n type CallToolState,\n type SideEffects,\n useCallTool,\n} from \"./use-call-tool.js\";\nexport { useDeepLink } from \"./use-deep-link.js\";\nexport { useDisplayMode } from \"./use-display-mode.js\";\nexport { type DownloadFn, useDownload } from \"./use-download.js\";\nexport {\n type FileResourceState,\n useFileResource,\n} from \"./use-file-resource.js\";\nexport { useFiles } from \"./use-files.js\";\nexport {\n type Host,\n type HostInfo,\n type OpenAIHostCapabilities,\n useHost,\n} from \"./use-host.js\";\nexport {\n type ModelContextState,\n useModelContext,\n} from \"./use-model-context.js\";\nexport { type OpenExternalFn, useOpenExternal } from \"./use-open-external.js\";\nexport { useOpenFile } from \"./use-open-file.js\";\nexport { useRegisterViewTool } from \"./use-register-view-tool.js\";\nexport { type RequestCloseFn, useRequestClose } from \"./use-request-close.js\";\nexport { useRequestModal } from \"./use-request-modal.js\";\nexport { type RequestSizeFn, useRequestSize } from \"./use-request-size.js\";\nexport { useSendFollowUpMessage } from \"./use-send-follow-up-message.js\";\nexport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\nexport { useToolInfo } from \"./use-tool-info.js\";\nexport { type UserState, useUser } from \"./use-user.js\";\nexport { useViewState } from \"./use-view-state.js\";\nexport { useViewport, type ViewportState } from \"./use-viewport.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { act, 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/index.js";
|
|
5
|
+
import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
|
|
6
|
+
import { useDeepLink } from "./use-deep-link.js";
|
|
7
|
+
import { useModelContext } from "./use-model-context.js";
|
|
8
|
+
import { useViewState } from "./use-view-state.js";
|
|
9
|
+
async function notifyHostContext(params) {
|
|
10
|
+
await act(async () => {
|
|
11
|
+
window.dispatchEvent(new MessageEvent("message", {
|
|
12
|
+
source: window.parent,
|
|
13
|
+
data: {
|
|
14
|
+
jsonrpc: "2.0",
|
|
15
|
+
method: "ui/notifications/host-context-changed",
|
|
16
|
+
params,
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
describe("model context and deep links in the view", () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
vi.stubGlobal("openai", undefined);
|
|
24
|
+
vi.stubGlobal("skybridge", {});
|
|
25
|
+
vi.stubGlobal("ResizeObserver", MockResizeObserver);
|
|
26
|
+
localStorage.clear();
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
HostAdaptor.resetInstance();
|
|
30
|
+
McpAppBridge.resetInstance();
|
|
31
|
+
vi.unstubAllGlobals();
|
|
32
|
+
localStorage.clear();
|
|
33
|
+
});
|
|
34
|
+
it("merges model context with view state and drops it once the user removes it", async () => {
|
|
35
|
+
const postMessage = getMcpAppHostPostMessageMock({}, { hostCapabilities: { updateModelContext: {} } });
|
|
36
|
+
vi.stubGlobal("parent", { postMessage });
|
|
37
|
+
const { result } = renderHook(() => ({
|
|
38
|
+
model: useModelContext(),
|
|
39
|
+
view: useViewState({ tab: "a" }),
|
|
40
|
+
}));
|
|
41
|
+
await waitFor(() => expect(result.current.model.supported).toBe(true));
|
|
42
|
+
const content = [
|
|
43
|
+
{
|
|
44
|
+
type: "text",
|
|
45
|
+
text: "Selected ski",
|
|
46
|
+
_meta: { "openai/title": "Ski" },
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
const lastModelContext = () => postMessage.mock.calls
|
|
50
|
+
.map(([message]) => message)
|
|
51
|
+
.filter((message) => message.method === "ui/update-model-context")
|
|
52
|
+
.at(-1)?.params;
|
|
53
|
+
await act(async () => result.current.model.update({
|
|
54
|
+
content,
|
|
55
|
+
structuredContent: { ski: 1, tab: "x" },
|
|
56
|
+
}));
|
|
57
|
+
await act(async () => result.current.view[1]({ tab: "b" }));
|
|
58
|
+
expect(lastModelContext()).toEqual({
|
|
59
|
+
structuredContent: { ski: 1, tab: "b" },
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: JSON.stringify({ tab: "b" }),
|
|
64
|
+
annotations: { audience: ["assistant"] },
|
|
65
|
+
},
|
|
66
|
+
...content,
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
await notifyHostContext({
|
|
70
|
+
"openai/modelContext": { updateId: "one", content },
|
|
71
|
+
});
|
|
72
|
+
expect(result.current.model.context).toEqual({ updateId: "one", content });
|
|
73
|
+
await notifyHostContext({ "openai/modelContext": null });
|
|
74
|
+
expect(result.current.model.context).toBeNull();
|
|
75
|
+
await act(async () => result.current.view[1]({ tab: "c" }));
|
|
76
|
+
expect(lastModelContext()).toEqual({
|
|
77
|
+
structuredContent: { tab: "c" },
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: JSON.stringify({ tab: "c" }),
|
|
82
|
+
annotations: { audience: ["assistant"] },
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
it("rejects model context updates on hosts without the capability", async () => {
|
|
88
|
+
const postMessage = getMcpAppHostPostMessageMock();
|
|
89
|
+
vi.stubGlobal("parent", { postMessage });
|
|
90
|
+
const { result } = renderHook(useModelContext);
|
|
91
|
+
await expect(result.current.update({ content: [] })).rejects.toThrow("updateModelContext");
|
|
92
|
+
expect(result.current.supported).toBe(false);
|
|
93
|
+
expect(postMessage.mock.calls.some(([message]) => message.method === "ui/update-model-context")).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
it("reads app-relative deep links and ignores ones that leave the app", async () => {
|
|
96
|
+
vi.stubGlobal("parent", {
|
|
97
|
+
postMessage: getMcpAppHostPostMessageMock({
|
|
98
|
+
"openai/deepLink": { url: "/parts?tag=bolt" },
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
const { result } = renderHook(useDeepLink);
|
|
102
|
+
await waitFor(() => expect(result.current).toBe("/parts?tag=bolt"));
|
|
103
|
+
await notifyHostContext({ "openai/deepLink": { url: "//evil.test" } });
|
|
104
|
+
expect(result.current).toBeUndefined();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=openai-extensions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-extensions.test.js","sourceRoot":"","sources":["../../../src/web/hooks/openai-extensions.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, 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/index.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useDeepLink } from \"./use-deep-link.js\";\nimport { useModelContext } from \"./use-model-context.js\";\nimport { useViewState } from \"./use-view-state.js\";\n\nasync function notifyHostContext(params: Record<string, unknown>) {\n await act(async () => {\n window.dispatchEvent(\n new MessageEvent(\"message\", {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n method: \"ui/notifications/host-context-changed\",\n params,\n },\n }),\n );\n });\n}\n\ndescribe(\"model context and deep links in the view\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n localStorage.clear();\n });\n\n afterEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n localStorage.clear();\n });\n\n it(\"merges model context with view state and drops it once the user removes it\", async () => {\n const postMessage = getMcpAppHostPostMessageMock(\n {},\n { hostCapabilities: { updateModelContext: {} } },\n );\n vi.stubGlobal(\"parent\", { postMessage });\n const { result } = renderHook(() => ({\n model: useModelContext(),\n view: useViewState({ tab: \"a\" }),\n }));\n await waitFor(() => expect(result.current.model.supported).toBe(true));\n const content = [\n {\n type: \"text\" as const,\n text: \"Selected ski\",\n _meta: { \"openai/title\": \"Ski\" },\n },\n ];\n const lastModelContext = () =>\n postMessage.mock.calls\n .map(([message]) => message as { method: string; params?: unknown })\n .filter((message) => message.method === \"ui/update-model-context\")\n .at(-1)?.params;\n\n await act(async () =>\n result.current.model.update({\n content,\n structuredContent: { ski: 1, tab: \"x\" },\n }),\n );\n await act(async () => result.current.view[1]({ tab: \"b\" }));\n expect(lastModelContext()).toEqual({\n structuredContent: { ski: 1, tab: \"b\" },\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ tab: \"b\" }),\n annotations: { audience: [\"assistant\"] },\n },\n ...content,\n ],\n });\n\n await notifyHostContext({\n \"openai/modelContext\": { updateId: \"one\", content },\n });\n expect(result.current.model.context).toEqual({ updateId: \"one\", content });\n await notifyHostContext({ \"openai/modelContext\": null });\n expect(result.current.model.context).toBeNull();\n\n await act(async () => result.current.view[1]({ tab: \"c\" }));\n expect(lastModelContext()).toEqual({\n structuredContent: { tab: \"c\" },\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ tab: \"c\" }),\n annotations: { audience: [\"assistant\"] },\n },\n ],\n });\n });\n\n it(\"rejects model context updates on hosts without the capability\", async () => {\n const postMessage = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage });\n const { result } = renderHook(useModelContext);\n\n await expect(result.current.update({ content: [] })).rejects.toThrow(\n \"updateModelContext\",\n );\n expect(result.current.supported).toBe(false);\n expect(\n postMessage.mock.calls.some(\n ([message]) => message.method === \"ui/update-model-context\",\n ),\n ).toBe(false);\n });\n\n it(\"reads app-relative deep links and ignores ones that leave the app\", async () => {\n vi.stubGlobal(\"parent\", {\n postMessage: getMcpAppHostPostMessageMock({\n \"openai/deepLink\": { url: \"/parts?tag=bolt\" },\n }),\n });\n const { result } = renderHook(useDeepLink);\n await waitFor(() => expect(result.current).toBe(\"/parts?tag=bolt\"));\n\n await notifyHostContext({ \"openai/deepLink\": { url: \"//evil.test\" } });\n expect(result.current).toBeUndefined();\n });\n});\n"]}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { McpUiHostContext, McpUiToolResultNotification } from "@modelcontextprotocol/ext-apps";
|
|
1
|
+
import type { McpUiDownloadFileResult, McpUiHostCapabilities, McpUiHostContext, McpUiInitializeResult, McpUiToolResultNotification } from "@modelcontextprotocol/ext-apps";
|
|
2
2
|
export declare class MockResizeObserver {
|
|
3
3
|
observe(): void;
|
|
4
4
|
unobserve(): void;
|
|
5
5
|
disconnect(): void;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
7
|
+
export type McpAppHostMockOptions = {
|
|
8
|
+
hostCapabilities?: McpUiHostCapabilities;
|
|
9
|
+
downloadFileResult?: McpUiDownloadFileResult;
|
|
10
|
+
hostInfo?: McpUiInitializeResult["hostInfo"];
|
|
11
|
+
};
|
|
12
|
+
export declare const getMcpAppHostPostMessageMock: (initialContext?: McpUiHostContext, options?: McpAppHostMockOptions) => import("vitest").Mock<(message: {
|
|
8
13
|
method: string;
|
|
9
14
|
id: number;
|
|
10
15
|
}) => void>;
|
|
@@ -7,16 +7,17 @@ export class MockResizeObserver {
|
|
|
7
7
|
disconnect() { }
|
|
8
8
|
}
|
|
9
9
|
const DEFAULT_CONTEXT = {};
|
|
10
|
-
export const getMcpAppHostPostMessageMock = (initialContext = DEFAULT_CONTEXT) => vi.fn((message) => {
|
|
10
|
+
export const getMcpAppHostPostMessageMock = (initialContext = DEFAULT_CONTEXT, options = {}) => vi.fn((message) => {
|
|
11
11
|
switch (message.method) {
|
|
12
12
|
case "ui/initialize": {
|
|
13
13
|
const result = {
|
|
14
14
|
protocolVersion: "2025-06-18",
|
|
15
|
-
hostInfo: { name: "test-host", version: "1.0.0" },
|
|
16
|
-
hostCapabilities: {},
|
|
15
|
+
hostInfo: options.hostInfo ?? { name: "test-host", version: "1.0.0" },
|
|
16
|
+
hostCapabilities: options.hostCapabilities ?? {},
|
|
17
17
|
hostContext: initialContext,
|
|
18
18
|
};
|
|
19
19
|
act(() => fireEvent(window, new MessageEvent("message", {
|
|
20
|
+
source: window.parent,
|
|
20
21
|
data: {
|
|
21
22
|
jsonrpc: "2.0",
|
|
22
23
|
id: message.id,
|
|
@@ -27,6 +28,7 @@ export const getMcpAppHostPostMessageMock = (initialContext = DEFAULT_CONTEXT) =
|
|
|
27
28
|
}
|
|
28
29
|
case "ui/update-model-context": {
|
|
29
30
|
act(() => fireEvent(window, new MessageEvent("message", {
|
|
31
|
+
source: window.parent,
|
|
30
32
|
data: {
|
|
31
33
|
jsonrpc: "2.0",
|
|
32
34
|
id: message.id,
|
|
@@ -35,10 +37,22 @@ export const getMcpAppHostPostMessageMock = (initialContext = DEFAULT_CONTEXT) =
|
|
|
35
37
|
})));
|
|
36
38
|
break;
|
|
37
39
|
}
|
|
40
|
+
case "ui/download-file": {
|
|
41
|
+
act(() => fireEvent(window, new MessageEvent("message", {
|
|
42
|
+
source: window.parent,
|
|
43
|
+
data: {
|
|
44
|
+
jsonrpc: "2.0",
|
|
45
|
+
id: message.id,
|
|
46
|
+
result: options.downloadFileResult ?? {},
|
|
47
|
+
},
|
|
48
|
+
})));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
38
51
|
}
|
|
39
52
|
});
|
|
40
53
|
export const fireToolInputNotification = (args) => {
|
|
41
54
|
fireEvent(window, new MessageEvent("message", {
|
|
55
|
+
source: window.parent,
|
|
42
56
|
data: {
|
|
43
57
|
jsonrpc: "2.0",
|
|
44
58
|
method: "ui/notifications/tool-input",
|
|
@@ -50,6 +64,7 @@ export const fireToolInputNotification = (args) => {
|
|
|
50
64
|
};
|
|
51
65
|
export const fireToolResultNotification = (params) => {
|
|
52
66
|
fireEvent(window, new MessageEvent("message", {
|
|
67
|
+
source: window.parent,
|
|
53
68
|
data: {
|
|
54
69
|
jsonrpc: "2.0",
|
|
55
70
|
method: "ui/notifications/tool-result",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/web/hooks/test/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/web/hooks/test/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n McpUiDownloadFileResult,\n McpUiHostCapabilities,\n McpUiHostContext,\n McpUiInitializeResult,\n McpUiToolInputNotification,\n McpUiToolResultNotification,\n} from \"@modelcontextprotocol/ext-apps\";\nimport { fireEvent } from \"@testing-library/react\";\nimport { act } from \"react\";\nimport { vi } from \"vitest\";\n\nexport class MockResizeObserver {\n observe(): void {}\n unobserve(): void {}\n disconnect(): void {}\n}\n\nconst DEFAULT_CONTEXT: McpUiHostContext = {};\n\nexport type McpAppHostMockOptions = {\n hostCapabilities?: McpUiHostCapabilities;\n downloadFileResult?: McpUiDownloadFileResult;\n hostInfo?: McpUiInitializeResult[\"hostInfo\"];\n};\n\nexport const getMcpAppHostPostMessageMock = (\n initialContext: McpUiHostContext = DEFAULT_CONTEXT,\n options: McpAppHostMockOptions = {},\n) =>\n vi.fn((message: { method: string; id: number }) => {\n switch (message.method) {\n case \"ui/initialize\": {\n const result: McpUiInitializeResult = {\n protocolVersion: \"2025-06-18\",\n hostInfo: options.hostInfo ?? { name: \"test-host\", version: \"1.0.0\" },\n hostCapabilities: options.hostCapabilities ?? {},\n hostContext: initialContext,\n };\n act(() =>\n fireEvent(\n window,\n new MessageEvent<{\n jsonrpc: \"2.0\";\n id: number;\n result: McpUiInitializeResult;\n }>(\"message\", {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n id: message.id,\n result,\n },\n }),\n ),\n );\n break;\n }\n case \"ui/update-model-context\": {\n act(() =>\n fireEvent(\n window,\n new MessageEvent<{ jsonrpc: \"2.0\"; id: number; result: unknown }>(\n \"message\",\n {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n id: message.id,\n result: {},\n },\n },\n ),\n ),\n );\n break;\n }\n case \"ui/download-file\": {\n act(() =>\n fireEvent(\n window,\n new MessageEvent<{\n jsonrpc: \"2.0\";\n id: number;\n result: McpUiDownloadFileResult;\n }>(\"message\", {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n id: message.id,\n result: options.downloadFileResult ?? {},\n },\n }),\n ),\n );\n break;\n }\n }\n });\n\nexport const fireToolInputNotification = (args: Record<string, unknown>) => {\n fireEvent(\n window,\n new MessageEvent<McpUiToolInputNotification & { jsonrpc: \"2.0\" }>(\n \"message\",\n {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-input\",\n params: {\n arguments: args,\n },\n },\n },\n ),\n );\n};\n\nexport const fireToolResultNotification = (params: {\n content: McpUiToolResultNotification[\"params\"][\"content\"];\n structuredContent: Record<string, unknown>;\n _meta?: Record<string, unknown>;\n}) => {\n fireEvent(\n window,\n new MessageEvent<McpUiToolResultNotification & { jsonrpc: \"2.0\" }>(\n \"message\",\n {\n source: window.parent,\n data: {\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-result\",\n params,\n },\n },\n ),\n );\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CallToolArgs, type CallToolResponse } from "../bridges/index.js";
|
|
1
|
+
import { type CallToolArgs, type CallToolOptions, type CallToolResponse } from "../bridges/index.js";
|
|
2
2
|
import type { HasRequiredKeys } from "../types.js";
|
|
3
3
|
type CallToolIdleState = {
|
|
4
4
|
status: "idle";
|
|
@@ -36,13 +36,26 @@ type CallToolErrorState = {
|
|
|
36
36
|
data: undefined;
|
|
37
37
|
error: unknown;
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* State of a {@link useCallTool} invocation, discriminated by `status`.
|
|
41
|
+
* Use `isIdle` / `isPending` / `isSuccess` / `isError` for ergonomic conditional rendering.
|
|
42
|
+
*/
|
|
39
43
|
export type CallToolState<TData extends CallToolResponse = CallToolResponse> = CallToolIdleState | CallToolPendingState | CallToolSuccessState<TData> | CallToolErrorState;
|
|
44
|
+
/**
|
|
45
|
+
* Optional callbacks fired around a {@link useCallTool} call.
|
|
46
|
+
* `onSettled` runs after success or error.
|
|
47
|
+
*/
|
|
40
48
|
export type SideEffects<ToolArgs, ToolResponse> = {
|
|
41
49
|
onSuccess?: (data: ToolResponse, toolArgs: ToolArgs) => void;
|
|
42
50
|
onError?: (error: unknown, toolArgs: ToolArgs) => void;
|
|
43
51
|
onSettled?: (data: ToolResponse | undefined, error: unknown | undefined, toolArgs: ToolArgs) => void;
|
|
44
52
|
};
|
|
45
53
|
type IsArgsOptional<T> = [T] extends [null] ? true : HasRequiredKeys<T> extends false ? true : false;
|
|
54
|
+
/**
|
|
55
|
+
* Fire-and-forget call function returned by {@link useCallTool}. Tracks state
|
|
56
|
+
* on the hook and supports optional {@link SideEffects} callbacks. Args are
|
|
57
|
+
* optional when the tool accepts none.
|
|
58
|
+
*/
|
|
46
59
|
export type CallToolFn<TArgs, TResponse> = IsArgsOptional<TArgs> extends true ? {
|
|
47
60
|
(): void;
|
|
48
61
|
(sideEffects: SideEffects<TArgs, TResponse>): void;
|
|
@@ -52,12 +65,44 @@ export type CallToolFn<TArgs, TResponse> = IsArgsOptional<TArgs> extends true ?
|
|
|
52
65
|
(args: TArgs): void;
|
|
53
66
|
(args: TArgs, sideEffects: SideEffects<TArgs, TResponse>): void;
|
|
54
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* Promise-returning call function returned by {@link useCallTool}. Rejects
|
|
70
|
+
* if the tool errors; use `try/catch` for error handling.
|
|
71
|
+
*/
|
|
55
72
|
export type CallToolAsyncFn<TArgs, TResponse> = IsArgsOptional<TArgs> extends true ? {
|
|
56
73
|
(): Promise<TResponse>;
|
|
57
74
|
(args: TArgs): Promise<TResponse>;
|
|
58
75
|
} : (args: TArgs) => Promise<TResponse>;
|
|
59
76
|
type ToolResponseSignature = Pick<CallToolResponse, "structuredContent" | "meta">;
|
|
60
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Call a server tool from a view and track its execution state.
|
|
79
|
+
*
|
|
80
|
+
* Returns the current {@link CallToolState} plus two callers: `callTool`
|
|
81
|
+
* (fire-and-forget, with optional {@link SideEffects}) and `callToolAsync`
|
|
82
|
+
* (promise-returning). If the same instance is invoked again while a call is
|
|
83
|
+
* in flight, the older response is dropped from the rendered state (but any
|
|
84
|
+
* `onSuccess` / `onError` / `onSettled` callbacks attached to it still fire).
|
|
85
|
+
*
|
|
86
|
+
* Pair with {@link useToolInfo} to read the result of the tool invocation
|
|
87
|
+
* that produced the current view. For end-to-end type safety across tool
|
|
88
|
+
* inputs and outputs, prefer the typed helpers produced by {@link generateHelpers}
|
|
89
|
+
* over calling this hook directly.
|
|
90
|
+
*
|
|
91
|
+
* @typeParam ToolArgs - Shape of the tool's input args (`null` for no-arg tools).
|
|
92
|
+
* @typeParam ToolResponse - Shape of the tool's `structuredContent` / `meta`.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* const { callTool, isPending, data } = useCallTool<{ query: string }>("search");
|
|
97
|
+
*
|
|
98
|
+
* <button onClick={() => callTool({ query: "skybridge" }, {
|
|
99
|
+
* onSuccess: (res) => console.log(res.structuredContent),
|
|
100
|
+
* })} />
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @see https://docs.skybridge.tech/api-reference/use-call-tool
|
|
104
|
+
*/
|
|
105
|
+
export declare const useCallTool: <ToolArgs extends CallToolArgs = null, ToolResponse extends Partial<ToolResponseSignature> = Record<string, never>>(name: string, options?: CallToolOptions) => {
|
|
61
106
|
callTool: CallToolFn<ToolArgs, CallToolResponse & ToolResponse>;
|
|
62
107
|
callToolAsync: CallToolAsyncFn<ToolArgs, CallToolResponse & ToolResponse>;
|
|
63
108
|
status: "idle";
|
|
@@ -1,14 +1,47 @@
|
|
|
1
|
-
import { useRef, useState } from "react";
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
2
|
import { getAdaptor, } from "../bridges/index.js";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Call a server tool from a view and track its execution state.
|
|
5
|
+
*
|
|
6
|
+
* Returns the current {@link CallToolState} plus two callers: `callTool`
|
|
7
|
+
* (fire-and-forget, with optional {@link SideEffects}) and `callToolAsync`
|
|
8
|
+
* (promise-returning). If the same instance is invoked again while a call is
|
|
9
|
+
* in flight, the older response is dropped from the rendered state (but any
|
|
10
|
+
* `onSuccess` / `onError` / `onSettled` callbacks attached to it still fire).
|
|
11
|
+
*
|
|
12
|
+
* Pair with {@link useToolInfo} to read the result of the tool invocation
|
|
13
|
+
* that produced the current view. For end-to-end type safety across tool
|
|
14
|
+
* inputs and outputs, prefer the typed helpers produced by {@link generateHelpers}
|
|
15
|
+
* over calling this hook directly.
|
|
16
|
+
*
|
|
17
|
+
* @typeParam ToolArgs - Shape of the tool's input args (`null` for no-arg tools).
|
|
18
|
+
* @typeParam ToolResponse - Shape of the tool's `structuredContent` / `meta`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { callTool, isPending, data } = useCallTool<{ query: string }>("search");
|
|
23
|
+
*
|
|
24
|
+
* <button onClick={() => callTool({ query: "skybridge" }, {
|
|
25
|
+
* onSuccess: (res) => console.log(res.structuredContent),
|
|
26
|
+
* })} />
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see https://docs.skybridge.tech/api-reference/use-call-tool
|
|
30
|
+
*/
|
|
31
|
+
export const useCallTool = (name, options) => {
|
|
4
32
|
const [{ status, data, error }, setCallToolState] = useState({ status: "idle", data: undefined, error: undefined });
|
|
5
33
|
const callIdRef = useRef(0);
|
|
6
34
|
const adaptor = getAdaptor();
|
|
7
|
-
const
|
|
35
|
+
const timeout = options?.timeout;
|
|
36
|
+
const execute = useCallback(async (toolArgs) => {
|
|
8
37
|
const callId = ++callIdRef.current;
|
|
9
|
-
setCallToolState({
|
|
38
|
+
setCallToolState({
|
|
39
|
+
status: "pending",
|
|
40
|
+
data: undefined,
|
|
41
|
+
error: undefined,
|
|
42
|
+
});
|
|
10
43
|
try {
|
|
11
|
-
const data = await adaptor.callTool(name, toolArgs);
|
|
44
|
+
const data = await adaptor.callTool(name, toolArgs, { timeout });
|
|
12
45
|
if (callId === callIdRef.current) {
|
|
13
46
|
setCallToolState({ status: "success", data, error: undefined });
|
|
14
47
|
}
|
|
@@ -20,14 +53,14 @@ export const useCallTool = (name) => {
|
|
|
20
53
|
}
|
|
21
54
|
throw error;
|
|
22
55
|
}
|
|
23
|
-
};
|
|
24
|
-
const callToolAsync = ((toolArgs) => {
|
|
56
|
+
}, [adaptor, name, timeout]);
|
|
57
|
+
const callToolAsync = useCallback((toolArgs) => {
|
|
25
58
|
if (toolArgs === undefined) {
|
|
26
59
|
return execute(null);
|
|
27
60
|
}
|
|
28
61
|
return execute(toolArgs);
|
|
29
|
-
});
|
|
30
|
-
const callTool = ((firstArg, sideEffects) => {
|
|
62
|
+
}, [execute]);
|
|
63
|
+
const callTool = useCallback((firstArg, sideEffects) => {
|
|
31
64
|
let toolArgs;
|
|
32
65
|
if (firstArg &&
|
|
33
66
|
typeof firstArg === "object" &&
|
|
@@ -49,7 +82,7 @@ export const useCallTool = (name) => {
|
|
|
49
82
|
sideEffects?.onError?.(error, toolArgs);
|
|
50
83
|
sideEffects?.onSettled?.(undefined, error, toolArgs);
|
|
51
84
|
});
|
|
52
|
-
});
|
|
85
|
+
}, [execute]);
|
|
53
86
|
const callToolState = {
|
|
54
87
|
status,
|
|
55
88
|
data,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-call-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-call-tool.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-call-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-call-tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nimport {\n type CallToolArgs,\n type CallToolOptions,\n type CallToolResponse,\n getAdaptor,\n} from \"../bridges/index.js\";\nimport type { HasRequiredKeys } from \"../types.js\";\n\ntype CallToolIdleState = {\n status: \"idle\";\n isIdle: true;\n isPending: false;\n isSuccess: false;\n isError: false;\n data: undefined;\n error: undefined;\n};\n\ntype CallToolPendingState = {\n status: \"pending\";\n isIdle: false;\n isPending: true;\n isSuccess: false;\n isError: false;\n data: undefined;\n error: undefined;\n};\n\ntype CallToolSuccessState<TData extends CallToolResponse = CallToolResponse> = {\n status: \"success\";\n isIdle: false;\n isPending: false;\n isSuccess: true;\n isError: false;\n data: TData;\n error: undefined;\n};\n\ntype CallToolErrorState = {\n status: \"error\";\n isIdle: false;\n isPending: false;\n isSuccess: false;\n isError: true;\n data: undefined;\n error: unknown;\n};\n\n/**\n * State of a {@link useCallTool} invocation, discriminated by `status`.\n * Use `isIdle` / `isPending` / `isSuccess` / `isError` for ergonomic conditional rendering.\n */\nexport type CallToolState<TData extends CallToolResponse = CallToolResponse> =\n | CallToolIdleState\n | CallToolPendingState\n | CallToolSuccessState<TData>\n | CallToolErrorState;\n\n/**\n * Optional callbacks fired around a {@link useCallTool} call.\n * `onSettled` runs after success or error.\n */\nexport type SideEffects<ToolArgs, ToolResponse> = {\n onSuccess?: (data: ToolResponse, toolArgs: ToolArgs) => void;\n onError?: (error: unknown, toolArgs: ToolArgs) => void;\n onSettled?: (\n data: ToolResponse | undefined,\n error: unknown | undefined,\n toolArgs: ToolArgs,\n ) => void;\n};\n\ntype IsArgsOptional<T> = [T] extends [null]\n ? true\n : HasRequiredKeys<T> extends false\n ? true\n : false;\n\n/**\n * Fire-and-forget call function returned by {@link useCallTool}. Tracks state\n * on the hook and supports optional {@link SideEffects} callbacks. Args are\n * optional when the tool accepts none.\n */\nexport type CallToolFn<TArgs, TResponse> =\n IsArgsOptional<TArgs> extends true\n ? {\n (): void;\n (sideEffects: SideEffects<TArgs, TResponse>): void;\n (args: TArgs): void;\n (args: TArgs, sideEffects: SideEffects<TArgs, TResponse>): void;\n }\n : {\n (args: TArgs): void;\n (args: TArgs, sideEffects: SideEffects<TArgs, TResponse>): void;\n };\n\n/**\n * Promise-returning call function returned by {@link useCallTool}. Rejects\n * if the tool errors; use `try/catch` for error handling.\n */\nexport type CallToolAsyncFn<TArgs, TResponse> =\n IsArgsOptional<TArgs> extends true\n ? {\n (): Promise<TResponse>;\n (args: TArgs): Promise<TResponse>;\n }\n : (args: TArgs) => Promise<TResponse>;\n\ntype ToolResponseSignature = Pick<\n CallToolResponse,\n \"structuredContent\" | \"meta\"\n>;\n\n/**\n * Call a server tool from a view and track its execution state.\n *\n * Returns the current {@link CallToolState} plus two callers: `callTool`\n * (fire-and-forget, with optional {@link SideEffects}) and `callToolAsync`\n * (promise-returning). If the same instance is invoked again while a call is\n * in flight, the older response is dropped from the rendered state (but any\n * `onSuccess` / `onError` / `onSettled` callbacks attached to it still fire).\n *\n * Pair with {@link useToolInfo} to read the result of the tool invocation\n * that produced the current view. For end-to-end type safety across tool\n * inputs and outputs, prefer the typed helpers produced by {@link generateHelpers}\n * over calling this hook directly.\n *\n * @typeParam ToolArgs - Shape of the tool's input args (`null` for no-arg tools).\n * @typeParam ToolResponse - Shape of the tool's `structuredContent` / `meta`.\n *\n * @example\n * ```tsx\n * const { callTool, isPending, data } = useCallTool<{ query: string }>(\"search\");\n *\n * <button onClick={() => callTool({ query: \"skybridge\" }, {\n * onSuccess: (res) => console.log(res.structuredContent),\n * })} />\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-call-tool\n */\nexport const useCallTool = <\n ToolArgs extends CallToolArgs = null,\n ToolResponse extends Partial<ToolResponseSignature> = Record<string, never>,\n>(\n name: string,\n options?: CallToolOptions,\n) => {\n type CombinedCallToolResponse = CallToolResponse & ToolResponse;\n\n const [{ status, data, error }, setCallToolState] = useState<\n Omit<\n CallToolState<CombinedCallToolResponse>,\n \"isIdle\" | \"isPending\" | \"isSuccess\" | \"isError\"\n >\n >({ status: \"idle\", data: undefined, error: undefined });\n\n const callIdRef = useRef(0);\n const adaptor = getAdaptor();\n const timeout = options?.timeout;\n\n const execute = useCallback(\n async (toolArgs: ToolArgs): Promise<CombinedCallToolResponse> => {\n const callId = ++callIdRef.current;\n setCallToolState({\n status: \"pending\",\n data: undefined,\n error: undefined,\n });\n\n try {\n const data = await adaptor.callTool<ToolArgs, CombinedCallToolResponse>(\n name,\n toolArgs,\n { timeout },\n );\n if (callId === callIdRef.current) {\n setCallToolState({ status: \"success\", data, error: undefined });\n }\n\n return data;\n } catch (error) {\n if (callId === callIdRef.current) {\n setCallToolState({ status: \"error\", data: undefined, error });\n }\n throw error;\n }\n },\n [adaptor, name, timeout],\n );\n\n const callToolAsync = useCallback(\n (toolArgs?: ToolArgs) => {\n if (toolArgs === undefined) {\n return execute(null as ToolArgs);\n }\n return execute(toolArgs);\n },\n [execute],\n ) as CallToolAsyncFn<ToolArgs, CombinedCallToolResponse>;\n\n const callTool = useCallback(\n (\n firstArg?: ToolArgs | SideEffects<ToolArgs, CombinedCallToolResponse>,\n sideEffects?: SideEffects<ToolArgs, CombinedCallToolResponse>,\n ) => {\n let toolArgs: ToolArgs;\n if (\n firstArg &&\n typeof firstArg === \"object\" &&\n (\"onSuccess\" in firstArg ||\n \"onError\" in firstArg ||\n \"onSettled\" in firstArg)\n ) {\n toolArgs = null as ToolArgs; // no toolArgs provided\n sideEffects = firstArg;\n } else {\n toolArgs = (firstArg === undefined ? null : firstArg) as ToolArgs;\n }\n\n execute(toolArgs)\n .then((data) => {\n sideEffects?.onSuccess?.(data, toolArgs);\n sideEffects?.onSettled?.(data, undefined, toolArgs);\n })\n .catch((error) => {\n sideEffects?.onError?.(error, toolArgs);\n sideEffects?.onSettled?.(undefined, error, toolArgs);\n });\n },\n [execute],\n ) as CallToolFn<ToolArgs, CombinedCallToolResponse>;\n\n const callToolState = {\n status,\n data,\n error,\n isIdle: status === \"idle\",\n isPending: status === \"pending\",\n isSuccess: status === \"success\",\n isError: status === \"error\",\n } as CallToolState<CombinedCallToolResponse>;\n\n return {\n ...callToolState,\n callTool,\n callToolAsync,\n };\n};\n"]}
|