skybridge 0.0.0-dev.a62841e → 0.0.0-dev.a63fad2

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.
Files changed (117) hide show
  1. package/README.md +1 -9
  2. package/dist/cli/build-helpers.d.ts +3 -0
  3. package/dist/cli/build-helpers.js +15 -4
  4. package/dist/cli/build-helpers.js.map +1 -1
  5. package/dist/cli/build-helpers.test.js +26 -1
  6. package/dist/cli/build-helpers.test.js.map +1 -1
  7. package/dist/cli/build-steps.d.ts +2 -0
  8. package/dist/cli/build-steps.js +68 -0
  9. package/dist/cli/build-steps.js.map +1 -0
  10. package/dist/cli/build-steps.test.d.ts +1 -0
  11. package/dist/cli/build-steps.test.js +52 -0
  12. package/dist/cli/build-steps.test.js.map +1 -0
  13. package/dist/cli/header.d.ts +1 -1
  14. package/dist/cli/run-plain.d.ts +18 -0
  15. package/dist/cli/run-plain.js +89 -0
  16. package/dist/cli/run-plain.js.map +1 -0
  17. package/dist/cli/use-execute-steps.d.ts +1 -1
  18. package/dist/cli/use-nodemon.d.ts +14 -0
  19. package/dist/cli/use-nodemon.js +71 -60
  20. package/dist/cli/use-nodemon.js.map +1 -1
  21. package/dist/cli/use-typescript-check.d.ts +8 -2
  22. package/dist/cli/use-typescript-check.js +70 -67
  23. package/dist/cli/use-typescript-check.js.map +1 -1
  24. package/dist/commands/build.d.ts +0 -2
  25. package/dist/commands/build.js +2 -61
  26. package/dist/commands/build.js.map +1 -1
  27. package/dist/commands/dev.d.ts +1 -0
  28. package/dist/commands/dev.js +32 -0
  29. package/dist/commands/dev.js.map +1 -1
  30. package/dist/server/server.d.ts +21 -5
  31. package/dist/server/server.js +93 -120
  32. package/dist/server/server.js.map +1 -1
  33. package/dist/server/view-name.test-d.d.ts +1 -0
  34. package/dist/server/view-name.test-d.js +8 -0
  35. package/dist/server/view-name.test-d.js.map +1 -0
  36. package/dist/server/view-resource-resolution.test.js +93 -10
  37. package/dist/server/view-resource-resolution.test.js.map +1 -1
  38. package/dist/test/view.test.js +69 -101
  39. package/dist/test/view.test.js.map +1 -1
  40. package/dist/web/bridges/adaptor.d.ts +51 -0
  41. package/dist/web/bridges/adaptor.js +330 -0
  42. package/dist/web/bridges/adaptor.js.map +1 -0
  43. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  44. package/dist/web/bridges/adaptor.test.js +208 -0
  45. package/dist/web/bridges/adaptor.test.js.map +1 -0
  46. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
  47. package/dist/web/bridges/apps-sdk/bridge.js +15 -4
  48. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  49. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  50. package/dist/web/bridges/apps-sdk/index.js +0 -1
  51. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  52. package/dist/web/bridges/get-adaptor.d.ts +4 -4
  53. package/dist/web/bridges/get-adaptor.js +6 -11
  54. package/dist/web/bridges/get-adaptor.js.map +1 -1
  55. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  56. package/dist/web/bridges/get-adaptor.test.js +32 -0
  57. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  58. package/dist/web/bridges/mcp-app/bridge.d.ts +13 -2
  59. package/dist/web/bridges/mcp-app/bridge.js +46 -4
  60. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  61. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  62. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  63. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  64. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  65. package/dist/web/bridges/mcp-app/index.js +0 -1
  66. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  67. package/dist/web/bridges/mcp-app/view-tools.test.js +5 -6
  68. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
  69. package/dist/web/bridges/types.d.ts +10 -0
  70. package/dist/web/bridges/types.js +14 -1
  71. package/dist/web/bridges/types.js.map +1 -1
  72. package/dist/web/bridges/types.test.d.ts +1 -0
  73. package/dist/web/bridges/types.test.js +19 -0
  74. package/dist/web/bridges/types.test.js.map +1 -0
  75. package/dist/web/components/modal-provider.d.ts +1 -1
  76. package/dist/web/components/modal-provider.js +4 -3
  77. package/dist/web/components/modal-provider.js.map +1 -1
  78. package/dist/web/create-store.test.js +8 -5
  79. package/dist/web/create-store.test.js.map +1 -1
  80. package/dist/web/data-llm.d.ts +1 -1
  81. package/dist/web/data-llm.test.js +17 -5
  82. package/dist/web/data-llm.test.js.map +1 -1
  83. package/dist/web/hooks/use-call-tool.test.js +37 -23
  84. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  85. package/dist/web/hooks/use-display-mode.test.js +56 -20
  86. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  87. package/dist/web/hooks/use-download.test.js +11 -3
  88. package/dist/web/hooks/use-download.test.js.map +1 -1
  89. package/dist/web/hooks/use-files.test.js +10 -2
  90. package/dist/web/hooks/use-files.test.js.map +1 -1
  91. package/dist/web/hooks/use-layout.test.js +59 -26
  92. package/dist/web/hooks/use-layout.test.js.map +1 -1
  93. package/dist/web/hooks/use-open-external.test.js +13 -3
  94. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  95. package/dist/web/hooks/use-request-close.test.js +35 -40
  96. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  97. package/dist/web/hooks/use-request-modal.test.js +10 -0
  98. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  99. package/dist/web/hooks/use-request-size.test.js +35 -53
  100. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  101. package/dist/web/hooks/use-set-open-in-app-url.test.js +28 -8
  102. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  103. package/dist/web/hooks/use-tool-info.test.js +37 -27
  104. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  105. package/dist/web/hooks/use-user.test.js +81 -35
  106. package/dist/web/hooks/use-user.test.js.map +1 -1
  107. package/dist/web/hooks/use-view-state.test.js +6 -2
  108. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  109. package/dist/web/plugin/plugin.js +0 -1
  110. package/dist/web/plugin/plugin.js.map +1 -1
  111. package/package.json +20 -20
  112. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -29
  113. package/dist/web/bridges/apps-sdk/adaptor.js +0 -117
  114. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  115. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -53
  116. package/dist/web/bridges/mcp-app/adaptor.js +0 -283
  117. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Command, Flags } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { resolvePort } from \"../cli/detect-port.js\";\nimport { Header } from \"../cli/header.js\";\nimport { resolveViewsDir } from \"../cli/resolve-views-dir.js\";\nimport { startTunnelControlServer } from \"../cli/tunnel-control-server.js\";\nimport { useMessages } from \"../cli/use-messages.js\";\nimport { useNodemon } from \"../cli/use-nodemon.js\";\nimport { useOpenBrowser } from \"../cli/use-open-browser.js\";\nimport { useTunnel } from \"../cli/use-tunnel.js\";\nimport { useTypeScriptCheck } from \"../cli/use-typescript-check.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\n\nexport default class Dev extends Command {\n static override description = \"Start development server\";\n static override examples = [\"skybridge\"];\n static override flags = {\n port: Flags.integer({\n char: \"p\",\n description: \"Port to run the server on\",\n min: 1,\n }),\n tunnel: Flags.boolean({\n description: \"Open an Alpic tunnel for remote testing\",\n default: false,\n }),\n open: Flags.boolean({\n description: \"Open DevTools in the browser when the server is ready\",\n default: process.env.SKYBRIDGE_OPEN !== \"false\",\n allowNo: true,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Show tunnel logs\",\n default: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(Dev);\n\n // Generate .skybridge/views.d.ts before render() spawns `tsc --noEmit\n // --watch`. Vite's plugin config hook writes the same file when nodemon\n // boots the server, but tsc starts in parallel — if .skybridge/ doesn't\n // exist at tsc startup, its watcher never picks up the late-created file\n // and the dev UI reports phantom TS errors forever.\n const root = process.cwd();\n try {\n scanAndWriteViewsDts(root, await resolveViewsDir(root));\n } catch {\n // Best-effort: if the scan fails (e.g. broken vite config, duplicate\n // view names) tsc may show phantom errors, but the dev server should\n // still start so the developer can fix the underlying issue.\n }\n\n const { port, fallback, envWarning } = await resolvePort(flags.port);\n if (envWarning) {\n this.warn(envWarning);\n }\n\n const {\n port: controlPort,\n manager: tunnelManager,\n close: closeTunnelControl,\n } = await startTunnelControlServer(() => port);\n\n const env = {\n ...process.env,\n __PORT: String(port),\n __TUNNEL_CONTROL_PORT: String(controlPort),\n };\n\n const App = () => {\n const tsErrors = useTypeScriptCheck();\n const [messages, pushMessage] = useMessages();\n useNodemon(env, pushMessage);\n useOpenBrowser(port, flags.open);\n const tunnelState = useTunnel(\n port,\n pushMessage,\n flags.verbose,\n flags.tunnel,\n );\n\n return (\n <Box flexDirection=\"column\" padding={1} marginLeft={1}>\n <Header version={this.config.version} />\n\n <Box>\n <Text>🏠{\" \"}</Text>\n {fallback ? (\n <Text color=\"yellow\">3000 in use, running on </Text>\n ) : (\n <Text>Running on </Text>\n )}\n <Text color=\"green\">{`http://localhost:${port}/mcp`}</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test locally with DevTools:{\" \"}\n </Text>\n <Text color=\"green\">{`http://localhost:${port}/`}</Text>\n </Box>\n\n {tunnelState.status === \"idle\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Get a public URL and LLM Playground access with </Text>\n <Text color=\"cyan\" bold>\n --tunnel\n </Text>\n <Text>.</Text>\n </Box>\n )}\n {tunnelState.status === \"starting\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"yellow\">{tunnelState.message}</Text>\n </Box>\n )}\n {tunnelState.status === \"connected\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Exposed on </Text>\n <Text color=\"green\">{`${tunnelState.url}/mcp`}</Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test with an LLM on Playground:{\" \"}\n </Text>\n <Text color=\"green\">{`${tunnelState.url}/try`}</Text>\n </Box>\n </Box>\n )}\n {tunnelState.status === \"error\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"red\">\n Cannot open tunnel: {tunnelState.message}\n </Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"red\">{`Try manually: npx alpic tunnel --port ${port}`}</Text>\n </Box>\n </Box>\n )}\n\n <Box>\n <Text>🛟{\" \"}</Text>\n <Text>Need help? Reach us on </Text>\n <Text color=\"white\" underline>\n https://discord.alpic.ai\n </Text>\n </Box>\n\n {tsErrors.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ⚠️ TypeScript errors found:\n </Text>\n {tsErrors.map((error) => (\n <Box\n key={`${error.file}:${error.line}:${error.col}`}\n marginLeft={2}\n flexDirection=\"column\"\n >\n <Box>\n <Text color=\"white\">{error.file}</Text>\n <Text color=\"grey\">\n ({error.line},{error.col}):{\" \"}\n </Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"red\">{error.message}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n {messages.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"white\" bold>\n Logs:\n </Text>\n {messages.map((message) => (\n <Box key={message.id} marginLeft={2}>\n {message.type === \"restart\" ? (\n <>\n <Text color=\"green\">✓{\" \"}</Text>\n <Text color=\"white\">{message.text}</Text>\n </>\n ) : message.type === \"error\" ? (\n <Text color=\"red\">{message.text}</Text>\n ) : (\n <Text>{message.text}</Text>\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n };\n\n // Note: `exitOnCtrlC: false` because we own SIGINT below to guarantee\n // alpic gets killed before we exit. If anything ever calls `useInput` or\n // puts stdin into raw mode, also wire an explicit `\\x03` keypress to the\n // shutdown function — Ink will otherwise swallow Ctrl-C without ever\n // delivering SIGINT.\n const ink = render(<App />, { exitOnCtrlC: false, patchConsole: true });\n\n // Synchronous-first shutdown: kill the alpic subprocess up front so we\n // can't leave it orphaned even if another SIGINT listener (e.g. nodemon's)\n // exits the process before our async cleanup completes.\n const shutdown = (code: number) => () => {\n tunnelManager.stop();\n void closeTunnelControl()\n .catch((err) => {\n console.error(\"Failed to close tunnel control server\", err);\n })\n .finally(() => {\n ink.unmount();\n process.exit(code);\n });\n };\n process.once(\"SIGINT\", shutdown(130));\n process.once(\"SIGTERM\", shutdown(143));\n }\n}\n"]}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Command, Flags } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { resolvePort } from \"../cli/detect-port.js\";\nimport { Header } from \"../cli/header.js\";\nimport { resolveViewsDir } from \"../cli/resolve-views-dir.js\";\nimport { runPlain } from \"../cli/run-plain.js\";\nimport { startTunnelControlServer } from \"../cli/tunnel-control-server.js\";\nimport { useMessages } from \"../cli/use-messages.js\";\nimport { useNodemon } from \"../cli/use-nodemon.js\";\nimport { useOpenBrowser } from \"../cli/use-open-browser.js\";\nimport { useTunnel } from \"../cli/use-tunnel.js\";\nimport { useTypeScriptCheck } from \"../cli/use-typescript-check.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\n\nexport default class Dev extends Command {\n static override description = \"Start development server\";\n static override examples = [\"skybridge\"];\n static override flags = {\n port: Flags.integer({\n char: \"p\",\n description: \"Port to run the server on\",\n min: 1,\n }),\n tunnel: Flags.boolean({\n description: \"Open an Alpic tunnel for remote testing\",\n default: false,\n }),\n open: Flags.boolean({\n description: \"Open DevTools in the browser when the server is ready\",\n default: process.env.SKYBRIDGE_OPEN !== \"false\",\n allowNo: true,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Show tunnel logs\",\n default: false,\n }),\n plain: Flags.boolean({\n description:\n \"Disable the interactive UI and stream raw server logs to stdout, so you can pipe them through a formatter (e.g. `skybridge dev --plain | bunyan`).\",\n default: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(Dev);\n\n // Generate .skybridge/views.d.ts before render() spawns `tsc --noEmit\n // --watch`. Vite's plugin config hook writes the same file when nodemon\n // boots the server, but tsc starts in parallel — if .skybridge/ doesn't\n // exist at tsc startup, its watcher never picks up the late-created file\n // and the dev UI reports phantom TS errors forever.\n const root = process.cwd();\n try {\n scanAndWriteViewsDts(root, await resolveViewsDir(root));\n } catch {\n // Best-effort: if the scan fails (e.g. broken vite config, duplicate\n // view names) tsc may show phantom errors, but the dev server should\n // still start so the developer can fix the underlying issue.\n }\n\n const { port, fallback, envWarning } = await resolvePort(flags.port);\n if (envWarning) {\n this.warn(envWarning);\n }\n\n const {\n port: controlPort,\n manager: tunnelManager,\n close: closeTunnelControl,\n } = await startTunnelControlServer(() => port);\n\n const env = {\n ...process.env,\n __PORT: String(port),\n __TUNNEL_CONTROL_PORT: String(controlPort),\n };\n\n if (flags.plain) {\n const teardown = runPlain({\n env,\n port,\n fallback,\n version: this.config.version,\n tunnel: flags.tunnel,\n tunnelManager,\n });\n\n // Synchronous-first shutdown: kill the alpic subprocess up front so we\n // can't leave it orphaned even if another SIGINT listener (e.g.\n // nodemon's) exits the process before our async cleanup completes.\n const shutdown = (code: number) => () => {\n tunnelManager.stop();\n teardown();\n void closeTunnelControl()\n .catch((err) => {\n console.error(\"Failed to close tunnel control server\", err);\n })\n .finally(() => {\n process.exit(code);\n });\n };\n process.once(\"SIGINT\", shutdown(130));\n process.once(\"SIGTERM\", shutdown(143));\n return;\n }\n\n const App = () => {\n const tsErrors = useTypeScriptCheck();\n const [messages, pushMessage] = useMessages();\n useNodemon(env, pushMessage);\n useOpenBrowser(port, flags.open);\n const tunnelState = useTunnel(\n port,\n pushMessage,\n flags.verbose,\n flags.tunnel,\n );\n\n return (\n <Box flexDirection=\"column\" padding={1} marginLeft={1}>\n <Header version={this.config.version} />\n\n <Box>\n <Text>🏠{\" \"}</Text>\n {fallback ? (\n <Text color=\"yellow\">3000 in use, running on </Text>\n ) : (\n <Text>Running on </Text>\n )}\n <Text color=\"green\">{`http://localhost:${port}/mcp`}</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test locally with DevTools:{\" \"}\n </Text>\n <Text color=\"green\">{`http://localhost:${port}/`}</Text>\n </Box>\n\n {tunnelState.status === \"idle\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Get a public URL and LLM Playground access with </Text>\n <Text color=\"cyan\" bold>\n --tunnel\n </Text>\n <Text>.</Text>\n </Box>\n )}\n {tunnelState.status === \"starting\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"yellow\">{tunnelState.message}</Text>\n </Box>\n )}\n {tunnelState.status === \"connected\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Exposed on </Text>\n <Text color=\"green\">{`${tunnelState.url}/mcp`}</Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test with an LLM on Playground:{\" \"}\n </Text>\n <Text color=\"green\">{`${tunnelState.url}/try`}</Text>\n </Box>\n </Box>\n )}\n {tunnelState.status === \"error\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"red\">\n Cannot open tunnel: {tunnelState.message}\n </Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"red\">{`Try manually: npx alpic tunnel --port ${port}`}</Text>\n </Box>\n </Box>\n )}\n\n <Box>\n <Text>🛟{\" \"}</Text>\n <Text>Need help? Reach us on </Text>\n <Text color=\"white\" underline>\n https://discord.alpic.ai\n </Text>\n </Box>\n\n {tsErrors.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ⚠️ TypeScript errors found:\n </Text>\n {tsErrors.map((error) => (\n <Box\n key={`${error.file}:${error.line}:${error.col}`}\n marginLeft={2}\n flexDirection=\"column\"\n >\n <Box>\n <Text color=\"white\">{error.file}</Text>\n <Text color=\"grey\">\n ({error.line},{error.col}):{\" \"}\n </Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"red\">{error.message}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n {messages.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"white\" bold>\n Logs:\n </Text>\n {messages.map((message) => (\n <Box key={message.id} marginLeft={2}>\n {message.type === \"restart\" ? (\n <>\n <Text color=\"green\">✓{\" \"}</Text>\n <Text color=\"white\">{message.text}</Text>\n </>\n ) : message.type === \"error\" ? (\n <Text color=\"red\">{message.text}</Text>\n ) : (\n <Text>{message.text}</Text>\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n };\n\n // Note: `exitOnCtrlC: false` because we own SIGINT below to guarantee\n // alpic gets killed before we exit. If anything ever calls `useInput` or\n // puts stdin into raw mode, also wire an explicit `\\x03` keypress to the\n // shutdown function — Ink will otherwise swallow Ctrl-C without ever\n // delivering SIGINT.\n const ink = render(<App />, { exitOnCtrlC: false, patchConsole: true });\n\n // Synchronous-first shutdown: kill the alpic subprocess up front so we\n // can't leave it orphaned even if another SIGINT listener (e.g. nodemon's)\n // exits the process before our async cleanup completes.\n const shutdown = (code: number) => () => {\n tunnelManager.stop();\n void closeTunnelControl()\n .catch((err) => {\n console.error(\"Failed to close tunnel control server\", err);\n })\n .finally(() => {\n ink.unmount();\n process.exit(code);\n });\n };\n process.once(\"SIGINT\", shutdown(130));\n process.once(\"SIGTERM\", shutdown(143));\n }\n}\n"]}
