skybridge 0.0.0-dev.ead707a → 0.0.0-dev.eaed8a9

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 (493) hide show
  1. package/README.md +154 -0
  2. package/dist/cli/build-helpers.d.ts +11 -0
  3. package/dist/cli/build-helpers.js +107 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.js +132 -0
  6. package/dist/cli/build-helpers.test.js.map +1 -0
  7. package/dist/cli/build-steps.d.ts +2 -0
  8. package/dist/cli/build-steps.js +73 -0
  9. package/dist/cli/build-steps.js.map +1 -0
  10. package/dist/cli/build-steps.test.js +52 -0
  11. package/dist/cli/build-steps.test.js.map +1 -0
  12. package/dist/cli/detect-port.d.ts +18 -0
  13. package/dist/cli/detect-port.js +50 -0
  14. package/dist/cli/detect-port.js.map +1 -0
  15. package/dist/cli/header.d.ts +1 -1
  16. package/dist/cli/header.js +1 -1
  17. package/dist/cli/header.js.map +1 -1
  18. package/dist/cli/resolve-skybridge-config.d.ts +5 -0
  19. package/dist/cli/resolve-skybridge-config.js +18 -0
  20. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  21. package/dist/cli/run-command.js.map +1 -1
  22. package/dist/cli/run-plain.d.ts +18 -0
  23. package/dist/cli/run-plain.js +89 -0
  24. package/dist/cli/run-plain.js.map +1 -0
  25. package/dist/cli/telemetry.d.ts +7 -0
  26. package/dist/cli/telemetry.js +123 -0
  27. package/dist/cli/telemetry.js.map +1 -0
  28. package/dist/cli/tunnel-control-server.d.ts +9 -0
  29. package/dist/cli/tunnel-control-server.js +31 -0
  30. package/dist/cli/tunnel-control-server.js.map +1 -0
  31. package/dist/cli/tunnel-control-server.test.d.ts +1 -0
  32. package/dist/cli/tunnel-control-server.test.js +39 -0
  33. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  34. package/dist/cli/tunnel-handler.d.ts +3 -0
  35. package/dist/cli/tunnel-handler.js +48 -0
  36. package/dist/cli/tunnel-handler.js.map +1 -0
  37. package/dist/cli/tunnel-handler.test.d.ts +1 -0
  38. package/dist/cli/tunnel-handler.test.js +105 -0
  39. package/dist/cli/tunnel-handler.test.js.map +1 -0
  40. package/dist/cli/tunnel.d.ts +57 -0
  41. package/dist/cli/tunnel.js +154 -0
  42. package/dist/cli/tunnel.js.map +1 -0
  43. package/dist/cli/tunnel.test.d.ts +1 -0
  44. package/dist/cli/tunnel.test.js +190 -0
  45. package/dist/cli/tunnel.test.js.map +1 -0
  46. package/dist/cli/types.d.ts +5 -0
  47. package/dist/cli/types.js +2 -0
  48. package/dist/cli/types.js.map +1 -0
  49. package/dist/cli/use-execute-steps.d.ts +3 -2
  50. package/dist/cli/use-execute-steps.js +6 -1
  51. package/dist/cli/use-execute-steps.js.map +1 -1
  52. package/dist/cli/use-messages.d.ts +3 -0
  53. package/dist/cli/use-messages.js +11 -0
  54. package/dist/cli/use-messages.js.map +1 -0
  55. package/dist/cli/use-nodemon.d.ts +16 -0
  56. package/dist/cli/use-nodemon.js +84 -0
  57. package/dist/cli/use-nodemon.js.map +1 -0
  58. package/dist/cli/use-open-browser.d.ts +1 -0
  59. package/dist/cli/use-open-browser.js +44 -0
  60. package/dist/cli/use-open-browser.js.map +1 -0
  61. package/dist/cli/use-tunnel.d.ts +14 -0
  62. package/dist/cli/use-tunnel.js +131 -0
  63. package/dist/cli/use-tunnel.js.map +1 -0
  64. package/dist/cli/use-typescript-check.d.ts +15 -0
  65. package/dist/cli/use-typescript-check.js +97 -0
  66. package/dist/cli/use-typescript-check.js.map +1 -0
  67. package/dist/commands/build.d.ts +0 -3
  68. package/dist/commands/build.js +3 -16
  69. package/dist/commands/build.js.map +1 -1
  70. package/dist/commands/create.d.ts +9 -0
  71. package/dist/commands/create.js +30 -0
  72. package/dist/commands/create.js.map +1 -0
  73. package/dist/commands/dev.d.ts +5 -1
  74. package/dist/commands/dev.js +109 -13
  75. package/dist/commands/dev.js.map +1 -1
  76. package/dist/commands/start.d.ts +3 -1
  77. package/dist/commands/start.js +37 -15
  78. package/dist/commands/start.js.map +1 -1
  79. package/dist/commands/telemetry/disable.d.ts +5 -0
  80. package/dist/commands/telemetry/disable.js +14 -0
  81. package/dist/commands/telemetry/disable.js.map +1 -0
  82. package/dist/commands/telemetry/enable.d.ts +5 -0
  83. package/dist/commands/telemetry/enable.js +14 -0
  84. package/dist/commands/telemetry/enable.js.map +1 -0
  85. package/dist/commands/telemetry/status.d.ts +5 -0
  86. package/dist/commands/telemetry/status.js +14 -0
  87. package/dist/commands/telemetry/status.js.map +1 -0
  88. package/dist/context-warnings.d.ts +5 -0
  89. package/dist/context-warnings.js +31 -0
  90. package/dist/context-warnings.js.map +1 -0
  91. package/dist/context-warnings.test.d.ts +1 -0
  92. package/dist/context-warnings.test.js +28 -0
  93. package/dist/context-warnings.test.js.map +1 -0
  94. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  95. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  96. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  97. package/dist/server/asset-base-url-transform-plugin.test.d.ts +1 -0
  98. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  99. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  100. package/dist/server/auth/discovery.d.ts +32 -0
  101. package/dist/server/auth/discovery.js +56 -0
  102. package/dist/server/auth/discovery.js.map +1 -0
  103. package/dist/server/auth/discovery.test.d.ts +1 -0
  104. package/dist/server/auth/discovery.test.js +93 -0
  105. package/dist/server/auth/discovery.test.js.map +1 -0
  106. package/dist/server/auth/index.d.ts +44 -0
  107. package/dist/server/auth/index.js +2 -0
  108. package/dist/server/auth/index.js.map +1 -0
  109. package/dist/server/auth/providers/auth0.d.ts +40 -0
  110. package/dist/server/auth/providers/auth0.js +31 -0
  111. package/dist/server/auth/providers/auth0.js.map +1 -0
  112. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  113. package/dist/server/auth/providers/auth0.test.js +50 -0
  114. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  115. package/dist/server/auth/providers/authplane.d.ts +49 -0
  116. package/dist/server/auth/providers/authplane.js +57 -0
  117. package/dist/server/auth/providers/authplane.js.map +1 -0
  118. package/dist/server/auth/providers/authplane.test.d.ts +1 -0
  119. package/dist/server/auth/providers/authplane.test.js +140 -0
  120. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  121. package/dist/server/auth/providers/clerk.d.ts +51 -0
  122. package/dist/server/auth/providers/clerk.js +19 -0
  123. package/dist/server/auth/providers/clerk.js.map +1 -0
  124. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  125. package/dist/server/auth/providers/clerk.test.js +30 -0
  126. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  127. package/dist/server/auth/providers/custom.d.ts +40 -0
  128. package/dist/server/auth/providers/custom.js +56 -0
  129. package/dist/server/auth/providers/custom.js.map +1 -0
  130. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  131. package/dist/server/auth/providers/custom.test.js +158 -0
  132. package/dist/server/auth/providers/custom.test.js.map +1 -0
  133. package/dist/server/auth/providers/descope.d.ts +44 -0
  134. package/dist/server/auth/providers/descope.js +44 -0
  135. package/dist/server/auth/providers/descope.js.map +1 -0
  136. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  137. package/dist/server/auth/providers/descope.test.js +62 -0
  138. package/dist/server/auth/providers/descope.test.js.map +1 -0
  139. package/dist/server/auth/providers/shared.d.ts +2 -0
  140. package/dist/server/auth/providers/shared.js +6 -0
  141. package/dist/server/auth/providers/shared.js.map +1 -0
  142. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  143. package/dist/server/auth/providers/shared.test.js +10 -0
  144. package/dist/server/auth/providers/shared.test.js.map +1 -0
  145. package/dist/server/auth/providers/stytch.d.ts +25 -0
  146. package/dist/server/auth/providers/stytch.js +16 -0
  147. package/dist/server/auth/providers/stytch.js.map +1 -0
  148. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  149. package/dist/server/auth/providers/verify-spy.js +21 -0
  150. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  151. package/dist/server/auth/providers/workos.d.ts +33 -0
  152. package/dist/server/auth/providers/workos.js +15 -0
  153. package/dist/server/auth/providers/workos.js.map +1 -0
  154. package/dist/server/auth/security-schemes.d.ts +23 -0
  155. package/dist/server/auth/security-schemes.js +64 -0
  156. package/dist/server/auth/security-schemes.js.map +1 -0
  157. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  158. package/dist/server/auth/security-schemes.test.js +99 -0
  159. package/dist/server/auth/security-schemes.test.js.map +1 -0
  160. package/dist/server/auth/setup.d.ts +6 -0
  161. package/dist/server/auth/setup.js +92 -0
  162. package/dist/server/auth/setup.js.map +1 -0
  163. package/dist/server/auth/setup.test.d.ts +1 -0
  164. package/dist/server/auth/setup.test.js +508 -0
  165. package/dist/server/auth/setup.test.js.map +1 -0
  166. package/dist/server/auth/verify.d.ts +46 -0
  167. package/dist/server/auth/verify.js +62 -0
  168. package/dist/server/auth/verify.js.map +1 -0
  169. package/dist/server/auth/verify.test.d.ts +1 -0
  170. package/dist/server/auth/verify.test.js +149 -0
  171. package/dist/server/auth/verify.test.js.map +1 -0
  172. package/dist/server/auth-extra.test-d.d.ts +1 -0
  173. package/dist/server/auth-extra.test-d.js +82 -0
  174. package/dist/server/auth-extra.test-d.js.map +1 -0
  175. package/dist/server/auth.d.ts +58 -0
  176. package/dist/server/auth.js +28 -0
  177. package/dist/server/auth.js.map +1 -0
  178. package/dist/server/build-manifest.test.d.ts +1 -0
  179. package/dist/server/build-manifest.test.js +27 -0
  180. package/dist/server/build-manifest.test.js.map +1 -0
  181. package/dist/server/content-helpers.d.ts +67 -0
  182. package/dist/server/content-helpers.js +79 -0
  183. package/dist/server/content-helpers.js.map +1 -0
  184. package/dist/server/content-helpers.test.d.ts +1 -0
  185. package/dist/server/content-helpers.test.js +70 -0
  186. package/dist/server/content-helpers.test.js.map +1 -0
  187. package/dist/server/express.d.ts +11 -0
  188. package/dist/server/express.js +101 -0
  189. package/dist/server/express.js.map +1 -0
  190. package/dist/server/express.test.d.ts +1 -0
  191. package/dist/server/express.test.js +491 -0
  192. package/dist/server/express.test.js.map +1 -0
  193. package/dist/server/file-ref.d.ts +28 -0
  194. package/dist/server/file-ref.js +27 -0
  195. package/dist/server/file-ref.js.map +1 -0
  196. package/dist/server/host.d.ts +2 -0
  197. package/dist/server/host.js +11 -0
  198. package/dist/server/host.js.map +1 -0
  199. package/dist/server/host.test.d.ts +1 -0
  200. package/dist/server/host.test.js +13 -0
  201. package/dist/server/host.test.js.map +1 -0
  202. package/dist/server/index.d.ts +18 -3
  203. package/dist/server/index.js +15 -2
  204. package/dist/server/index.js.map +1 -1
  205. package/dist/server/inferUtilityTypes.d.ts +6 -6
  206. package/dist/server/inferUtilityTypes.js.map +1 -1
  207. package/dist/server/metric.d.ts +14 -0
  208. package/dist/server/metric.js +62 -0
  209. package/dist/server/metric.js.map +1 -0
  210. package/dist/server/middleware.d.ts +162 -0
  211. package/dist/server/middleware.js +126 -0
  212. package/dist/server/middleware.js.map +1 -0
  213. package/dist/server/middleware.test-d.d.ts +1 -0
  214. package/dist/server/middleware.test-d.js +75 -0
  215. package/dist/server/middleware.test-d.js.map +1 -0
  216. package/dist/server/middleware.test.d.ts +1 -0
  217. package/dist/server/middleware.test.js +529 -0
  218. package/dist/server/middleware.test.js.map +1 -0
  219. package/dist/server/requestOrigin.d.ts +7 -0
  220. package/dist/server/requestOrigin.js +25 -0
  221. package/dist/server/requestOrigin.js.map +1 -0
  222. package/dist/server/server.d.ts +426 -60
  223. package/dist/server/server.js +700 -97
  224. package/dist/server/server.js.map +1 -1
  225. package/dist/server/skills-integration.test.d.ts +1 -0
  226. package/dist/server/skills-integration.test.js +79 -0
  227. package/dist/server/skills-integration.test.js.map +1 -0
  228. package/dist/server/skills.d.ts +29 -0
  229. package/dist/server/skills.js +195 -0
  230. package/dist/server/skills.js.map +1 -0
  231. package/dist/server/skills.test.d.ts +1 -0
  232. package/dist/server/skills.test.js +247 -0
  233. package/dist/server/skills.test.js.map +1 -0
  234. package/dist/server/templateHelper.d.ts +5 -7
  235. package/dist/server/templateHelper.js +3 -22
  236. package/dist/server/templateHelper.js.map +1 -1
  237. package/dist/server/templates.generated.d.ts +4 -0
  238. package/dist/server/templates.generated.js +47 -0
  239. package/dist/server/templates.generated.js.map +1 -0
  240. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  241. package/dist/server/tunnel-proxy-router.js +110 -0
  242. package/dist/server/tunnel-proxy-router.js.map +1 -0
  243. package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
  244. package/dist/server/tunnel-proxy-router.test.js +229 -0
  245. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  246. package/dist/server/view-name.test-d.d.ts +1 -0
  247. package/dist/server/view-name.test-d.js +8 -0
  248. package/dist/server/view-name.test-d.js.map +1 -0
  249. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  250. package/dist/server/view-resource-resolution.test.js +171 -0
  251. package/dist/server/view-resource-resolution.test.js.map +1 -0
  252. package/dist/server/viewsDevServer.d.ts +14 -0
  253. package/dist/server/viewsDevServer.js +48 -0
  254. package/dist/server/viewsDevServer.js.map +1 -0
  255. package/dist/test/utils.d.ts +16 -24
  256. package/dist/test/utils.js +42 -37
  257. package/dist/test/utils.js.map +1 -1
  258. package/dist/test/view.test.d.ts +1 -0
  259. package/dist/test/view.test.js +552 -0
  260. package/dist/test/view.test.js.map +1 -0
  261. package/dist/version.d.ts +1 -0
  262. package/dist/version.js +3 -0
  263. package/dist/version.js.map +1 -0
  264. package/dist/web/bridges/adaptor.d.ts +51 -0
  265. package/dist/web/bridges/adaptor.js +327 -0
  266. package/dist/web/bridges/adaptor.js.map +1 -0
  267. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  268. package/dist/web/bridges/adaptor.test.js +225 -0
  269. package/dist/web/bridges/adaptor.test.js.map +1 -0
  270. package/dist/web/bridges/apps-sdk/bridge.d.ts +7 -2
  271. package/dist/web/bridges/apps-sdk/bridge.js +15 -3
  272. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  273. package/dist/web/bridges/apps-sdk/index.d.ts +1 -2
  274. package/dist/web/bridges/apps-sdk/index.js +0 -1
  275. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  276. package/dist/web/bridges/apps-sdk/types.d.ts +38 -26
  277. package/dist/web/bridges/apps-sdk/types.js.map +1 -1
  278. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
  279. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
  280. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  281. package/dist/web/bridges/get-adaptor.d.ts +7 -0
  282. package/dist/web/bridges/get-adaptor.js +9 -7
  283. package/dist/web/bridges/get-adaptor.js.map +1 -1
  284. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  285. package/dist/web/bridges/get-adaptor.test.js +32 -0
  286. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  287. package/dist/web/bridges/index.js.map +1 -1
  288. package/dist/web/bridges/mcp-app/bridge.d.ts +27 -31
  289. package/dist/web/bridges/mcp-app/bridge.js +111 -198
  290. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  291. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  292. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  293. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  294. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  295. package/dist/web/bridges/mcp-app/index.js +0 -1
  296. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  297. package/dist/web/bridges/mcp-app/types.d.ts +2 -0
  298. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  299. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +17 -3
  300. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +14 -2
  301. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  302. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -41
  303. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  304. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  305. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  306. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  307. package/dist/web/bridges/types.d.ts +152 -12
  308. package/dist/web/bridges/types.js +14 -1
  309. package/dist/web/bridges/types.js.map +1 -1
  310. package/dist/web/bridges/types.test.d.ts +1 -0
  311. package/dist/web/bridges/types.test.js +19 -0
  312. package/dist/web/bridges/types.test.js.map +1 -0
  313. package/dist/web/bridges/use-host-context.d.ts +5 -0
  314. package/dist/web/bridges/use-host-context.js +5 -0
  315. package/dist/web/bridges/use-host-context.js.map +1 -1
  316. package/dist/web/components/modal-provider.d.ts +4 -0
  317. package/dist/web/components/modal-provider.js +46 -0
  318. package/dist/web/components/modal-provider.js.map +1 -0
  319. package/dist/web/create-store.d.ts +26 -0
  320. package/dist/web/create-store.js +43 -3
  321. package/dist/web/create-store.js.map +1 -1
  322. package/dist/web/create-store.test.js +31 -25
  323. package/dist/web/create-store.test.js.map +1 -1
  324. package/dist/web/data-llm.d.ts +35 -2
  325. package/dist/web/data-llm.js +31 -3
  326. package/dist/web/data-llm.js.map +1 -1
  327. package/dist/web/data-llm.test.js +51 -35
  328. package/dist/web/data-llm.test.js.map +1 -1
  329. package/dist/web/generate-helpers.d.ts +22 -18
  330. package/dist/web/generate-helpers.js +22 -18
  331. package/dist/web/generate-helpers.js.map +1 -1
  332. package/dist/web/generate-helpers.test-d.js +30 -28
  333. package/dist/web/generate-helpers.test-d.js.map +1 -1
  334. package/dist/web/generate-helpers.test.js.map +1 -1
  335. package/dist/web/helpers/state.d.ts +2 -2
  336. package/dist/web/helpers/state.js +11 -11
  337. package/dist/web/helpers/state.js.map +1 -1
  338. package/dist/web/helpers/state.test.js +9 -9
  339. package/dist/web/helpers/state.test.js.map +1 -1
  340. package/dist/web/hooks/index.d.ts +8 -2
  341. package/dist/web/hooks/index.js +7 -1
  342. package/dist/web/hooks/index.js.map +1 -1
  343. package/dist/web/hooks/test/utils.d.ts +7 -2
  344. package/dist/web/hooks/test/utils.js +18 -3
  345. package/dist/web/hooks/test/utils.js.map +1 -1
  346. package/dist/web/hooks/use-call-tool.d.ts +45 -0
  347. package/dist/web/hooks/use-call-tool.js +28 -0
  348. package/dist/web/hooks/use-call-tool.js.map +1 -1
  349. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
  350. package/dist/web/hooks/use-call-tool.test.js +62 -27
  351. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  352. package/dist/web/hooks/use-display-mode.d.ts +23 -3
  353. package/dist/web/hooks/use-display-mode.js +20 -0
  354. package/dist/web/hooks/use-display-mode.js.map +1 -1
  355. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  356. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  357. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  358. package/dist/web/hooks/use-display-mode.test.js +56 -20
  359. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  360. package/dist/web/hooks/use-download.d.ts +5 -0
  361. package/dist/web/hooks/use-download.js +8 -0
  362. package/dist/web/hooks/use-download.js.map +1 -0
  363. package/dist/web/hooks/use-download.test.d.ts +1 -0
  364. package/dist/web/hooks/use-download.test.js +103 -0
  365. package/dist/web/hooks/use-download.test.js.map +1 -0
  366. package/dist/web/hooks/use-files.d.ts +35 -6
  367. package/dist/web/hooks/use-files.js +37 -2
  368. package/dist/web/hooks/use-files.js.map +1 -1
  369. package/dist/web/hooks/use-files.test.js +36 -3
  370. package/dist/web/hooks/use-files.test.js.map +1 -1
  371. package/dist/web/hooks/use-host-info.d.ts +22 -0
  372. package/dist/web/hooks/use-host-info.js +30 -0
  373. package/dist/web/hooks/use-host-info.js.map +1 -0
  374. package/dist/web/hooks/use-host-info.test.d.ts +1 -0
  375. package/dist/web/hooks/use-host-info.test.js +59 -0
  376. package/dist/web/hooks/use-host-info.test.js.map +1 -0
  377. package/dist/web/hooks/use-layout.d.ts +2 -0
  378. package/dist/web/hooks/use-layout.js +2 -0
  379. package/dist/web/hooks/use-layout.js.map +1 -1
  380. package/dist/web/hooks/use-layout.test.js +62 -29
  381. package/dist/web/hooks/use-layout.test.js.map +1 -1
  382. package/dist/web/hooks/use-open-external.d.ts +20 -1
  383. package/dist/web/hooks/use-open-external.js +17 -1
  384. package/dist/web/hooks/use-open-external.js.map +1 -1
  385. package/dist/web/hooks/use-open-external.test.js +38 -13
  386. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  387. package/dist/web/hooks/use-register-view-tool.d.ts +38 -0
  388. package/dist/web/hooks/use-register-view-tool.js +50 -0
  389. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  390. package/dist/web/hooks/use-request-close.d.ts +16 -0
  391. package/dist/web/hooks/use-request-close.js +21 -0
  392. package/dist/web/hooks/use-request-close.js.map +1 -0
  393. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  394. package/dist/web/hooks/use-request-close.test.js +47 -0
  395. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  396. package/dist/web/hooks/use-request-modal.d.ts +18 -3
  397. package/dist/web/hooks/use-request-modal.js +25 -8
  398. package/dist/web/hooks/use-request-modal.js.map +1 -1
  399. package/dist/web/hooks/use-request-modal.test.js +15 -1
  400. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  401. package/dist/web/hooks/use-request-size.d.ts +20 -0
  402. package/dist/web/hooks/use-request-size.js +24 -0
  403. package/dist/web/hooks/use-request-size.js.map +1 -0
  404. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  405. package/dist/web/hooks/use-request-size.test.js +47 -0
  406. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  407. package/dist/web/hooks/use-send-follow-up-message.d.ts +19 -1
  408. package/dist/web/hooks/use-send-follow-up-message.js +19 -2
  409. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  410. package/dist/web/hooks/use-set-open-in-app-url.d.ts +18 -0
  411. package/dist/web/hooks/use-set-open-in-app-url.js +25 -0
  412. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  413. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  414. package/dist/web/hooks/use-set-open-in-app-url.test.js +63 -0
  415. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  416. package/dist/web/hooks/use-tool-info.d.ts +53 -2
  417. package/dist/web/hooks/use-tool-info.js +30 -7
  418. package/dist/web/hooks/use-tool-info.js.map +1 -1
  419. package/dist/web/hooks/use-tool-info.test-d.js +11 -29
  420. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  421. package/dist/web/hooks/use-tool-info.test.js +43 -33
  422. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  423. package/dist/web/hooks/use-user.d.ts +2 -0
  424. package/dist/web/hooks/use-user.js +20 -2
  425. package/dist/web/hooks/use-user.js.map +1 -1
  426. package/dist/web/hooks/use-user.test.js +101 -27
  427. package/dist/web/hooks/use-user.test.js.map +1 -1
  428. package/dist/web/hooks/use-view-state.d.ts +25 -0
  429. package/dist/web/hooks/use-view-state.js +42 -0
  430. package/dist/web/hooks/use-view-state.js.map +1 -0
  431. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  432. package/dist/web/hooks/use-view-state.test.js +212 -0
  433. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  434. package/dist/web/index.d.ts +1 -2
  435. package/dist/web/index.js +1 -2
  436. package/dist/web/index.js.map +1 -1
  437. package/dist/web/mount-view.d.ts +20 -0
  438. package/dist/web/mount-view.js +46 -0
  439. package/dist/web/mount-view.js.map +1 -0
  440. package/dist/web/plugin/data-llm.test.js.map +1 -1
  441. package/dist/web/plugin/plugin-build.test.d.ts +1 -0
  442. package/dist/web/plugin/plugin-build.test.js +54 -0
  443. package/dist/web/plugin/plugin-build.test.js.map +1 -0
  444. package/dist/web/plugin/plugin.d.ts +38 -1
  445. package/dist/web/plugin/plugin.js +179 -18
  446. package/dist/web/plugin/plugin.js.map +1 -1
  447. package/dist/web/plugin/plugin.test.d.ts +1 -0
  448. package/dist/web/plugin/plugin.test.js +61 -0
  449. package/dist/web/plugin/plugin.test.js.map +1 -0
  450. package/dist/web/plugin/scan-views.d.ts +16 -0
  451. package/dist/web/plugin/scan-views.js +88 -0
  452. package/dist/web/plugin/scan-views.js.map +1 -0
  453. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  454. package/dist/web/plugin/scan-views.test.js +99 -0
  455. package/dist/web/plugin/scan-views.test.js.map +1 -0
  456. package/dist/web/plugin/transform-data-llm.js +1 -1
  457. package/dist/web/plugin/transform-data-llm.js.map +1 -1
  458. package/dist/web/plugin/transform-data-llm.test.js.map +1 -1
  459. package/dist/web/plugin/validate-view.d.ts +1 -0
  460. package/dist/web/plugin/validate-view.js +9 -0
  461. package/dist/web/plugin/validate-view.js.map +1 -0
  462. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  463. package/dist/web/plugin/validate-view.test.js +24 -0
  464. package/dist/web/plugin/validate-view.test.js.map +1 -0
  465. package/dist/web/proxy.js +0 -1
  466. package/dist/web/proxy.js.map +1 -1
  467. package/dist/web/types.d.ts +4 -0
  468. package/dist/web/types.js.map +1 -1
  469. package/package.json +59 -30
  470. package/tsconfig.base.json +33 -0
  471. package/dist/server/templates/development.hbs +0 -66
  472. package/dist/server/templates/production.hbs +0 -7
  473. package/dist/server/widgetsDevServer.d.ts +0 -12
  474. package/dist/server/widgetsDevServer.js +0 -47
  475. package/dist/server/widgetsDevServer.js.map +0 -1
  476. package/dist/test/widget.test.js +0 -255
  477. package/dist/test/widget.test.js.map +0 -1
  478. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -14
  479. package/dist/web/bridges/apps-sdk/adaptor.js +0 -39
  480. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  481. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -19
  482. package/dist/web/bridges/mcp-app/adaptor.js +0 -145
  483. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
  484. package/dist/web/hooks/use-widget-state.d.ts +0 -4
  485. package/dist/web/hooks/use-widget-state.js +0 -32
  486. package/dist/web/hooks/use-widget-state.js.map +0 -1
  487. package/dist/web/hooks/use-widget-state.test.js +0 -61
  488. package/dist/web/hooks/use-widget-state.test.js.map +0 -1
  489. package/dist/web/mount-widget.d.ts +0 -1
  490. package/dist/web/mount-widget.js +0 -19
  491. package/dist/web/mount-widget.js.map +0 -1
  492. /package/dist/{test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  493. /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/build-steps.test.d.ts} +0 -0
