skybridge 0.0.0-dev.8490ca2 → 0.0.0-dev.84c5e86
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 +123 -116
- package/dist/cli/detect-port.d.ts +18 -0
- package/dist/cli/detect-port.js +61 -0
- package/dist/cli/detect-port.js.map +1 -0
- package/dist/cli/header.js +1 -1
- package/dist/cli/header.js.map +1 -1
- package/dist/cli/resolve-views-dir.d.ts +1 -0
- package/dist/cli/resolve-views-dir.js +17 -0
- package/dist/cli/resolve-views-dir.js.map +1 -0
- package/dist/cli/run-command.js.map +1 -1
- 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.d.ts +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.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 +2 -6
- package/dist/cli/use-nodemon.js +18 -14
- 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 +1 -0
- package/dist/cli/use-typescript-check.js +42 -7
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.js +48 -7
- 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 +73 -8
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.d.ts +3 -1
- package/dist/commands/start.js +28 -12
- 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/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.d.ts +20 -0
- package/dist/server/auth.js +28 -0
- package/dist/server/auth.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/express.d.ts +7 -5
- package/dist/server/express.js +55 -23
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +381 -25
- 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/index.d.ts +7 -3
- package/dist/server/index.js +5 -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/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 +137 -0
- package/dist/server/middleware.js +93 -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 +493 -0
- package/dist/server/middleware.test.js.map +1 -0
- package/dist/server/server.d.ts +357 -64
- package/dist/server/server.js +469 -102
- package/dist/server/server.js.map +1 -1
- package/dist/server/templateHelper.d.ts +5 -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 +47 -0
- package/dist/server/templates.generated.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/viewsDevServer.d.ts +14 -0
- package/dist/server/viewsDevServer.js +45 -0
- package/dist/server/viewsDevServer.js.map +1 -0
- package/dist/test/utils.d.ts +13 -21
- package/dist/test/utils.js +42 -37
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.d.ts +1 -0
- package/dist/test/view.test.js +568 -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/web/bridges/adaptor.d.ts +45 -0
- package/dist/web/bridges/adaptor.js +302 -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 +375 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +2 -1
- package/dist/web/bridges/apps-sdk/bridge.js +3 -3
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +1 -2
- 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 +26 -11
- 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 +9 -0
- package/dist/web/bridges/get-adaptor.js +26 -5
- 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 +48 -0
- package/dist/web/bridges/get-adaptor.test.js.map +1 -0
- package/dist/web/bridges/host-context-stores.d.ts +27 -0
- package/dist/web/bridges/host-context-stores.js +73 -0
- package/dist/web/bridges/host-context-stores.js.map +1 -0
- package/dist/web/bridges/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.d.ts +14 -30
- package/dist/web/bridges/mcp-app/bridge.js +43 -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 +21 -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.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 +1 -41
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +102 -14
- 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.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 +28 -23
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +34 -1
- package/dist/web/data-llm.js +31 -3
- package/dist/web/data-llm.js.map +1 -1
- package/dist/web/data-llm.test.js +32 -28
- 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 +22 -18
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +26 -26
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- 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 +5 -2
- package/dist/web/hooks/index.js +4 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.d.ts +6 -2
- package/dist/web/hooks/test/utils.js +17 -2
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.d.ts +45 -0
- package/dist/web/hooks/use-call-tool.js +28 -0
- 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 +61 -27
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +23 -3
- 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.d.ts +1 -0
- package/dist/web/hooks/use-display-mode.test-d.js +8 -0
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
- package/dist/web/hooks/use-display-mode.test.js +55 -20
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +5 -0
- package/dist/web/hooks/use-download.js +8 -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-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 +30 -2
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-layout.d.ts +2 -0
- package/dist/web/hooks/use-layout.js +2 -0
- package/dist/web/hooks/use-layout.js.map +1 -1
- package/dist/web/hooks/use-layout.test.js +62 -29
- package/dist/web/hooks/use-layout.test.js.map +1 -1
- package/dist/web/hooks/use-open-external.d.ts +20 -1
- package/dist/web/hooks/use-open-external.js +17 -1
- package/dist/web/hooks/use-open-external.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js +43 -14
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- 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 +46 -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 +15 -1
- 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 +19 -1
- package/dist/web/hooks/use-send-follow-up-message.js +19 -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 +28 -14
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +33 -0
- package/dist/web/hooks/use-tool-info.js +26 -0
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +38 -28
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +2 -0
- package/dist/web/hooks/use-user.js +20 -2
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +101 -27
- 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 +32 -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 +181 -0
- package/dist/web/hooks/use-view-state.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 +20 -0
- package/dist/web/{mount-widget.js → mount-view.js} +21 -2
- package/dist/web/mount-view.js.map +1 -0
- package/dist/web/plugin/data-llm.test.js.map +1 -1
- package/dist/web/plugin/plugin.d.ts +32 -1
- package/dist/web/plugin/plugin.js +161 -18
- package/dist/web/plugin/plugin.js.map +1 -1
- package/dist/web/plugin/scan-views.d.ts +16 -0
- package/dist/web/plugin/scan-views.js +88 -0
- package/dist/web/plugin/scan-views.js.map +1 -0
- package/dist/web/plugin/scan-views.test.d.ts +1 -0
- package/dist/web/plugin/scan-views.test.js +99 -0
- package/dist/web/plugin/scan-views.test.js.map +1 -0
- package/dist/web/plugin/transform-data-llm.js +1 -1
- package/dist/web/plugin/transform-data-llm.js.map +1 -1
- package/dist/web/plugin/transform-data-llm.test.js.map +1 -1
- package/dist/web/plugin/validate-view.d.ts +1 -0
- package/dist/web/plugin/validate-view.js +9 -0
- package/dist/web/plugin/validate-view.js.map +1 -0
- package/dist/web/plugin/validate-view.test.d.ts +1 -0
- package/dist/web/plugin/validate-view.test.js +24 -0
- package/dist/web/plugin/validate-view.test.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 +38 -24
- package/tsconfig.base.json +5 -0
- 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 -57
- 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 -80
- 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-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 -62
- 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.map +0 -1
- /package/dist/{test/widget.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
- /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import { App } from \"@modelcontextprotocol/ext-apps\";\nimport type { Implementation } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Bridge, Subscribe } from \"../types.js\";\nimport type { McpAppContext, McpAppContextKey } from \"./types.js\";\n\n/** @internal Singleton bridge over the `ext-apps` JSON-RPC App connection. Used by `HostAdaptor`. */\nexport class McpAppBridge implements Bridge<McpAppContext> {\n private static instance: McpAppBridge | null = null;\n public context: McpAppContext = {\n toolInput: null,\n toolCancelled: null,\n toolResult: null,\n };\n private listeners = new Map<McpAppContextKey, Set<() => void>>();\n private app: App;\n private connectPromise: Promise<void>;\n\n constructor(options: { appInfo: Implementation }) {\n this.app = new App(options.appInfo);\n\n this.app.ontoolinput = (params) => {\n this.updateContext({ toolInput: params.arguments ?? {} });\n };\n\n this.app.ontoolinputpartial = (params) => {\n this.updateContext({ toolInput: params.arguments ?? {} });\n };\n\n this.app.ontoolresult = (params) => {\n this.updateContext({ toolResult: params });\n };\n\n this.app.ontoolcancelled = (params) => {\n this.updateContext({ toolCancelled: params });\n };\n\n this.app.onhostcontextchanged = (params) => {\n this.updateContext(params);\n };\n\n this.connectPromise = this.connect();\n }\n\n private async connect() {\n try {\n await this.app.connect();\n const hostContext = this.app.getHostContext();\n if (hostContext) {\n this.updateContext(hostContext);\n }\n } catch (err) {\n console.error(err);\n }\n }\n\n public async getApp(): Promise<App> {\n await this.connectPromise;\n return this.app;\n }\n\n public static getInstance(\n options?: Partial<{ appInfo: Implementation }>,\n ): McpAppBridge {\n if (McpAppBridge.instance && options) {\n console.warn(\n \"McpAppBridge.getInstance: options ignored, instance already exists\",\n );\n }\n if (!McpAppBridge.instance) {\n const defaultOptions = {\n appInfo: { name: \"skybridge-app\", version: \"0.0.1\" },\n };\n McpAppBridge.instance = new McpAppBridge({\n ...defaultOptions,\n ...options,\n });\n }\n return McpAppBridge.instance;\n }\n\n public subscribe(key: McpAppContextKey): Subscribe;\n public subscribe(keys: readonly McpAppContextKey[]): Subscribe;\n public subscribe(\n keyOrKeys: McpAppContextKey | readonly McpAppContextKey[],\n ): Subscribe {\n const keys = Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];\n return (onChange: () => void) => {\n for (const key of keys) {\n this.listeners.set(\n key,\n new Set([...(this.listeners.get(key) || []), onChange]),\n );\n }\n return () => {\n for (const key of keys) {\n this.listeners.get(key)?.delete(onChange);\n }\n };\n };\n }\n\n public getSnapshot<K extends keyof McpAppContext>(key: K): McpAppContext[K] {\n return this.context[key];\n }\n\n public cleanup = () => {\n this.listeners.clear();\n };\n\n public static resetInstance(): void {\n if (McpAppBridge.instance) {\n McpAppBridge.instance.cleanup();\n McpAppBridge.instance = null;\n }\n }\n\n private emit(key: McpAppContextKey) {\n this.listeners.get(key)?.forEach((listener) => {\n listener();\n });\n }\n\n private updateContext(context: Partial<McpAppContext>) {\n this.context = { ...this.context, ...context };\n for (const key of Object.keys(context)) {\n this.emit(key);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { McpAppBridge } from "./bridge.js";
|
|
3
|
+
describe("McpAppBridge.getInstance", () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
McpAppBridge.resetInstance();
|
|
6
|
+
vi.stubGlobal("parent", { postMessage: vi.fn() });
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
vi.unstubAllGlobals();
|
|
10
|
+
McpAppBridge.resetInstance();
|
|
11
|
+
});
|
|
12
|
+
it("instantiates when hostType is apps-sdk", () => {
|
|
13
|
+
vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
|
|
14
|
+
expect(() => McpAppBridge.getInstance()).not.toThrow();
|
|
15
|
+
});
|
|
16
|
+
it("instantiates when hostType is mcp-app", () => {
|
|
17
|
+
vi.stubGlobal("skybridge", { hostType: "mcp-app" });
|
|
18
|
+
expect(() => McpAppBridge.getInstance()).not.toThrow();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=bridge.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.test.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/bridge.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,UAAU,CAAC,GAAG,EAAE;QACd,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { McpAppBridge } from \"./bridge.js\";\n\ndescribe(\"McpAppBridge.getInstance\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n });\n\n it(\"instantiates when hostType is apps-sdk\", () => {\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n expect(() => McpAppBridge.getInstance()).not.toThrow();\n });\n\n it(\"instantiates when hostType is mcp-app\", () => {\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n expect(() => McpAppBridge.getInstance()).not.toThrow();\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["export { McpAppBridge } from \"./bridge.js\";\nexport type {\n McpAppContext,\n McpAppContextKey,\n McpToolState,\n} from \"./types.js\";\nexport { useMcpAppContext } from \"./use-mcp-app-context.js\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n McpUiHostContext,\n McpUiToolCancelledNotification,\n McpUiToolInputNotification,\n McpUiToolResultNotification,\n} from \"@modelcontextprotocol/ext-apps\";\n\nexport type McpToolState = {\n toolInput: NonNullable<\n McpUiToolInputNotification[\"params\"][\"arguments\"]\n > | null;\n toolResult: McpUiToolResultNotification[\"params\"] | null;\n toolCancelled: McpUiToolCancelledNotification[\"params\"] | null;\n};\n\nexport type McpAppContext = McpUiHostContext & McpToolState;\n\nexport type McpAppContextKey = keyof McpAppContext;\n"]}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Implementation } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import type { McpAppContext } from "./types.js";
|
|
3
|
-
type McpAppInitializationOptions =
|
|
4
|
-
|
|
3
|
+
type McpAppInitializationOptions = {
|
|
4
|
+
appInfo: Implementation;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Read a single key from the raw MCP Apps (`ext-apps`) bridge context.
|
|
8
|
+
*
|
|
9
|
+
* Advanced escape hatch — prefer the cross-host hooks (`useToolInfo`,
|
|
10
|
+
* `useLayout`, etc.) which work in both MCP Apps and Apps SDK. Reach for this
|
|
11
|
+
* when you need protocol-level fields not surfaced by the public hooks.
|
|
12
|
+
*
|
|
13
|
+
* `options.appInfo` is honored only on the first call that creates the
|
|
14
|
+
* underlying bridge; subsequent calls reuse the singleton.
|
|
15
|
+
*
|
|
16
|
+
* @see https://docs.skybridge.tech/api-reference/use-mcp-app-context
|
|
17
|
+
*/
|
|
18
|
+
export declare function useMcpAppContext<K extends keyof McpAppContext>(key: K, options?: Partial<McpAppInitializationOptions>): McpAppContext[K];
|
|
5
19
|
export {};
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { useSyncExternalStore } from "react";
|
|
2
2
|
import { McpAppBridge } from "./bridge.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Read a single key from the raw MCP Apps (`ext-apps`) bridge context.
|
|
5
|
+
*
|
|
6
|
+
* Advanced escape hatch — prefer the cross-host hooks (`useToolInfo`,
|
|
7
|
+
* `useLayout`, etc.) which work in both MCP Apps and Apps SDK. Reach for this
|
|
8
|
+
* when you need protocol-level fields not surfaced by the public hooks.
|
|
9
|
+
*
|
|
10
|
+
* `options.appInfo` is honored only on the first call that creates the
|
|
11
|
+
* underlying bridge; subsequent calls reuse the singleton.
|
|
12
|
+
*
|
|
13
|
+
* @see https://docs.skybridge.tech/api-reference/use-mcp-app-context
|
|
14
|
+
*/
|
|
15
|
+
export function useMcpAppContext(key, options) {
|
|
16
|
+
const bridge = McpAppBridge.getInstance(options);
|
|
5
17
|
return useSyncExternalStore(bridge.subscribe(key), () => bridge.getSnapshot(key));
|
|
6
18
|
}
|
|
7
19
|
//# sourceMappingURL=use-mcp-app-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-mcp-app-context.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"use-mcp-app-context.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAM,EACN,OAA8C;IAE9C,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CACtD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CACxB,CAAC;AACJ,CAAC","sourcesContent":["import type { Implementation } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { McpAppBridge } from \"./bridge.js\";\nimport type { McpAppContext } from \"./types.js\";\n\ntype McpAppInitializationOptions = {\n appInfo: Implementation;\n};\n\n/**\n * Read a single key from the raw MCP Apps (`ext-apps`) bridge context.\n *\n * Advanced escape hatch — prefer the cross-host hooks (`useToolInfo`,\n * `useLayout`, etc.) which work in both MCP Apps and Apps SDK. Reach for this\n * when you need protocol-level fields not surfaced by the public hooks.\n *\n * `options.appInfo` is honored only on the first call that creates the\n * underlying bridge; subsequent calls reuse the singleton.\n *\n * @see https://docs.skybridge.tech/api-reference/use-mcp-app-context\n */\nexport function useMcpAppContext<K extends keyof McpAppContext>(\n key: K,\n options?: Partial<McpAppInitializationOptions>,\n): McpAppContext[K] {\n const bridge = McpAppBridge.getInstance(options);\n return useSyncExternalStore(bridge.subscribe(key), () =>\n bridge.getSnapshot(key),\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
3
|
import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "../../hooks/test/utils.js";
|
|
4
4
|
import { McpAppBridge } from "./bridge.js";
|
|
@@ -22,45 +22,5 @@ describe("useMcpAppContext", () => {
|
|
|
22
22
|
expect(result.current).toBe("light");
|
|
23
23
|
});
|
|
24
24
|
});
|
|
25
|
-
it("should reject the request after timeout", async () => {
|
|
26
|
-
vi.useFakeTimers();
|
|
27
|
-
const consoleErrorSpy = vi
|
|
28
|
-
.spyOn(console, "error")
|
|
29
|
-
.mockImplementation(() => { });
|
|
30
|
-
const nonRespondingMock = vi.fn();
|
|
31
|
-
vi.stubGlobal("parent", { postMessage: nonRespondingMock });
|
|
32
|
-
renderHook(() => useMcpAppContext("theme", undefined, 100));
|
|
33
|
-
expect(nonRespondingMock).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/initialize" }), "*");
|
|
34
|
-
await act(async () => {
|
|
35
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
36
|
-
});
|
|
37
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(new Error("Request timed out"));
|
|
38
|
-
consoleErrorSpy.mockRestore();
|
|
39
|
-
vi.useRealTimers();
|
|
40
|
-
});
|
|
41
|
-
it("should send size-changed notification after successful initialization", async () => {
|
|
42
|
-
// Mock body dimensions to non-zero (size-changed only sends when dimensions change)
|
|
43
|
-
Object.defineProperty(document.body, "scrollWidth", {
|
|
44
|
-
value: 800,
|
|
45
|
-
configurable: true,
|
|
46
|
-
});
|
|
47
|
-
Object.defineProperty(document.body, "scrollHeight", {
|
|
48
|
-
value: 600,
|
|
49
|
-
configurable: true,
|
|
50
|
-
});
|
|
51
|
-
const postMessageMock = getMcpAppHostPostMessageMock({ theme: "light" });
|
|
52
|
-
vi.stubGlobal("parent", { postMessage: postMessageMock });
|
|
53
|
-
renderHook(() => useMcpAppContext("theme"));
|
|
54
|
-
await waitFor(() => {
|
|
55
|
-
expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
56
|
-
jsonrpc: "2.0",
|
|
57
|
-
method: "ui/notifications/size-changed",
|
|
58
|
-
params: expect.objectContaining({
|
|
59
|
-
width: expect.any(Number),
|
|
60
|
-
height: expect.any(Number),
|
|
61
|
-
}),
|
|
62
|
-
}), "*");
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
25
|
});
|
|
66
26
|
//# sourceMappingURL=use-mcp-app-context.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-mcp-app-context.test.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"use-mcp-app-context.test.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.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,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;YACtB,WAAW,EAAE,4BAA4B,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;QAE/D,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,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 {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"../../hooks/test/utils.js\";\nimport { McpAppBridge } from \"./bridge.js\";\nimport { useMcpAppContext } from \"./use-mcp-app-context.js\";\n\ndescribe(\"useMcpAppContext\", () => {\n beforeEach(async () => {\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n McpAppBridge.resetInstance();\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.clearAllMocks();\n });\n\n it(\"should return the theme value from host context and update on notification\", async () => {\n vi.stubGlobal(\"parent\", {\n postMessage: getMcpAppHostPostMessageMock({ theme: \"light\" }),\n });\n const { result } = renderHook(() => useMcpAppContext(\"theme\"));\n\n await waitFor(() => {\n expect(result.current).toBe(\"light\");\n });\n });\n});\n"]}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
1
|
+
import type { CallToolResult, EmbeddedResource, ResourceLink } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import type { useSyncExternalStore } from "react";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ViewHostType } from "../../server/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Globals injected on `window.skybridge` by the host. Tells the view which
|
|
6
|
+
* runtime it's running under and where to reach the MCP server.
|
|
7
|
+
*/
|
|
4
8
|
export type SkybridgeProperties = {
|
|
5
|
-
hostType:
|
|
9
|
+
hostType: ViewHostType;
|
|
6
10
|
serverUrl: string;
|
|
7
11
|
};
|
|
8
12
|
declare global {
|
|
@@ -10,26 +14,43 @@ declare global {
|
|
|
10
14
|
skybridge: SkybridgeProperties;
|
|
11
15
|
}
|
|
12
16
|
}
|
|
17
|
+
/** Arguments passed to a tool call. `null` for tools that take no input. */
|
|
13
18
|
export type CallToolArgs = Record<string, unknown> | null;
|
|
19
|
+
/**
|
|
20
|
+
* Result of a tool call as surfaced to the view: MCP `content` blocks plus
|
|
21
|
+
* the typed `structuredContent` and optional `meta`. `isError` is set when
|
|
22
|
+
* the server marks the call as failed.
|
|
23
|
+
*/
|
|
14
24
|
export type CallToolResponse = {
|
|
15
25
|
content: CallToolResult["content"];
|
|
16
26
|
structuredContent: NonNullable<CallToolResult["structuredContent"]>;
|
|
17
27
|
isError: NonNullable<CallToolResult["isError"]>;
|
|
18
|
-
result: string;
|
|
19
28
|
meta?: CallToolResult["_meta"];
|
|
20
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* How the view is laid out by the host. `"modal"` is host-driven (see
|
|
32
|
+
* {@link useRequestModal}); `"pip"`, `"inline"`, and `"fullscreen"` are
|
|
33
|
+
* requestable via {@link useDisplayMode}.
|
|
34
|
+
*/
|
|
21
35
|
export type DisplayMode = "pip" | "inline" | "fullscreen" | "modal";
|
|
36
|
+
/** Subset of {@link DisplayMode} that the view can request from the host. */
|
|
37
|
+
export type RequestDisplayMode = Exclude<DisplayMode, "modal">;
|
|
38
|
+
/** Host theme. Mirror this in your view's styling for a native feel. */
|
|
22
39
|
export type Theme = "light" | "dark";
|
|
40
|
+
/** Coarse device class reported by the host. `"unknown"` when unavailable. */
|
|
23
41
|
export type DeviceType = "mobile" | "tablet" | "desktop" | "unknown";
|
|
42
|
+
/** Pixel insets the view should keep clear of (notches, home indicators, etc.). */
|
|
24
43
|
export type SafeAreaInsets = {
|
|
25
44
|
top: number;
|
|
26
45
|
right: number;
|
|
27
46
|
bottom: number;
|
|
28
47
|
left: number;
|
|
29
48
|
};
|
|
49
|
+
/** Wrapper around {@link SafeAreaInsets} exposed via {@link useLayout}. */
|
|
30
50
|
export type SafeArea = {
|
|
31
51
|
insets: SafeAreaInsets;
|
|
32
52
|
};
|
|
53
|
+
/** Device and input-capability hints exposed via {@link useUser}. */
|
|
33
54
|
export type UserAgent = {
|
|
34
55
|
device: {
|
|
35
56
|
type: DeviceType;
|
|
@@ -39,6 +60,11 @@ export type UserAgent = {
|
|
|
39
60
|
touch: boolean;
|
|
40
61
|
};
|
|
41
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* Full snapshot of state the host exposes to the view. Most fields are
|
|
65
|
+
* better accessed through their dedicated hooks (`useLayout`, `useUser`,
|
|
66
|
+
* `useToolInfo`, etc.) — read this directly only for advanced cases.
|
|
67
|
+
*/
|
|
42
68
|
export interface HostContext {
|
|
43
69
|
theme: Theme;
|
|
44
70
|
locale: string;
|
|
@@ -49,30 +75,44 @@ export interface HostContext {
|
|
|
49
75
|
toolInput: Record<string, unknown> | null;
|
|
50
76
|
toolOutput: Record<string, unknown> | null;
|
|
51
77
|
toolResponseMetadata: Record<string, unknown> | null;
|
|
52
|
-
|
|
78
|
+
display: {
|
|
53
79
|
mode: DisplayMode;
|
|
54
80
|
params?: Record<string, unknown>;
|
|
55
81
|
};
|
|
56
|
-
|
|
82
|
+
viewState: Record<string, unknown> | null;
|
|
57
83
|
}
|
|
84
|
+
/** @internal `useSyncExternalStore` subscribe signature, re-exported for bridge implementations. */
|
|
58
85
|
export type Subscribe = Parameters<typeof useSyncExternalStore>[0];
|
|
86
|
+
/** @internal Bridge contract implemented by per-host bridge classes. */
|
|
59
87
|
export interface Bridge<Context> {
|
|
60
88
|
subscribe(key: keyof Context): Subscribe;
|
|
61
89
|
subscribe(keys: readonly (keyof Context)[]): Subscribe;
|
|
62
90
|
getSnapshot<K extends keyof Context>(key: K): Context[K] | undefined;
|
|
63
91
|
}
|
|
92
|
+
/** @internal Per-key snapshot store backing {@link useHostContext}. */
|
|
64
93
|
export type HostContextStore<K extends keyof HostContext> = {
|
|
65
94
|
subscribe: Subscribe;
|
|
66
95
|
getSnapshot: () => HostContext[K];
|
|
67
96
|
};
|
|
68
|
-
|
|
69
|
-
export type
|
|
97
|
+
/** Persisted view state shape (a plain object). See {@link useViewState}. */
|
|
98
|
+
export type ViewState = Record<string, unknown>;
|
|
99
|
+
/** Updater form accepted when writing to view state. */
|
|
100
|
+
export type SetViewStateAction = ViewState | ((prevState: ViewState | null) => ViewState);
|
|
101
|
+
/** Reference to a host-managed file (returned by {@link useFiles}). */
|
|
70
102
|
export type FileMetadata = {
|
|
71
103
|
fileId: string;
|
|
104
|
+
fileName?: string;
|
|
105
|
+
mimeType?: string;
|
|
72
106
|
};
|
|
107
|
+
/** Options for {@link useFiles}'s `upload`. `library: true` saves into the user's library when supported. */
|
|
108
|
+
export type UploadFileOptions = {
|
|
109
|
+
library?: boolean;
|
|
110
|
+
};
|
|
111
|
+
/** Options for {@link useRequestModal}'s `open` call. */
|
|
73
112
|
export type RequestModalOptions = {
|
|
74
113
|
title?: string;
|
|
75
114
|
params?: Record<string, unknown>;
|
|
115
|
+
template?: string;
|
|
76
116
|
anchor?: {
|
|
77
117
|
top?: number;
|
|
78
118
|
left?: number;
|
|
@@ -80,19 +120,67 @@ export type RequestModalOptions = {
|
|
|
80
120
|
height?: number;
|
|
81
121
|
};
|
|
82
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* Options for {@link useOpenExternal}. Set `redirectUrl: false` to tell the
|
|
125
|
+
* host not to append its `?redirectUrl=…` tracking query parameter when
|
|
126
|
+
* opening allowlisted targets.
|
|
127
|
+
*/
|
|
128
|
+
export type OpenExternalOptions = {
|
|
129
|
+
redirectUrl?: false;
|
|
130
|
+
};
|
|
131
|
+
/** Options for {@link useSendFollowUpMessage}. */
|
|
132
|
+
export type SendFollowUpMessageOptions = {
|
|
133
|
+
scrollToBottom?: boolean;
|
|
134
|
+
};
|
|
135
|
+
/** Options for {@link useRequestSize}. Omit a dimension to leave it unchanged. */
|
|
136
|
+
export type RequestSizeOptions = {
|
|
137
|
+
width?: number;
|
|
138
|
+
height?: number;
|
|
139
|
+
};
|
|
140
|
+
export type DownloadParams = {
|
|
141
|
+
contents: (EmbeddedResource | ResourceLink)[];
|
|
142
|
+
};
|
|
143
|
+
export type DownloadResult = {
|
|
144
|
+
isError?: boolean;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* @internal
|
|
148
|
+
* Low-level interface every host bridge implements. End-user code should use
|
|
149
|
+
* the React hooks (`useCallTool`, `useViewState`, `useFiles`, …) rather than
|
|
150
|
+
* calling this directly.
|
|
151
|
+
*/
|
|
83
152
|
export interface Adaptor {
|
|
84
153
|
getHostContextStore<K extends keyof HostContext>(key: K): HostContextStore<K>;
|
|
85
154
|
callTool<ToolArgs extends CallToolArgs = null, ToolResponse extends CallToolResponse = CallToolResponse>(name: string, args: ToolArgs): Promise<ToolResponse>;
|
|
86
|
-
requestDisplayMode(mode:
|
|
87
|
-
mode:
|
|
155
|
+
requestDisplayMode(mode: RequestDisplayMode): Promise<{
|
|
156
|
+
mode: RequestDisplayMode;
|
|
88
157
|
}>;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
158
|
+
requestClose(): Promise<void>;
|
|
159
|
+
requestSize(size: RequestSizeOptions): Promise<void>;
|
|
160
|
+
sendFollowUpMessage(prompt: string, options?: SendFollowUpMessageOptions): Promise<void>;
|
|
161
|
+
openExternal(href: string, options?: OpenExternalOptions): void;
|
|
162
|
+
download(params: DownloadParams): Promise<DownloadResult>;
|
|
163
|
+
setViewState(stateOrUpdater: SetViewStateAction): Promise<void>;
|
|
164
|
+
uploadFile(file: File, options?: UploadFileOptions): Promise<FileMetadata>;
|
|
93
165
|
getFileDownloadUrl(file: FileMetadata): Promise<{
|
|
94
166
|
downloadUrl: string;
|
|
95
167
|
}>;
|
|
168
|
+
selectFiles(): Promise<FileMetadata[]>;
|
|
96
169
|
openModal(options: RequestModalOptions): void;
|
|
97
170
|
setOpenInAppUrl(href: string): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Close a modal opened via {@link Adaptor.openModal}. In the Apps SDK
|
|
173
|
+
* runtime this is a no-op (the host owns modal lifecycle). In the MCP App
|
|
174
|
+
* runtime it dismisses the in-iframe polyfill.
|
|
175
|
+
*/
|
|
176
|
+
closeModal(): void;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Thrown when a host bridge method is called in a runtime that doesn't
|
|
180
|
+
* support it (e.g. `uploadFile` outside the Apps SDK runtime).
|
|
181
|
+
*/
|
|
182
|
+
export declare class NotSupportedError extends Error {
|
|
183
|
+
readonly method: string;
|
|
184
|
+
readonly reason?: string | undefined;
|
|
185
|
+
constructor(method: string, reason?: string | undefined);
|
|
98
186
|
}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when a host bridge method is called in a runtime that doesn't
|
|
3
|
+
* support it (e.g. `uploadFile` outside the Apps SDK runtime).
|
|
4
|
+
*/
|
|
5
|
+
export class NotSupportedError extends Error {
|
|
6
|
+
method;
|
|
7
|
+
reason;
|
|
8
|
+
constructor(method, reason) {
|
|
9
|
+
super(`${method} is not supported in this runtime${reason ? `: ${reason}` : ""}`);
|
|
10
|
+
this.method = method;
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
this.name = "NotSupportedError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
2
15
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/web/bridges/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/web/bridges/types.ts"],"names":[],"mappings":"AA4MA;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAExB;IACA;IAFlB,YACkB,MAAc,EACd,MAAe;QAE/B,KAAK,CACH,GAAG,MAAM,oCAAoC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3E,CAAC;QALc,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAS;QAK/B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF","sourcesContent":["import type {\n CallToolResult,\n EmbeddedResource,\n ResourceLink,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { useSyncExternalStore } from \"react\";\nimport type { ViewHostType } from \"../../server/index.js\";\n\n/**\n * Globals injected on `window.skybridge` by the host. Tells the view which\n * runtime it's running under and where to reach the MCP server.\n */\nexport type SkybridgeProperties = {\n hostType: ViewHostType;\n serverUrl: string;\n};\n\ndeclare global {\n interface Window {\n skybridge: SkybridgeProperties;\n }\n}\n\n/** Arguments passed to a tool call. `null` for tools that take no input. */\nexport type CallToolArgs = Record<string, unknown> | null;\n\n/**\n * Result of a tool call as surfaced to the view: MCP `content` blocks plus\n * the typed `structuredContent` and optional `meta`. `isError` is set when\n * the server marks the call as failed.\n */\nexport type CallToolResponse = {\n content: CallToolResult[\"content\"];\n structuredContent: NonNullable<CallToolResult[\"structuredContent\"]>;\n isError: NonNullable<CallToolResult[\"isError\"]>;\n meta?: CallToolResult[\"_meta\"];\n};\n\n/**\n * How the view is laid out by the host. `\"modal\"` is host-driven (see\n * {@link useRequestModal}); `\"pip\"`, `\"inline\"`, and `\"fullscreen\"` are\n * requestable via {@link useDisplayMode}.\n */\nexport type DisplayMode = \"pip\" | \"inline\" | \"fullscreen\" | \"modal\";\n/** Subset of {@link DisplayMode} that the view can request from the host. */\nexport type RequestDisplayMode = Exclude<DisplayMode, \"modal\">;\n\n/** Host theme. Mirror this in your view's styling for a native feel. */\nexport type Theme = \"light\" | \"dark\";\n\n/** Coarse device class reported by the host. `\"unknown\"` when unavailable. */\nexport type DeviceType = \"mobile\" | \"tablet\" | \"desktop\" | \"unknown\";\n\n/** Pixel insets the view should keep clear of (notches, home indicators, etc.). */\nexport type SafeAreaInsets = {\n top: number;\n right: number;\n bottom: number;\n left: number;\n};\n\n/** Wrapper around {@link SafeAreaInsets} exposed via {@link useLayout}. */\nexport type SafeArea = {\n insets: SafeAreaInsets;\n};\n\n/** Device and input-capability hints exposed via {@link useUser}. */\nexport type UserAgent = {\n device: {\n type: DeviceType;\n };\n capabilities: {\n hover: boolean;\n touch: boolean;\n };\n};\n\n/**\n * Full snapshot of state the host exposes to the view. Most fields are\n * better accessed through their dedicated hooks (`useLayout`, `useUser`,\n * `useToolInfo`, etc.) — read this directly only for advanced cases.\n */\nexport interface HostContext {\n theme: Theme;\n locale: string;\n displayMode: DisplayMode;\n safeArea: SafeArea;\n maxHeight: number | undefined;\n userAgent: UserAgent;\n toolInput: Record<string, unknown> | null;\n toolOutput: Record<string, unknown> | null;\n toolResponseMetadata: Record<string, unknown> | null;\n display: {\n mode: DisplayMode;\n params?: Record<string, unknown>;\n };\n viewState: Record<string, unknown> | null;\n}\n\n/** @internal `useSyncExternalStore` subscribe signature, re-exported for bridge implementations. */\nexport type Subscribe = Parameters<typeof useSyncExternalStore>[0];\n\n/** @internal Bridge contract implemented by per-host bridge classes. */\nexport interface Bridge<Context> {\n subscribe(key: keyof Context): Subscribe;\n subscribe(keys: readonly (keyof Context)[]): Subscribe;\n getSnapshot<K extends keyof Context>(key: K): Context[K] | undefined;\n}\n\n/** @internal Per-key snapshot store backing {@link useHostContext}. */\nexport type HostContextStore<K extends keyof HostContext> = {\n subscribe: Subscribe;\n getSnapshot: () => HostContext[K];\n};\n\n/** Persisted view state shape (a plain object). See {@link useViewState}. */\nexport type ViewState = Record<string, unknown>;\n\n/** Updater form accepted when writing to view state. */\nexport type SetViewStateAction =\n | ViewState\n | ((prevState: ViewState | null) => ViewState);\n\n/** Reference to a host-managed file (returned by {@link useFiles}). */\nexport type FileMetadata = {\n fileId: string;\n fileName?: string;\n mimeType?: string;\n};\n\n/** Options for {@link useFiles}'s `upload`. `library: true` saves into the user's library when supported. */\nexport type UploadFileOptions = { library?: boolean };\n\n/** Options for {@link useRequestModal}'s `open` call. */\nexport type RequestModalOptions = {\n title?: string;\n params?: Record<string, unknown>;\n template?: string;\n anchor?: { top?: number; left?: number; width?: number; height?: number };\n};\n\n/**\n * Options for {@link useOpenExternal}. Set `redirectUrl: false` to tell the\n * host not to append its `?redirectUrl=…` tracking query parameter when\n * opening allowlisted targets.\n */\nexport type OpenExternalOptions = {\n redirectUrl?: false;\n};\n\n/** Options for {@link useSendFollowUpMessage}. */\nexport type SendFollowUpMessageOptions = { scrollToBottom?: boolean };\n\n/** Options for {@link useRequestSize}. Omit a dimension to leave it unchanged. */\nexport type RequestSizeOptions = {\n width?: number;\n height?: number;\n};\n\nexport type DownloadParams = {\n contents: (EmbeddedResource | ResourceLink)[];\n};\n\nexport type DownloadResult = {\n isError?: boolean;\n};\n\n/**\n * @internal\n * Low-level interface every host bridge implements. End-user code should use\n * the React hooks (`useCallTool`, `useViewState`, `useFiles`, …) rather than\n * calling this directly.\n */\nexport interface Adaptor {\n getHostContextStore<K extends keyof HostContext>(key: K): HostContextStore<K>;\n callTool<\n ToolArgs extends CallToolArgs = null,\n ToolResponse extends CallToolResponse = CallToolResponse,\n >(name: string, args: ToolArgs): Promise<ToolResponse>;\n requestDisplayMode(mode: RequestDisplayMode): Promise<{\n mode: RequestDisplayMode;\n }>;\n requestClose(): Promise<void>;\n requestSize(size: RequestSizeOptions): Promise<void>;\n sendFollowUpMessage(\n prompt: string,\n options?: SendFollowUpMessageOptions,\n ): Promise<void>;\n openExternal(href: string, options?: OpenExternalOptions): void;\n download(params: DownloadParams): Promise<DownloadResult>;\n setViewState(stateOrUpdater: SetViewStateAction): Promise<void>;\n uploadFile(file: File, options?: UploadFileOptions): Promise<FileMetadata>;\n getFileDownloadUrl(file: FileMetadata): Promise<{ downloadUrl: string }>;\n selectFiles(): Promise<FileMetadata[]>;\n openModal(options: RequestModalOptions): void;\n setOpenInAppUrl(href: string): Promise<void>;\n /**\n * Close a modal opened via {@link Adaptor.openModal}. In the Apps SDK\n * runtime this is a no-op (the host owns modal lifecycle). In the MCP App\n * runtime it dismisses the in-iframe polyfill.\n */\n closeModal(): void;\n}\n\n/**\n * Thrown when a host bridge method is called in a runtime that doesn't\n * support it (e.g. `uploadFile` outside the Apps SDK runtime).\n */\nexport class NotSupportedError extends Error {\n constructor(\n public readonly method: string,\n public readonly reason?: string,\n ) {\n super(\n `${method} is not supported in this runtime${reason ? `: ${reason}` : \"\"}`,\n );\n this.name = \"NotSupportedError\";\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { NotSupportedError } from "./types.js";
|
|
3
|
+
describe("NotSupportedError", () => {
|
|
4
|
+
it("includes method name in message", () => {
|
|
5
|
+
const err = new NotSupportedError("uploadFile");
|
|
6
|
+
expect(err.message).toBe("uploadFile is not supported in this runtime");
|
|
7
|
+
expect(err.name).toBe("NotSupportedError");
|
|
8
|
+
expect(err.method).toBe("uploadFile");
|
|
9
|
+
});
|
|
10
|
+
it("includes reason when provided", () => {
|
|
11
|
+
const err = new NotSupportedError("callTool", "MCP transport unavailable");
|
|
12
|
+
expect(err.message).toBe("callTool is not supported in this runtime: MCP transport unavailable");
|
|
13
|
+
expect(err.reason).toBe("MCP transport unavailable");
|
|
14
|
+
});
|
|
15
|
+
it("is an instance of Error", () => {
|
|
16
|
+
expect(new NotSupportedError("x")).toBeInstanceOf(Error);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../../src/web/bridges/types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACxE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;QAC3E,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CACtB,sEAAsE,CACvE,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { NotSupportedError } from \"./types.js\";\n\ndescribe(\"NotSupportedError\", () => {\n it(\"includes method name in message\", () => {\n const err = new NotSupportedError(\"uploadFile\");\n expect(err.message).toBe(\"uploadFile is not supported in this runtime\");\n expect(err.name).toBe(\"NotSupportedError\");\n expect(err.method).toBe(\"uploadFile\");\n });\n\n it(\"includes reason when provided\", () => {\n const err = new NotSupportedError(\"callTool\", \"MCP transport unavailable\");\n expect(err.message).toBe(\n \"callTool is not supported in this runtime: MCP transport unavailable\",\n );\n expect(err.reason).toBe(\"MCP transport unavailable\");\n });\n\n it(\"is an instance of Error\", () => {\n expect(new NotSupportedError(\"x\")).toBeInstanceOf(Error);\n });\n});\n"]}
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import type { HostContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
* Subscribe to a single {@link HostContext} key via `useSyncExternalStore`.
|
|
5
|
+
* Used to build the higher-level hooks; prefer those for app code.
|
|
6
|
+
*/
|
|
2
7
|
export declare const useHostContext: <K extends keyof HostContext>(key: K) => HostContext[K];
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { useSyncExternalStore } from "react";
|
|
2
2
|
import { getAdaptor } from "./get-adaptor.js";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
* Subscribe to a single {@link HostContext} key via `useSyncExternalStore`.
|
|
6
|
+
* Used to build the higher-level hooks; prefer those for app code.
|
|
7
|
+
*/
|
|
3
8
|
export const useHostContext = (key) => {
|
|
4
9
|
const adaptor = getAdaptor();
|
|
5
10
|
const store = adaptor.getHostContextStore(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-host-context.js","sourceRoot":"","sources":["../../../src/web/bridges/use-host-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,GAAM,EACU,EAAE;IAClB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;AAClE,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"use-host-context.js","sourceRoot":"","sources":["../../../src/web/bridges/use-host-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,GAAM,EACU,EAAE;IAClB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;AAClE,CAAC,CAAC","sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { getAdaptor } from \"./get-adaptor.js\";\nimport type { HostContext } from \"./types.js\";\n\n/**\n * @internal\n * Subscribe to a single {@link HostContext} key via `useSyncExternalStore`.\n * Used to build the higher-level hooks; prefer those for app code.\n */\nexport const useHostContext = <K extends keyof HostContext>(\n key: K,\n): HostContext[K] => {\n const adaptor = getAdaptor();\n const store = adaptor.getHostContextStore(key);\n\n return useSyncExternalStore(store.subscribe, store.getSnapshot);\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useSyncExternalStore } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { getAdaptor } from "../bridges/index.js";
|
|
4
4
|
const modalStyles = `
|
|
5
5
|
.sb-modal-backdrop {
|
|
6
6
|
position: fixed;
|
|
@@ -20,8 +20,9 @@ const modalStyles = `
|
|
|
20
20
|
}
|
|
21
21
|
`;
|
|
22
22
|
export function ModalProvider({ children }) {
|
|
23
|
-
const adaptor =
|
|
24
|
-
const
|
|
23
|
+
const adaptor = getAdaptor();
|
|
24
|
+
const displayStore = adaptor.getHostContextStore("display");
|
|
25
|
+
const { mode } = useSyncExternalStore(displayStore.subscribe, displayStore.getSnapshot);
|
|
25
26
|
const isOpen = mode === "modal";
|
|
26
27
|
const handleBackdropClick = (e) => {
|
|
27
28
|
if (e.target === e.currentTarget) {
|
|
@@ -40,8 +41,6 @@ export function ModalProvider({ children }) {
|
|
|
40
41
|
document.addEventListener("keydown", handler);
|
|
41
42
|
return () => document.removeEventListener("keydown", handler);
|
|
42
43
|
}, [isOpen, adaptor]);
|
|
43
|
-
return (_jsxs(_Fragment, { children: [_jsx("style", { children: modalStyles }), isOpen && (
|
|
44
|
-
// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop isn't focusable
|
|
45
|
-
_jsx("div", { role: "dialog", className: "sb-modal-backdrop", onClick: handleBackdropClick })), _jsx("div", { className: isOpen ? "sb-modal-container" : undefined, children: children })] }));
|
|
44
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: modalStyles }), isOpen && (_jsx("div", { role: "dialog", className: "sb-modal-backdrop", onClick: handleBackdropClick })), _jsx("div", { className: isOpen ? "sb-modal-container" : undefined, children: children })] }));
|
|
46
45
|
}
|
|
47
46
|
//# sourceMappingURL=modal-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-provider.js","sourceRoot":"","sources":["../../../src/web/components/modal-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"modal-provider.js","sourceRoot":"","sources":["../../../src/web/components/modal-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;CAiBnB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAA2B;IACjE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,GAAG,oBAAoB,CACnC,YAAY,CAAC,SAAS,EACtB,YAAY,CAAC,WAAW,CACzB,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;IAEhC,MAAM,mBAAmB,GAAG,CAAC,CAAmB,EAAE,EAAE;QAClD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YACjC,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvB,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,OAAO,CACL,8BACE,0BAAQ,WAAW,GAAS,EAC3B,MAAM,IAAI,CAET,cACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mBAAmB,EAC7B,OAAO,EAAE,mBAAmB,GAC5B,CACH,EACD,cAAK,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,YACtD,QAAQ,GACL,IACL,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import { type ReactNode, useEffect, useSyncExternalStore } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\nconst modalStyles = `\n.sb-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n.sb-modal-container {\n border-radius: 12px;\n position: fixed;\n inset: 0;\n margin: auto;\n width: fit-content;\n height: fit-content;\n background: white;\n z-index: 9999;\n}\n`;\n\nexport function ModalProvider({ children }: { children: ReactNode }) {\n const adaptor = getAdaptor();\n const displayStore = adaptor.getHostContextStore(\"display\");\n const { mode } = useSyncExternalStore(\n displayStore.subscribe,\n displayStore.getSnapshot,\n );\n const isOpen = mode === \"modal\";\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n adaptor.closeModal();\n }\n };\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n adaptor.closeModal();\n }\n };\n document.addEventListener(\"keydown\", handler);\n return () => document.removeEventListener(\"keydown\", handler);\n }, [isOpen, adaptor]);\n\n return (\n <>\n <style>{modalStyles}</style>\n {isOpen && (\n // biome-ignore lint/a11y/useKeyWithClickEvents: backdrop isn't focusable\n <div\n role=\"dialog\"\n className=\"sb-modal-backdrop\"\n onClick={handleBackdropClick}\n />\n )}\n <div className={isOpen ? \"sb-modal-container\" : undefined}>\n {children}\n </div>\n </>\n );\n}\n"]}
|
|
@@ -1,3 +1,29 @@
|
|
|
1
1
|
import { type StateCreator } from "zustand";
|
|
2
2
|
import type { UnknownObject } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a Zustand store that is bidirectionally synced with the host's
|
|
5
|
+
* `viewState`. Local store updates persist to the host, and external host
|
|
6
|
+
* updates rehydrate the store — making the store the single source of truth
|
|
7
|
+
* for state that should survive view remounts.
|
|
8
|
+
*
|
|
9
|
+
* Use this when you outgrow {@link useViewState} and want first-class Zustand
|
|
10
|
+
* ergonomics (selectors, actions, middleware). Otherwise prefer `useViewState`.
|
|
11
|
+
*
|
|
12
|
+
* Skybridge-internal context fields (see {@link DataLLM}) are filtered out
|
|
13
|
+
* automatically before reaching your store.
|
|
14
|
+
*
|
|
15
|
+
* @typeParam State - Shape of the store's state. Must be a plain object.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* export const useStore = createStore<{ count: number; inc: () => void }>(
|
|
20
|
+
* (set) => ({
|
|
21
|
+
* count: 0,
|
|
22
|
+
* inc: () => set((s) => ({ count: s.count + 1 })),
|
|
23
|
+
* }),
|
|
24
|
+
* );
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @see https://docs.skybridge.tech/api-reference/create-store
|
|
28
|
+
*/
|
|
3
29
|
export declare function createStore<State extends UnknownObject>(storeCreator: StateCreator<State, [], [], State>, defaultState?: State | (() => State)): import("zustand").UseBoundStore<import("zustand").StoreApi<State>>;
|