@@ -19,7 +19,11 @@ export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unk
19
19
  output: TOutput;
20
20
  responseMetadata: TResponseMetadata;
21
21
  };
22
- /** Which host runtime a view targets — `"apps-sdk"` (ChatGPT) or `"mcp-app"` (MCP Apps spec). */
22
+ /**
23
+ * @deprecated Views now always emit a single ext-apps resource; host targeting
24
+ * no longer applies. Retained for backwards compatibility; will be removed in a
25
+ * future major.
26
+ */
23
27
  export type ViewHostType = "apps-sdk" | "mcp-app";
24
28
  /**
25
29
  * Content Security Policy origins attached to a view's resource. Each list is
@@ -45,8 +49,16 @@ export interface ViewCsp {
45
49
  */
46
50
  export interface ViewNameRegistry {
47
51
  }
52
+ /**
53
+ * Resolve view component names from a registry: the union of its keys, or
54
+ * `string` when the registry is empty. The empty case happens before
55
+ * `.skybridge/views.d.ts` is generated; falling back to `string` keeps valid
56
+ * view names from erroring on a fresh checkout, and narrowing kicks in once
57
+ * the generated file augments the registry.
58
+ */
59
+ export type ViewNameFor<Registry> = [keyof Registry & string] extends [never] ? string : keyof Registry & string;
48
60
  /** Union of valid view component names. Narrowed by {@link ViewNameRegistry}. */