@@ -0,0 +1,552 @@
1
+ import crypto from "node:crypto";
2
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
+ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
4
+ import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
5
+ import { TOOL_OUTPUT_WARNING_TOKENS } from "../context-warnings.js";
6
+ import { McpServer as McpServerClass } from "../server/server.js";
7
+ import { createMockExtra, createMockMcpServer, resetTestEnv, setTestEnv, } from "./utils.js";
8
+ const mockManifest = {
9
+ "skybridge:view:my-view": {
10
+ file: "assets/my-view-abc123.js",
11
+ name: "my-view",
12
+ isEntry: true,
13
+ },
14
+ "skybridge:view:folder-view": {
15
+ file: "assets/folder-view-def456.js",
16
+ name: "folder-view",
17
+ isEntry: true,
18
+ },
19
+ "style.css": { file: "style.css" },
20
+ };
21
+ // Mirrors `McpServer.computeViewVersionParam`. Tests recompute the expected
22
+ // hash from the mocked manifest so they don't hardcode digest output.
23
+ function expectedVersionParam(viewFile, styleFile) {
24
+ const hash = crypto
25
+ .createHash("sha256")
26
+ .update(viewFile)
27
+ .update("\0")
28
+ .update(styleFile)
29
+ .digest("hex")
30
+ .slice(0, 8);
31
+ return `?v=${hash}`;
32
+ }
33
+ const actual = vi.hoisted(() => require("node:fs"));
34
+ vi.mock("node:fs", () => {
35
+ const readFileSyncImpl = (path, ...args) => {
36
+ if (typeof path === "string" && path.includes("manifest.json")) {
37
+ return JSON.stringify(mockManifest);
38
+ }
39
+ return actual.readFileSync(path, ...args);
40
+ };
41
+ const readFileSync = vi.fn(readFileSyncImpl);
42
+ return {
43
+ readFileSync,
44
+ default: {
45
+ readFileSync,
46
+ },
47
+ };
48
+ });
49
+ describe("McpServer.registerTool (unified API)", () => {
50
+ let server;
51
+ let mockRegisterResource;
52
+ let mockRegisterTool;
53
+ beforeEach(() => {
54
+ ({ server, mockRegisterResource, mockRegisterTool } =
55
+ createMockMcpServer());
56
+ });
57
+ afterEach(() => {
58
+ vi.clearAllMocks();
59
+ resetTestEnv();
60
+ });
61
+ it("should generate correct HTML for development mode", async () => {
62
+ setTestEnv({ NODE_ENV: "development" });
63
+ server.registerTool({
64
+ name: "my-view",
65
+ description: "Test tool",
66
+ view: {
67
+ component: "my-view",
68
+ description: "Test view",
69
+ },
70
+ }, vi.fn());
71
+ const appsSdkResourceCallback = mockRegisterResource.mock
72
+ .calls[0]?.[3];
73
+ expect(appsSdkResourceCallback).toBeDefined();
74
+ const host = "localhost:3000";
75
+ const serverUrl = `http://${host}`;
76
+ const hmrUrl = `ws://${host}`;
77
+ const mockExtra = createMockExtra(host);
78
+ const result = await appsSdkResourceCallback(new URL("ui://views/ext-apps/my-view.html"), mockExtra);
79
+ expect(mockRegisterTool).toHaveBeenCalled();
80
+ expect(result).toEqual({
81
+ contents: [
82
+ {
83
+ uri: "ui://views/ext-apps/my-view.html",
84
+ mimeType: "text/html;profile=mcp-app",
85
+ text: expect.stringContaining('<div id="root"></div>'),
86
+ _meta: {
87
+ ui: {
88
+ csp: {
89
+ resourceDomains: [serverUrl],
90
+ connectDomains: [serverUrl, hmrUrl],
91
+ baseUriDomains: [serverUrl],
92
+ },
93
+ domain: serverUrl,
94
+ description: "Test view",
95
+ },
96
+ "openai/widgetDescription": "Test view",
97
+ },
98
+ },
99
+ ],
100
+ });
101
+ expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/@react-refresh`);
102
+ expect(result.contents[0]?.text).toContain(`${serverUrl}/@vite/client`);
103
+ expect(result.contents[0]?.text).toContain(`${serverUrl}/_skybridge/view/my-view`);
104
+ });
105
+ it("should generate correct HTML for production mode", async () => {
106
+ setTestEnv({ NODE_ENV: "production" });
107
+ server.registerTool({
108
+ name: "my-view",
109
+ description: "Test tool",
110
+ view: {
111
+ component: "my-view",
112
+ description: "Test view",
113
+ },
114
+ }, vi.fn());
115
+ const appsSdkResourceCallback = mockRegisterResource.mock
116
+ .calls[0]?.[3];
117
+ expect(appsSdkResourceCallback).toBeDefined();
118
+ const host = "myapp.com";
119
+ const serverUrl = `https://${host}`;
120
+ const mockExtra = createMockExtra(host);
121
+ const versionedUri = `ui://views/ext-apps/my-view.html${expectedVersionParam("assets/my-view-abc123.js", "style.css")}`;
122
+ const result = await appsSdkResourceCallback(new URL(versionedUri), mockExtra);
123
+ expect(result).toEqual({
124
+ contents: [
125
+ {
126
+ uri: versionedUri,
127
+ mimeType: "text/html;profile=mcp-app",
128
+ text: expect.stringContaining('<div id="root"></div>'),
129
+ _meta: {
130
+ ui: {
131
+ csp: {
132
+ resourceDomains: [serverUrl],
133
+ connectDomains: [serverUrl],
134
+ baseUriDomains: [serverUrl],
135
+ },
136
+ domain: serverUrl,
137
+ description: "Test view",
138
+ },
139
+ "openai/widgetDescription": "Test view",
140
+ },
141
+ },
142
+ ],
143
+ });
144
+ expect(result.contents[0]?.text).not.toContain(`${serverUrl}/assets/@react-refresh`);
145
+ expect(result.contents[0]?.text).not.toContain(`${serverUrl}@vite/client`);
146
+ expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/assets/my-view-abc123.js`);
147
+ expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/style.css`);
148
+ });
149
+ it("should prefer x-alpic-forwarded-url when hashing Claude view domains", async () => {
150
+ setTestEnv({ NODE_ENV: "production" });
151
+ server.registerTool({
152
+ name: "my-view",
153
+ description: "Test tool",
154
+ view: { component: "my-view", description: "Test view" },
155
+ }, vi.fn());
156
+ const extAppsResourceCallback = mockRegisterResource.mock
157
+ .calls[0]?.[3];
158
+ expect(extAppsResourceCallback).toBeDefined();
159
+ const forwardedUrl = "https://everything-3a2c1264.staging.alpic.live/mcp?foo=bar";
160
+ const expectedDomain = `${crypto
161
+ .createHash("sha256")
162
+ .update(forwardedUrl)
163
+ .digest("hex")
164
+ .slice(0, 32)}.claudemcpcontent.com`;
165
+ const result = await extAppsResourceCallback(new URL(`ui://views/ext-apps/my-view.html${expectedVersionParam("assets/my-view-abc123.js", "style.css")}`), createMockExtra("localhost:3000", {
166
+ headers: {
167
+ "user-agent": "Claude-User",
168
+ "x-alpic-forwarded-url": forwardedUrl,
169
+ },
170
+ url: "http://localhost:3000/mcp",
171
+ }));
172
+ expect(result.contents[0]?._meta).toEqual({
173
+ ui: {
174
+ csp: {
175
+ resourceDomains: ["http://localhost:3000"],
176
+ connectDomains: ["http://localhost:3000"],
177
+ baseUriDomains: ["http://localhost:3000"],
178
+ },
179
+ description: "Test view",
180
+ domain: expectedDomain,
181
+ },
182
+ "openai/widgetDescription": "Test view",
183
+ });
184
+ });
185
+ it("should register a single ext-apps resource", async () => {
186
+ server.registerTool({
187
+ name: "my-view",
188
+ description: "Test tool",
189
+ view: {
190
+ component: "my-view",
191
+ description: "Test view",
192
+ prefersBorder: true,
193
+ },
194
+ }, vi.fn());
195
+ expect(mockRegisterResource).toHaveBeenCalledTimes(1);
196
+ const resourceCallback = mockRegisterResource.mock
197
+ .calls[0]?.[3];
198
+ const host = "localhost:3000";
199
+ const serverUrl = `http://${host}`;
200
+ const hmrUrl = `ws://${host}`;
201
+ const result = await resourceCallback(new URL("ui://views/ext-apps/my-view.html"), createMockExtra(host));
202
+ expect(result).toEqual({
203
+ contents: [
204
+ {
205
+ uri: "ui://views/ext-apps/my-view.html",
206
+ mimeType: "text/html;profile=mcp-app",
207
+ text: expect.stringContaining('<div id="root"></div>'),
208
+ _meta: {
209
+ ui: {
210
+ csp: {
211
+ resourceDomains: [serverUrl],
212
+ connectDomains: [serverUrl, hmrUrl],
213
+ baseUriDomains: [serverUrl],
214
+ },
215
+ domain: serverUrl,
216
+ description: "Test view",
217
+ prefersBorder: true,
218
+ },
219
+ "openai/widgetDescription": "Test view",
220
+ },
221
+ },
222
+ ],
223
+ });
224
+ expect(result.contents[0]?.text).toContain('window.skybridge = { hostType: "mcp-app", serverUrl: "http://localhost:3000" };');
225
+ });
226
+ it("should advertise the single resource via ui.resourceUri only (no openai/outputTemplate)", async () => {
227
+ server.registerTool({
228
+ name: "my-view",
229
+ description: "Test tool",
230
+ view: { component: "my-view", description: "Test view" },
231
+ }, vi.fn());
232
+ const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
233
+ const uri = "ui://views/ext-apps/my-view.html";
234
+ expect(toolConfig._meta?.ui?.resourceUri).toBe(uri);
235
+ expect(toolConfig._meta?.["ui/resourceUri"]).toBe(uri);
236
+ expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
237
+ });
238
+ it("treats the deprecated hosts option as a no-op (always the single resource)", async () => {
239
+ server.registerTool({
240
+ name: "my-view",
241
+ description: "Test tool",
242
+ view: {
243
+ component: "my-view",
244
+ description: "Test view",
245
+ hosts: ["apps-sdk"],
246
+ },
247
+ }, vi.fn());
248
+ expect(mockRegisterResource).toHaveBeenCalledTimes(1);
249
+ const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
250
+ expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/my-view.html");
251
+ expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
252
+ });
253
+ it("should not version view URIs in development", () => {
254
+ server.registerTool({
255
+ name: "my-view",
256
+ description: "Test tool",
257
+ view: { component: "my-view", description: "Test view" },
258
+ }, vi.fn());
259
+ const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
260
+ expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
261
+ expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/my-view.html");
262
+ // The URI registered with the resource handler must match ui.resourceUri
263
+ // exactly so the SDK can resolve `resources/read` requests.
264
+ expect(mockRegisterResource.mock.calls[0]?.[1]).toBe("ui://views/ext-apps/my-view.html");
265
+ });
266
+ it("should append a stable content hash to view URIs in production", () => {
267
+ setTestEnv({ NODE_ENV: "production" });
268
+ server.registerTool({
269
+ name: "my-view",
270
+ description: "Test tool",
271
+ view: { component: "my-view", description: "Test view" },
272
+ }, vi.fn());
273
+ const expected = expectedVersionParam("assets/my-view-abc123.js", "style.css");
274
+ const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
275
+ expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
276
+ expect(toolConfig._meta?.ui?.resourceUri).toBe(`ui://views/ext-apps/my-view.html${expected}`);
277
+ expect(mockRegisterResource.mock.calls[0]?.[1]).toBe(`ui://views/ext-apps/my-view.html${expected}`);
278
+ });
279
+ it("should produce different version params for views with different bundles", () => {
280
+ setTestEnv({ NODE_ENV: "production" });
281
+ server.registerTool({
282
+ name: "my-view",
283
+ description: "First tool",
284
+ view: { component: "my-view" },
285
+ }, vi.fn());
286
+ server.registerTool({
287
+ name: "folder-view",
288
+ description: "Second tool",
289
+ view: { component: "folder-view" },
290
+ }, vi.fn());
291
+ const myviewTemplate = mockRegisterTool.mock.calls[0][1]._meta?.ui?.resourceUri;
292
+ const folderviewTemplate = mockRegisterTool.mock.calls[1][1]._meta?.ui?.resourceUri;
293
+ expect(myviewTemplate).not.toEqual(folderviewTemplate);
294
+ expect(myviewTemplate).toMatch(/\?v=[0-9a-f]{8}$/);
295
+ expect(folderviewTemplate).toMatch(/\?v=[0-9a-f]{8}$/);
296
+ });
297
+ it("should fall back to bare URI in production when manifest is missing", () => {
298
+ setTestEnv({ NODE_ENV: "production" });
299
+ server.registerTool({
300
+ name: "unknown-view",
301
+ description: "Test tool",
302
+ view: { component: "unknown-view" },
303
+ }, vi.fn());
304
+ const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
305
+ expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/unknown-view.html");
306
+ });
307
+ it("should inject viewUUID into _meta of tool callback results", async () => {
308
+ const mockToolCallback = vi.fn().mockResolvedValue({
309
+ content: [{ type: "text", text: "result" }],
310
+ structuredContent: { data: "test" },
311
+ });
312
+ server.registerTool({
313
+ name: "my-view",
314
+ description: "Test tool",
315
+ view: { component: "my-view", description: "Test view" },
316
+ }, mockToolCallback);
317
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
318
+ expect(wrappedCallback).toBeDefined();
319
+ const result = await wrappedCallback({}, {});
320
+ expect(result._meta).toBeDefined();
321
+ expect(result._meta?.viewUUID).toBeDefined();
322
+ expect(typeof result._meta?.viewUUID).toBe("string");
323
+ expect(result._meta?.viewUUID).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
324
+ });
325
+ it("warns when a tool callback returns large model-visible output", async () => {
326
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
327
+ server.registerTool({ name: "large-output", description: "Test tool" }, vi.fn().mockResolvedValue({
328
+ content: [
329
+ {
330
+ type: "text",
331
+ text: "x".repeat(TOOL_OUTPUT_WARNING_TOKENS * 4),
332
+ },
333
+ ],
334
+ }));
335
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
336
+ await wrappedCallback({}, {});
337
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Tool "large-output" returned'));
338
+ warnSpy.mockRestore();
339
+ });
340
+ it("should preserve existing _meta when injecting viewUUID", async () => {
341
+ const mockToolCallback = vi.fn().mockResolvedValue({
342
+ content: [{ type: "text", text: "result" }],
343
+ structuredContent: { data: "test" },
344
+ _meta: { requestId: "req-123", cached: true },
345
+ });
346
+ server.registerTool({
347
+ name: "my-view",
348
+ description: "Test tool",
349
+ view: { component: "my-view", description: "Test view" },
350
+ }, mockToolCallback);
351
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
352
+ const result = await wrappedCallback({}, {});
353
+ expect(result._meta?.requestId).toBe("req-123");
354
+ expect(result._meta?.cached).toBe(true);
355
+ expect(result._meta?.viewUUID).toBeDefined();
356
+ });
357
+ it("should generate unique viewUUIDs across calls", async () => {
358
+ const mockToolCallback = vi.fn().mockResolvedValue({
359
+ content: [{ type: "text", text: "result" }],
360
+ structuredContent: {},
361
+ });
362
+ server.registerTool({
363
+ name: "my-view",
364
+ description: "Test tool",
365
+ view: { component: "my-view", description: "Test view" },
366
+ }, mockToolCallback);
367
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
368
+ const result1 = await wrappedCallback({}, {});
369
+ const result2 = await wrappedCallback({}, {});
370
+ expect(result1._meta?.viewUUID).not.toBe(result2._meta?.viewUUID);
371
+ });
372
+ it("should enforce one-tool-per-view constraint", () => {
373
+ server.registerTool({
374
+ name: "shake",
375
+ description: "First tool",
376
+ view: { component: "magic-8-ball" },
377
+ }, vi.fn());
378
+ expect(() => {
379
+ server.registerTool({
380
+ name: "shake-v2",
381
+ description: "Second tool",
382
+ view: { component: "magic-8-ball" },
383
+ }, vi.fn());
384
+ }).toThrow('skybridge: view "magic-8-ball" is already used by tool "shake"');
385
+ });
386
+ it("should normalize string content to ContentBlock array", async () => {
387
+ const mockToolCallback = vi.fn().mockResolvedValue({
388
+ content: "Hello world",
389
+ structuredContent: {},
390
+ });
391
+ server.registerTool({
392
+ name: "string-content",
393
+ description: "Test tool",
394
+ view: { component: "string-content" },
395
+ }, mockToolCallback);
396
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
397
+ const result = await wrappedCallback({}, {});
398
+ expect(result.content).toEqual([{ type: "text", text: "Hello world" }]);
399
+ });
400
+ it("should normalize single ContentBlock to array", async () => {
401
+ const mockToolCallback = vi.fn().mockResolvedValue({
402
+ content: { type: "text", text: "Single block" },
403
+ structuredContent: {},
404
+ });
405
+ server.registerTool({
406
+ name: "single-block",
407
+ description: "Test tool",
408
+ view: { component: "single-block" },
409
+ }, mockToolCallback);
410
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
411
+ const result = await wrappedCallback({}, {});
412
+ expect(result.content).toEqual([{ type: "text", text: "Single block" }]);
413
+ });
414
+ it("should pass through ContentBlock array unchanged", async () => {
415
+ const blocks = [
416
+ { type: "text", text: "A" },
417
+ { type: "text", text: "B" },
418
+ ];
419
+ const mockToolCallback = vi.fn().mockResolvedValue({
420
+ content: blocks,
421
+ structuredContent: {},
422
+ });
423
+ server.registerTool({
424
+ name: "array-content",
425
+ description: "Test tool",
426
+ view: { component: "array-content" },
427
+ }, mockToolCallback);
428
+ const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
429
+ const result = await wrappedCallback({}, {});
430
+ expect(result.content).toEqual(blocks);
431
+ });
432
+ it("should register tool without view (no resource registration)", () => {
433
+ server.registerTool({
434
+ name: "plain-tool",
435
+ description: "No view",
436
+ }, vi.fn());
437
+ expect(mockRegisterResource).not.toHaveBeenCalled();
438
+ expect(mockRegisterTool).toHaveBeenCalledTimes(1);
439
+ });
440
+ it("should apply view.csp fields to resource _meta", async () => {
441
+ server.registerTool({
442
+ name: "csp-tool",
443
+ description: "Test tool",
444
+ view: {
445
+ component: "csp-tool",
446
+ description: "Test view",
447
+ csp: {
448
+ connectDomains: ["https://api.example.com"],
449
+ resourceDomains: ["https://cdn.example.com"],
450
+ },
451
+ },
452
+ }, vi.fn());
453
+ const appsSdkCallback = mockRegisterResource.mock
454
+ .calls[0]?.[3];
455
+ const host = "localhost:3000";
456
+ const serverUrl = `http://${host}`;
457
+ const hmrUrl = `ws://${host}`;
458
+ const result = await appsSdkCallback(new URL("ui://views/ext-apps/csp-tool.html"), createMockExtra(host));
459
+ const meta = result.contents[0]?._meta;
460
+ expect(meta.ui?.csp).toEqual({
461
+ resourceDomains: [serverUrl, "https://cdn.example.com"],
462
+ connectDomains: [serverUrl, hmrUrl, "https://api.example.com"],
463
+ baseUriDomains: [serverUrl],
464
+ });
465
+ });
466
+ it("should let view._meta override framework-computed keys", async () => {
467
+ server.registerTool({
468
+ name: "override-tool",
469
+ description: "Test tool",
470
+ view: {
471
+ component: "override-tool",
472
+ description: "Test view",
473
+ csp: { connectDomains: ["https://api.x.com"] },
474
+ _meta: {
475
+ ui: {
476
+ csp: {
477
+ connectDomains: ["https://api.y.com"],
478
+ },
479
+ },
480
+ },
481
+ },
482
+ }, vi.fn());
483
+ const appsSdkCallback = mockRegisterResource.mock
484
+ .calls[0]?.[3];
485
+ const result = await appsSdkCallback(new URL("ui://views/ext-apps/override-tool.html"), createMockExtra("localhost:3000"));
486
+ const meta = result.contents[0]?._meta;
487
+ expect(meta.ui?.csp).toEqual({
488
+ connectDomains: ["https://api.y.com"],
489
+ });
490
+ });
491
+ it("should pass user _meta keys through to tool config", () => {
492
+ server.registerTool({
493
+ name: "meta-tool",
494
+ description: "Test tool",
495
+ _meta: {
496
+ "openai/widgetAccessible": true,
497
+ "openai/toolInvocation/invoking": "Loading...",
498
+ "acme.com/category": "utility",
499
+ },
500
+ }, vi.fn());
501
+ const toolCallArgs = mockRegisterTool.mock.calls[0];
502
+ const toolConfig = toolCallArgs?.[1];
503
+ expect(toolConfig._meta?.["openai/widgetAccessible"]).toBe(true);
504
+ expect(toolConfig._meta?.["openai/toolInvocation/invoking"]).toBe("Loading...");
505
+ expect(toolConfig._meta?.["acme.com/category"]).toBe("utility");
506
+ });
507
+ });
508
+ describe("resources/list view _meta injection", () => {
509
+ afterEach(() => resetTestEnv());
510
+ it("attaches CSP, domain, and connectDomains _meta to view resources at list time", async () => {
511
+ setTestEnv({ NODE_ENV: "production" });
512
+ const server = new McpServerClass({ name: "test", version: "1.0.0" }, { capabilities: {} });
513
+ server.registerTool({
514
+ name: "start",
515
+ description: "Start",
516
+ view: {
517
+ component: "my-view",
518
+ description: "Onboarding deck",
519
+ domain: "skybridge.tech",
520
+ csp: {
521
+ resourceDomains: ["https://fonts.googleapis.com"],
522
+ redirectDomains: ["https://docs.skybridge.tech"],
523
+ },
524
+ },
525
+ }, vi.fn().mockResolvedValue({
526
+ content: [{ type: "text", text: "ok" }],
527
+ structuredContent: {},
528
+ }));
529
+ const client = new Client({ name: "test-client", version: "1.0.0" });
530
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
531
+ await server.connect(serverTransport);
532
+ await client.connect(clientTransport);
533
+ const { resources } = await client.listResources();
534
+ await client.close();
535
+ await server.close();
536
+ const appsSdk = resources.find((r) => r.uri.includes("apps-sdk"));
537
+ const extApps = resources.find((r) => r.uri.includes("ext-apps"));
538
+ expect(appsSdk).toBeUndefined();
539
+ expect(extApps?._meta).toBeDefined();
540
+ const extUi = extApps._meta?.ui;
541
+ expect(extUi?.csp?.connectDomains?.length).toBeGreaterThan(0);
542
+ expect(extUi?.csp?.resourceDomains).toContain("https://fonts.googleapis.com");
543
+ expect(extUi?.domain).toBe("skybridge.tech");
544
+ const meta = extApps?._meta;
545
+ expect(meta["openai/widgetDescription"]).toBe("Onboarding deck");
546
+ expect(meta["openai/widgetCSP"]?.redirect_domains).toEqual([
547
+ "https://docs.skybridge.tech",
548
+ ]);
549
+ expect(meta.ui?.csp).not.toHaveProperty("redirectDomains");
550
+ });
551
+ });
552
+ //# sourceMappingURL=view.test.js.map