49
- export type ViewName = keyof ViewNameRegistry & string;
61
+ export type ViewName = ViewNameFor<ViewNameRegistry>;
50
62
  /**
51
63
  * Pass under `view` in a tool's `registerTool` config to render the tool's
52
64
  * result through a Skybridge view instead of a plain text response.
@@ -56,11 +68,14 @@ export interface ViewConfig {
56
68
  component: ViewName;
57
69
  /** Human-readable label the host may show alongside the view. */
58
70
  description?: string;
59
- /** Restrict where the view is rendered. Defaults to all known hosts. */
71
+ /**
72
+ * @deprecated No-op. Every view emits a single ext-apps resource regardless
73
+ * of this value. Will be removed in a future major.
74
+ */
60
75
  hosts?: ViewHostType[];
61
- /** Apps SDK only: request a visible border around the widget. */
76
+ /** Request a visible border around the view (forwarded as `ui.prefersBorder`). */
62
77
  prefersBorder?: boolean;
63
- /** Apps SDK only: override the iframe's served domain (advanced). */
78
+ /** Override the iframe's served domain (advanced; forwarded as `ui.domain`). */
64
79
  domain?: string;
65
80
  /** Per-view CSP overrides — see {@link ViewCsp}. */
66
81
  csp?: ViewCsp;
@@ -350,6 +365,7 @@ export declare class McpServer<TTools extends Record<string, ToolDef> = Record<n
350
365
  private resolveViewRequestContext;
351
366
  private registerViewResources;
352
367
  private registerViewResource;
368
+ private serveLegacyAppsSdkUrl;
353
369
  private wrapHandler;
354
370
  private computeViewVersionParam;
355
371
  private lookupViewFile;
@@ -19,6 +19,19 @@ const mergeWithUnion = (target, source) => {
19
19
  }
20
20
  });
21
21
  };
22
+ /**
23
+ * Normalize an `x-forwarded-prefix` value into a leading-slash, no-trailing-slash
24
+ * path. Takes the first hop of a comma-separated proxy chain.
25
+ * "/v1/", "v1", "/v1, /internal" → "/v1"; "", "/", undefined → "".
26
+ */
27
+ function normalizeForwardedPrefix(raw) {
28
+ const firstHop = raw?.split(",")[0]?.trim() ?? "";
29
+ const trimmed = firstHop.replace(/\/+$/, "");
30
+ if (trimmed === "") {
31
+ return "";
32
+ }
33
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
34
+ }
22
35
  /**
23
36
  * Drop the query string from a `ui://` view URI, leaving the bare path. The
24
37
  * `?v=` cache key is the only query we append, so a plain split is enough and
@@ -236,7 +249,7 @@ export class McpServer extends McpServerBaseOmitted {
236
249
  const result = (await next());
237
250
  for (const content of result.contents ?? []) {
238
251
  if (typeof content.uri === "string" &&
239
- stripQuery(content.uri) === path) {
252
+ stripQuery(content.uri) === stripQuery(canonical)) {
240
253
  content.uri = requested;
241
254
  }
242
255
  }
@@ -383,6 +396,11 @@ export class McpServer extends McpServerBaseOmitted {
383
396
  };
384
397
  const isClaude = header("user-agent") === "Claude-User";
385
398
  const serverUrl = resolveServerOrigin(header);
399
+ // Path prefix the proxy routed this request under (e.g. `foo.com/v1`). Read
400
+ // per-request so one process can serve many hosts/prefixes at once: the
401
+ // origin is recovered from x-forwarded-host, the prefix from
402
+ // x-forwarded-prefix. Empty when served at the origin root.
403
+ const assetsBasePath = normalizeForwardedPrefix(header("x-forwarded-prefix"));
386
404
  const connectDomains = [serverUrl];
387
405
  if (!isProduction) {
388
406
  const wsUrl = new URL(serverUrl);
@@ -403,132 +421,77 @@ export class McpServer extends McpServerBaseOmitted {
403
421
  .slice(0, 32);
404
422
  contentMetaOverrides = { domain: `${hash}.claudemcpcontent.com` };
405
423
  }
406
- return { serverUrl, connectDomains, contentMetaOverrides };
424
+ return { serverUrl, assetsBasePath, connectDomains, contentMetaOverrides };
407
425
  }
408
426
  registerViewResources(toolName, view, toolMeta) {
409
- const hosts = view.hosts ?? ["apps-sdk", "mcp-app"];
410
427
  // Append a content-derived version param so hosts (e.g. ChatGPT) bust
411
428
  // their cache when the bundle changes, but keep the URI stable across
412
429
  // `tools/list` calls when the bundle hasn't changed.
413
430
  const versionParam = this.computeViewVersionParam(view.component);
414
- if (hosts.includes("apps-sdk")) {
415
- const viewResource = {
416
- hostType: "mcp-app",
417
- uri: `ui://views/apps-sdk/${view.component}.html${versionParam}`,
418
- mimeType: "text/html;profile=mcp-app",
419
- buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
420
- const defaults = {
421
- ui: {
422
- csp: {
423
- resourceDomains,
424
- connectDomains,
425
- baseUriDomains,
426
- },
427
- domain,
431
+ const viewResource = {
432
+ hostType: "mcp-app",
433
+ uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
434
+ mimeType: "text/html;profile=mcp-app",
435
+ buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
436
+ const defaults = {
437
+ ui: {
438
+ csp: {
439
+ resourceDomains,
440
+ connectDomains,
441
+ baseUriDomains,
428
442
  },
429
- };
430
- const fromView = {
431
- ui: {
432
- ...(view.description && { description: view.description }),
433
- ...(view.prefersBorder !== undefined && {
434
- prefersBorder: view.prefersBorder,
443
+ domain,
444
+ },
445
+ };
446
+ const fromView = {
447
+ ui: {
448
+ ...(view.description && { description: view.description }),
449
+ ...(view.prefersBorder !== undefined && {
450
+ prefersBorder: view.prefersBorder,
451
+ }),
452
+ ...(view.domain && { domain: view.domain }),
453
+ csp: {
454
+ ...(view.csp?.resourceDomains && {
455
+ resourceDomains: view.csp.resourceDomains,
435
456
  }),
436
- ...(view.domain && { domain: view.domain }),
437
- csp: {
438
- ...(view.csp?.resourceDomains && {
439
- resourceDomains: view.csp.resourceDomains,
440
- }),
441
- ...(view.csp?.connectDomains && {
442
- connectDomains: view.csp.connectDomains,
443
- }),
444
- ...(view.csp?.frameDomains && {
445
- frameDomains: view.csp.frameDomains,
446
- }),
447
- ...(view.csp?.baseUriDomains && {
448
- baseUriDomains: view.csp.baseUriDomains,
449
- }),
450
- ...(view.csp?.redirectDomains && {
451
- redirectDomains: view.csp.redirectDomains,
452
- }),
453
- },
454
- },
455
- };
456
- const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
457
- ui: overrides,
458
- });
459
- if (view._meta) {
460
- return { ...base, ...view._meta };
461
- }
462
- return base;
463
- },
464
- };
465
- this.registerViewResource({
466
- name: toolName,
467
- viewResource,
468
- view,
469
- });
470
- toolMeta["openai/outputTemplate"] = viewResource.uri;
471
- // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
472
- toolMeta["ui/resourceUri"] = viewResource.uri;
473
- toolMeta.ui = { ...toolMeta.ui, resourceUri: viewResource.uri };
474
- }
475
- if (hosts.includes("mcp-app")) {
476
- const viewResource = {
477
- hostType: "mcp-app",
478
- uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
479
- mimeType: "text/html;profile=mcp-app",
480
- buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
481
- const defaults = {
482
- ui: {
483
- csp: {
484
- resourceDomains,
485
- connectDomains,
486
- baseUriDomains,
487
- },
488
- domain,
489
- },
490
- };
491
- const fromView = {
492
- ui: {
493
- ...(view.description && { description: view.description }),
494
- ...(view.prefersBorder !== undefined && {
495
- prefersBorder: view.prefersBorder,
457
+ ...(view.csp?.connectDomains && {
458
+ connectDomains: view.csp.connectDomains,
459
+ }),
460
+ ...(view.csp?.frameDomains && {
461
+ frameDomains: view.csp.frameDomains,
462
+ }),
463
+ ...(view.csp?.baseUriDomains && {
464
+ baseUriDomains: view.csp.baseUriDomains,
496
465
  }),
497
- ...(view.domain && { domain: view.domain }),
498
- csp: {
499
- ...(view.csp?.resourceDomains && {
500
- resourceDomains: view.csp.resourceDomains,
501
- }),
502
- ...(view.csp?.connectDomains && {
503
- connectDomains: view.csp.connectDomains,
504
- }),
505
- ...(view.csp?.frameDomains && {
506
- frameDomains: view.csp.frameDomains,
507
- }),
508
- ...(view.csp?.baseUriDomains && {
509
- baseUriDomains: view.csp.baseUriDomains,
510
- }),
511
- ...(view.csp?.redirectDomains && {
512
- redirectDomains: view.csp.redirectDomains,
513
- }),
514
- },
515
466
  },
516
- };
517
- const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
518
- ui: overrides,
519
- });
520
- if (view._meta) {
521
- return { ...base, ...view._meta };
522
- }
523
- return base;
524
- },
525
- };
526
- this.registerViewResource({
527
- name: toolName,
528
- viewResource,
529
- view,
530
- });
531
- }
467
+ },
468
+ };
469
+ const ui = mergeWithUnion(mergeWithUnion(defaults, fromView), {
470
+ ui: overrides,
471
+ });
472
+ const base = {
473
+ ...ui,
474
+ ...(view.description && {
475
+ "openai/widgetDescription": view.description,
476
+ }),
477
+ ...(view.csp?.redirectDomains && {
478
+ "openai/widgetCSP": { redirect_domains: view.csp.redirectDomains },
479
+ }),
480
+ };
481
+ if (view._meta) {
482
+ return { ...base, ...view._meta };
483
+ }
484
+ return base;
485
+ },
486
+ };
487
+ this.registerViewResource({ name: toolName, viewResource, view });
488
+ // Advertise via the MCP Apps standard pointer only — ChatGPT renders from
489
+ // ui.resourceUri (verified), and not emitting openai/outputTemplate lets us
490
+ // retire the legacy apps-sdk resource later. The legacy apps-sdk URL is still
491
+ // served (see registerViewResource) so already-published apps keep resolving.
492
+ // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
493
+ toolMeta["ui/resourceUri"] = viewResource.uri;
494
+ toolMeta.ui = { ...toolMeta.ui, resourceUri: viewResource.uri };
532
495
  }
533
496
  registerViewResource({ name, viewResource, view, }) {
534
497
  const { hostType, uri: viewUri, mimeType, buildContentMeta } = viewResource;
@@ -543,19 +506,24 @@ export class McpServer extends McpServerBaseOmitted {
543
506
  };
544
507
  this.viewMetaBuilders.set(viewUri, buildMeta);
545
508
  this.viewUriByPath.set(stripQuery(viewUri), viewUri);
509
+ this.serveLegacyAppsSdkUrl(view.component, viewUri);
546
510
  this.registerResource(name, viewUri, { description: view.description }, async (uri, extra) => {
547
511
  const isProduction = process.env.NODE_ENV === "production";
548
- const { serverUrl } = this.resolveViewRequestContext(extra);
512
+ const { serverUrl, assetsBasePath } = this.resolveViewRequestContext(extra);
513
+ // The view resolves all assets (template imports + runtime lazy chunks
514
+ // via `window.skybridge.serverUrl`) against this base, so it carries the
515
+ // proxy path prefix. CSP domains in `buildMeta` stay the bare origin.
516
+ const viewBase = `${serverUrl}${assetsBasePath}`;
549
517
  const html = isProduction
550
518
  ? templateHelper.renderProduction({
551
519
  hostType,
552
- serverUrl,
520
+ serverUrl: viewBase,
553
521
  viewFile: this.lookupViewFile(view.component),
554
522
  styleFile: this.lookupDistFile("style.css") ?? "",
555
523
  })
556
524
  : templateHelper.renderDevelopment({
557
525
  hostType,
558
- serverUrl,
526
+ serverUrl: viewBase,
559
527
  viewName: view.component,
560
528
  });
561
529
  return {
@@ -565,6 +533,11 @@ export class McpServer extends McpServerBaseOmitted {
565
533
  };
566
534
  });
567
535
  }
536
+ serveLegacyAppsSdkUrl(component, canonicalUri) {
537
+ this.viewUriByPath.set(`ui://views/apps-sdk/${component}.html`, canonicalUri);
538
+ this.viewUriByPath.set(`ui://widgets/apps-sdk/${component}.html`, canonicalUri);
539
+ this.viewUriByPath.set(`ui://widgets/ext-apps/${component}.html`, canonicalUri);
540
+ }
568
541
  wrapHandler(cb, { attachViewUUID }) {
569
542
  return async (args, extra) => {
570
543
  const result = await cb(args, extra);