skybridge 0.0.0-dev.e97960f → 0.0.0-dev.e99ee17

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 (439) hide show
  1. package/README.md +126 -124
  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 +2 -2
  13. package/dist/cli/detect-port.js +8 -20
  14. package/dist/cli/detect-port.js.map +1 -1
  15. package/dist/cli/header.d.ts +1 -1
  16. package/dist/cli/resolve-skybridge-config.d.ts +5 -0
  17. package/dist/cli/resolve-skybridge-config.js +18 -0
  18. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  19. package/dist/cli/run-plain.d.ts +18 -0
  20. package/dist/cli/run-plain.js +90 -0
  21. package/dist/cli/run-plain.js.map +1 -0
  22. package/dist/cli/telemetry.js +2 -0
  23. package/dist/cli/telemetry.js.map +1 -1
  24. package/dist/cli/use-execute-steps.d.ts +1 -1
  25. package/dist/cli/use-nodemon.d.ts +25 -1
  26. package/dist/cli/use-nodemon.js +96 -63
  27. package/dist/cli/use-nodemon.js.map +1 -1
  28. package/dist/cli/use-typescript-check.d.ts +8 -2
  29. package/dist/cli/use-typescript-check.js +71 -68
  30. package/dist/cli/use-typescript-check.js.map +1 -1
  31. package/dist/commands/build.d.ts +0 -3
  32. package/dist/commands/build.js +2 -73
  33. package/dist/commands/build.js.map +1 -1
  34. package/dist/commands/create.d.ts +9 -0
  35. package/dist/commands/create.js +30 -0
  36. package/dist/commands/create.js.map +1 -0
  37. package/dist/commands/dev.d.ts +1 -0
  38. package/dist/commands/dev.js +51 -3
  39. package/dist/commands/dev.js.map +1 -1
  40. package/dist/commands/start.js +7 -1
  41. package/dist/commands/start.js.map +1 -1
  42. package/dist/context-warnings.d.ts +5 -0
  43. package/dist/context-warnings.js +31 -0
  44. package/dist/context-warnings.js.map +1 -0
  45. package/dist/context-warnings.test.js +28 -0
  46. package/dist/context-warnings.test.js.map +1 -0
  47. package/dist/server/app.d.ts +194 -0
  48. package/dist/server/app.js +266 -0
  49. package/dist/server/app.js.map +1 -0
  50. package/dist/server/app.test.js +97 -0
  51. package/dist/server/app.test.js.map +1 -0
  52. package/dist/server/asset-base-url-transform-plugin.d.ts +1 -0
  53. package/dist/server/asset-base-url-transform-plugin.js +16 -1
  54. package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
  55. package/dist/server/asset-base-url-transform-plugin.test.js +51 -1
  56. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
  57. package/dist/server/auth/discovery.d.ts +33 -0
  58. package/dist/server/auth/discovery.js +56 -0
  59. package/dist/server/auth/discovery.js.map +1 -0
  60. package/dist/server/auth/discovery.test.d.ts +1 -0
  61. package/dist/server/auth/discovery.test.js +93 -0
  62. package/dist/server/auth/discovery.test.js.map +1 -0
  63. package/dist/server/auth/index.d.ts +48 -0
  64. package/dist/server/auth/index.js +2 -0
  65. package/dist/server/auth/index.js.map +1 -0
  66. package/dist/server/auth/providers/auth0.d.ts +40 -0
  67. package/dist/server/auth/providers/auth0.js +36 -0
  68. package/dist/server/auth/providers/auth0.js.map +1 -0
  69. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  70. package/dist/server/auth/providers/auth0.test.js +50 -0
  71. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  72. package/dist/server/auth/providers/authplane.d.ts +49 -0
  73. package/dist/server/auth/providers/authplane.js +57 -0
  74. package/dist/server/auth/providers/authplane.js.map +1 -0
  75. package/dist/server/auth/providers/authplane.test.d.ts +1 -0
  76. package/dist/server/auth/providers/authplane.test.js +143 -0
  77. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  78. package/dist/server/auth/providers/clerk.d.ts +51 -0
  79. package/dist/server/auth/providers/clerk.js +19 -0
  80. package/dist/server/auth/providers/clerk.js.map +1 -0
  81. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  82. package/dist/server/auth/providers/clerk.test.js +30 -0
  83. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  84. package/dist/server/auth/providers/custom.d.ts +42 -0
  85. package/dist/server/auth/providers/custom.js +59 -0
  86. package/dist/server/auth/providers/custom.js.map +1 -0
  87. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  88. package/dist/server/auth/providers/custom.test.js +161 -0
  89. package/dist/server/auth/providers/custom.test.js.map +1 -0
  90. package/dist/server/auth/providers/descope.d.ts +44 -0
  91. package/dist/server/auth/providers/descope.js +44 -0
  92. package/dist/server/auth/providers/descope.js.map +1 -0
  93. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  94. package/dist/server/auth/providers/descope.test.js +62 -0
  95. package/dist/server/auth/providers/descope.test.js.map +1 -0
  96. package/dist/server/auth/providers/shared.d.ts +2 -0
  97. package/dist/server/auth/providers/shared.js +6 -0
  98. package/dist/server/auth/providers/shared.js.map +1 -0
  99. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  100. package/dist/server/auth/providers/shared.test.js +10 -0
  101. package/dist/server/auth/providers/shared.test.js.map +1 -0
  102. package/dist/server/auth/providers/stytch.d.ts +25 -0
  103. package/dist/server/auth/providers/stytch.js +16 -0
  104. package/dist/server/auth/providers/stytch.js.map +1 -0
  105. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  106. package/dist/server/auth/providers/verify-spy.js +21 -0
  107. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  108. package/dist/server/auth/providers/workos.d.ts +34 -0
  109. package/dist/server/auth/providers/workos.js +16 -0
  110. package/dist/server/auth/providers/workos.js.map +1 -0
  111. package/dist/server/auth/security-schemes.d.ts +23 -0
  112. package/dist/server/auth/security-schemes.js +64 -0
  113. package/dist/server/auth/security-schemes.js.map +1 -0
  114. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  115. package/dist/server/auth/security-schemes.test.js +99 -0
  116. package/dist/server/auth/security-schemes.test.js.map +1 -0
  117. package/dist/server/auth/setup.d.ts +6 -0
  118. package/dist/server/auth/setup.js +91 -0
  119. package/dist/server/auth/setup.js.map +1 -0
  120. package/dist/server/auth/setup.test.d.ts +1 -0
  121. package/dist/server/auth/setup.test.js +514 -0
  122. package/dist/server/auth/setup.test.js.map +1 -0
  123. package/dist/server/auth/verify.d.ts +48 -0
  124. package/dist/server/auth/verify.js +62 -0
  125. package/dist/server/auth/verify.js.map +1 -0
  126. package/dist/server/auth/verify.test.d.ts +1 -0
  127. package/dist/server/auth/verify.test.js +165 -0
  128. package/dist/server/auth/verify.test.js.map +1 -0
  129. package/dist/server/auth-extra.test-d.js +130 -0
  130. package/dist/server/auth-extra.test-d.js.map +1 -0
  131. package/dist/server/auth.d.ts +57 -0
  132. package/dist/server/auth.js +27 -0
  133. package/dist/server/auth.js.map +1 -0
  134. package/dist/server/build-manifest.test.d.ts +1 -0
  135. package/dist/server/build-manifest.test.js +28 -0
  136. package/dist/server/build-manifest.test.js.map +1 -0
  137. package/dist/server/content-helpers.d.ts +41 -1
  138. package/dist/server/content-helpers.js +33 -0
  139. package/dist/server/content-helpers.js.map +1 -1
  140. package/dist/server/events.d.ts +113 -0
  141. package/dist/server/events.js +318 -0
  142. package/dist/server/events.js.map +1 -0
  143. package/dist/server/events.test.d.ts +1 -0
  144. package/dist/server/events.test.js +172 -0
  145. package/dist/server/events.test.js.map +1 -0
  146. package/dist/server/express.d.ts +23 -3
  147. package/dist/server/express.js +43 -32
  148. package/dist/server/express.js.map +1 -1
  149. package/dist/server/express.test.js +269 -90
  150. package/dist/server/express.test.js.map +1 -1
  151. package/dist/server/file-ref.d.ts +21 -1
  152. package/dist/server/file-ref.js +20 -1
  153. package/dist/server/file-ref.js.map +1 -1
  154. package/dist/server/form-input.d.ts +120 -0
  155. package/dist/server/form-input.js +89 -0
  156. package/dist/server/form-input.js.map +1 -0
  157. package/dist/server/host.d.ts +2 -0
  158. package/dist/server/host.js +11 -0
  159. package/dist/server/host.js.map +1 -0
  160. package/dist/server/host.test.d.ts +1 -0
  161. package/dist/server/host.test.js +13 -0
  162. package/dist/server/host.test.js.map +1 -0
  163. package/dist/server/index.d.ts +19 -2
  164. package/dist/server/index.js +16 -1
  165. package/dist/server/index.js.map +1 -1
  166. package/dist/server/mcp-errors.test.d.ts +1 -0
  167. package/dist/server/mcp-errors.test.js +41 -0
  168. package/dist/server/mcp-errors.test.js.map +1 -0
  169. package/dist/server/middleware.d.ts +51 -13
  170. package/dist/server/middleware.js +33 -0
  171. package/dist/server/middleware.js.map +1 -1
  172. package/dist/server/middleware.test-d.js +1 -1
  173. package/dist/server/middleware.test-d.js.map +1 -1
  174. package/dist/server/middleware.test.js +242 -134
  175. package/dist/server/middleware.test.js.map +1 -1
  176. package/dist/server/register-tool.test.d.ts +1 -0
  177. package/dist/server/register-tool.test.js +230 -0
  178. package/dist/server/register-tool.test.js.map +1 -0
  179. package/dist/server/requestOrigin.d.ts +7 -0
  180. package/dist/server/requestOrigin.js +25 -0
  181. package/dist/server/requestOrigin.js.map +1 -0
  182. package/dist/server/server.d.ts +532 -67
  183. package/dist/server/server.js +646 -315
  184. package/dist/server/server.js.map +1 -1
  185. package/dist/server/skills-integration.test.d.ts +1 -0
  186. package/dist/server/skills-integration.test.js +86 -0
  187. package/dist/server/skills-integration.test.js.map +1 -0
  188. package/dist/server/skills.d.ts +27 -0
  189. package/dist/server/skills.js +188 -0
  190. package/dist/server/skills.js.map +1 -0
  191. package/dist/server/skills.test.d.ts +1 -0
  192. package/dist/server/skills.test.js +243 -0
  193. package/dist/server/skills.test.js.map +1 -0
  194. package/dist/server/templateHelper.d.ts +0 -3
  195. package/dist/server/templateHelper.js.map +1 -1
  196. package/dist/server/templates.generated.js +4 -8
  197. package/dist/server/templates.generated.js.map +1 -1
  198. package/dist/server/tool-extra.test.d.ts +1 -0
  199. package/dist/server/tool-extra.test.js +167 -0
  200. package/dist/server/tool-extra.test.js.map +1 -0
  201. package/dist/server/view-name.test-d.d.ts +1 -0
  202. package/dist/server/view-name.test-d.js +8 -0
  203. package/dist/server/view-name.test-d.js.map +1 -0
  204. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  205. package/dist/server/view-resource-resolution.test.js +176 -0
  206. package/dist/server/view-resource-resolution.test.js.map +1 -0
  207. package/dist/server/viewsDevServer.js +4 -1
  208. package/dist/server/viewsDevServer.js.map +1 -1
  209. package/dist/test/utils.d.ts +9 -11
  210. package/dist/test/utils.js +220 -201
  211. package/dist/test/utils.js.map +1 -1
  212. package/dist/test/view.test.js +123 -106
  213. package/dist/test/view.test.js.map +1 -1
  214. package/dist/views/index.d.ts +10 -0
  215. package/dist/views/index.js +3 -0
  216. package/dist/views/index.js.map +1 -0
  217. package/dist/{web/plugin → views}/scan-views.js +1 -1
  218. package/dist/views/scan-views.js.map +1 -0
  219. package/dist/views/scan-views.test.d.ts +1 -0
  220. package/dist/views/scan-views.test.js.map +1 -0
  221. package/dist/views/validate-view.d.ts +1 -0
  222. package/dist/{web/plugin → views}/validate-view.js +2 -2
  223. package/dist/views/validate-view.js.map +1 -0
  224. package/dist/views/validate-view.test.d.ts +1 -0
  225. package/dist/views/validate-view.test.js.map +1 -0
  226. package/dist/web/bridges/adaptor.d.ts +62 -0
  227. package/dist/web/bridges/adaptor.js +471 -0
  228. package/dist/web/bridges/adaptor.js.map +1 -0
  229. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  230. package/dist/web/bridges/adaptor.test.js +264 -0
  231. package/dist/web/bridges/adaptor.test.js.map +1 -0
  232. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -1
  233. package/dist/web/bridges/apps-sdk/bridge.js +15 -3
  234. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  235. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  236. package/dist/web/bridges/apps-sdk/index.js +0 -1
  237. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  238. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
  239. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
  240. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  241. package/dist/web/bridges/get-adaptor.d.ts +7 -0
  242. package/dist/web/bridges/get-adaptor.js +9 -7
  243. package/dist/web/bridges/get-adaptor.js.map +1 -1
  244. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  245. package/dist/web/bridges/get-adaptor.test.js +32 -0
  246. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  247. package/dist/web/bridges/mcp-app/bridge.d.ts +15 -2
  248. package/dist/web/bridges/mcp-app/bridge.js +80 -7
  249. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  250. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  251. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  252. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  253. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  254. package/dist/web/bridges/mcp-app/index.js +0 -1
  255. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  256. package/dist/web/bridges/mcp-app/types.d.ts +19 -2
  257. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  258. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +13 -1
  259. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +12 -0
  260. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  261. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
  262. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  263. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  264. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  265. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  266. package/dist/web/bridges/types.d.ts +160 -5
  267. package/dist/web/bridges/types.js +14 -1
  268. package/dist/web/bridges/types.js.map +1 -1
  269. package/dist/web/bridges/types.test.d.ts +1 -0
  270. package/dist/web/bridges/types.test.js +19 -0
  271. package/dist/web/bridges/types.test.js.map +1 -0
  272. package/dist/web/bridges/use-host-context.d.ts +5 -0
  273. package/dist/web/bridges/use-host-context.js +5 -0
  274. package/dist/web/bridges/use-host-context.js.map +1 -1
  275. package/dist/web/components/modal-provider.d.ts +1 -1
  276. package/dist/web/components/modal-provider.js +4 -3
  277. package/dist/web/components/modal-provider.js.map +1 -1
  278. package/dist/web/create-store.d.ts +26 -0
  279. package/dist/web/create-store.js +26 -0
  280. package/dist/web/create-store.js.map +1 -1
  281. package/dist/web/create-store.test.js +10 -7
  282. package/dist/web/create-store.test.js.map +1 -1
  283. package/dist/web/data-llm.d.ts +34 -1
  284. package/dist/web/data-llm.js +31 -2
  285. package/dist/web/data-llm.js.map +1 -1
  286. package/dist/web/data-llm.test.js +26 -7
  287. package/dist/web/data-llm.test.js.map +1 -1
  288. package/dist/web/generate-helpers.d.ts +25 -19
  289. package/dist/web/generate-helpers.js +23 -17
  290. package/dist/web/generate-helpers.js.map +1 -1
  291. package/dist/web/generate-helpers.test-d.js +7 -5
  292. package/dist/web/generate-helpers.test-d.js.map +1 -1
  293. package/dist/web/generate-helpers.test.js +2 -2
  294. package/dist/web/generate-helpers.test.js.map +1 -1
  295. package/dist/web/hooks/index.d.ts +8 -1
  296. package/dist/web/hooks/index.js +8 -1
  297. package/dist/web/hooks/index.js.map +1 -1
  298. package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
  299. package/dist/web/hooks/openai-extensions.test.js +107 -0
  300. package/dist/web/hooks/openai-extensions.test.js.map +1 -0
  301. package/dist/web/hooks/test/utils.d.ts +7 -2
  302. package/dist/web/hooks/test/utils.js +14 -3
  303. package/dist/web/hooks/test/utils.js.map +1 -1
  304. package/dist/web/hooks/use-call-tool.d.ts +47 -2
  305. package/dist/web/hooks/use-call-tool.js +43 -10
  306. package/dist/web/hooks/use-call-tool.js.map +1 -1
  307. package/dist/web/hooks/use-call-tool.test.js +75 -25
  308. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  309. package/dist/web/hooks/use-deep-link.d.ts +22 -0
  310. package/dist/web/hooks/use-deep-link.js +34 -0
  311. package/dist/web/hooks/use-deep-link.js.map +1 -0
  312. package/dist/web/hooks/use-display-mode.d.ts +20 -0
  313. package/dist/web/hooks/use-display-mode.js +20 -0
  314. package/dist/web/hooks/use-display-mode.js.map +1 -1
  315. package/dist/web/hooks/use-display-mode.test.js +57 -21
  316. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  317. package/dist/web/hooks/use-download.d.ts +3 -0
  318. package/dist/web/hooks/use-download.js +7 -0
  319. package/dist/web/hooks/use-download.js.map +1 -0
  320. package/dist/web/hooks/use-download.test.d.ts +1 -0
  321. package/dist/web/hooks/use-download.test.js +103 -0
  322. package/dist/web/hooks/use-download.test.js.map +1 -0
  323. package/dist/web/hooks/use-file-resource.d.ts +37 -0
  324. package/dist/web/hooks/use-file-resource.js +98 -0
  325. package/dist/web/hooks/use-file-resource.js.map +1 -0
  326. package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
  327. package/dist/web/hooks/use-file-resource.test.js +65 -0
  328. package/dist/web/hooks/use-file-resource.test.js.map +1 -0
  329. package/dist/web/hooks/use-files.d.ts +32 -0
  330. package/dist/web/hooks/use-files.js +32 -0
  331. package/dist/web/hooks/use-files.js.map +1 -1
  332. package/dist/web/hooks/use-files.test.js +11 -3
  333. package/dist/web/hooks/use-files.test.js.map +1 -1
  334. package/dist/web/hooks/use-host.d.ts +44 -0
  335. package/dist/web/hooks/use-host.js +45 -0
  336. package/dist/web/hooks/use-host.js.map +1 -0
  337. package/dist/web/hooks/use-host.test.d.ts +1 -0
  338. package/dist/web/hooks/use-host.test.js +59 -0
  339. package/dist/web/hooks/use-host.test.js.map +1 -0
  340. package/dist/web/hooks/use-model-context.d.ts +44 -0
  341. package/dist/web/hooks/use-model-context.js +63 -0
  342. package/dist/web/hooks/use-model-context.js.map +1 -0
  343. package/dist/web/hooks/use-open-external.d.ts +17 -0
  344. package/dist/web/hooks/use-open-external.js +16 -0
  345. package/dist/web/hooks/use-open-external.js.map +1 -1
  346. package/dist/web/hooks/use-open-external.test.js +15 -5
  347. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  348. package/dist/web/hooks/use-open-file.d.ts +20 -0
  349. package/dist/web/hooks/use-open-file.js +25 -0
  350. package/dist/web/hooks/use-open-file.js.map +1 -0
  351. package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
  352. package/dist/web/hooks/use-register-view-tool.js +50 -0
  353. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  354. package/dist/web/hooks/use-request-close.d.ts +14 -0
  355. package/dist/web/hooks/use-request-close.js +13 -0
  356. package/dist/web/hooks/use-request-close.js.map +1 -1
  357. package/dist/web/hooks/use-request-close.test.js +35 -40
  358. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  359. package/dist/web/hooks/use-request-modal.d.ts +16 -1
  360. package/dist/web/hooks/use-request-modal.js +16 -1
  361. package/dist/web/hooks/use-request-modal.js.map +1 -1
  362. package/dist/web/hooks/use-request-modal.test.js +11 -1
  363. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  364. package/dist/web/hooks/use-request-size.d.ts +17 -0
  365. package/dist/web/hooks/use-request-size.js +16 -0
  366. package/dist/web/hooks/use-request-size.js.map +1 -1
  367. package/dist/web/hooks/use-request-size.test.js +35 -53
  368. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  369. package/dist/web/hooks/use-send-follow-up-message.d.ts +25 -2
  370. package/dist/web/hooks/use-send-follow-up-message.js +23 -0
  371. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  372. package/dist/web/hooks/use-set-open-in-app-url.d.ts +17 -0
  373. package/dist/web/hooks/use-set-open-in-app-url.js +17 -0
  374. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
  375. package/dist/web/hooks/use-set-open-in-app-url.test.js +26 -12
  376. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  377. package/dist/web/hooks/use-tool-info.d.ts +46 -14
  378. package/dist/web/hooks/use-tool-info.js +29 -7
  379. package/dist/web/hooks/use-tool-info.js.map +1 -1
  380. package/dist/web/hooks/use-tool-info.test-d.js +11 -34
  381. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  382. package/dist/web/hooks/use-tool-info.test.js +42 -37
  383. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  384. package/dist/web/hooks/use-user.d.ts +5 -2
  385. package/dist/web/hooks/use-user.js +6 -3
  386. package/dist/web/hooks/use-user.js.map +1 -1
  387. package/dist/web/hooks/use-user.test.js +85 -37
  388. package/dist/web/hooks/use-user.test.js.map +1 -1
  389. package/dist/web/hooks/use-view-state.d.ts +21 -0
  390. package/dist/web/hooks/use-view-state.js +19 -9
  391. package/dist/web/hooks/use-view-state.js.map +1 -1
  392. package/dist/web/hooks/use-view-state.test.js +39 -4
  393. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  394. package/dist/web/hooks/use-viewport.d.ts +20 -0
  395. package/dist/web/hooks/use-viewport.js +21 -0
  396. package/dist/web/hooks/use-viewport.js.map +1 -0
  397. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  398. package/dist/web/hooks/use-viewport.test.js +109 -0
  399. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  400. package/dist/web/mount-view.d.ts +20 -0
  401. package/dist/web/mount-view.js +22 -6
  402. package/dist/web/mount-view.js.map +1 -1
  403. package/dist/web/types.d.ts +4 -0
  404. package/dist/web/types.js.map +1 -1
  405. package/package.json +35 -23
  406. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -26
  407. package/dist/web/bridges/apps-sdk/adaptor.js +0 -102
  408. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  409. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -50
  410. package/dist/web/bridges/mcp-app/adaptor.js +0 -271
  411. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
  412. package/dist/web/hooks/use-layout.d.ts +0 -22
  413. package/dist/web/hooks/use-layout.js +0 -23
  414. package/dist/web/hooks/use-layout.js.map +0 -1
  415. package/dist/web/hooks/use-layout.test.js +0 -96
  416. package/dist/web/hooks/use-layout.test.js.map +0 -1
  417. package/dist/web/plugin/data-llm.test.js +0 -81
  418. package/dist/web/plugin/data-llm.test.js.map +0 -1
  419. package/dist/web/plugin/plugin.d.ts +0 -5
  420. package/dist/web/plugin/plugin.js +0 -163
  421. package/dist/web/plugin/plugin.js.map +0 -1
  422. package/dist/web/plugin/scan-views.js.map +0 -1
  423. package/dist/web/plugin/scan-views.test.js.map +0 -1
  424. package/dist/web/plugin/transform-data-llm.d.ts +0 -12
  425. package/dist/web/plugin/transform-data-llm.js +0 -96
  426. package/dist/web/plugin/transform-data-llm.js.map +0 -1
  427. package/dist/web/plugin/transform-data-llm.test.js +0 -81
  428. package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
  429. package/dist/web/plugin/validate-view.d.ts +0 -1
  430. package/dist/web/plugin/validate-view.js.map +0 -1
  431. package/dist/web/plugin/validate-view.test.js.map +0 -1
  432. /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  433. /package/dist/{web/plugin/data-llm.test.d.ts → cli/build-steps.test.d.ts} +0 -0
  434. /package/dist/{web/plugin/scan-views.test.d.ts → context-warnings.test.d.ts} +0 -0
  435. /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/app.test.d.ts} +0 -0
  436. /package/dist/{web/plugin/validate-view.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
  437. /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
  438. /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
  439. /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,IAAI,gBAA0C,CAAC;QAE/C,UAAU,CAAC,GAAG,EAAE;YACd,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACxD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACtB,YAAY,EAAE,gBAAgB;aAC/B,CAAC,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC9E,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAEvD,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YAEvB,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,IAAI,eAAgE,CAAC;QAErE,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YACpD,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;YACpD,eAAe,GAAG,4BAA4B,EAAE,CAAC;YACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,KAAK,IAAI,EAAE;YACnB,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACtB,EAAE,CAAC,aAAa,EAAE,CAAC;YACnB,YAAY,CAAC,aAAa,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;YAC5F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAEvD,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YAEvB,MAAM,OAAO,CAAC,GAAG,EAAE;gBACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;oBACtB,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,mCAAmC;iBAC5C,CAAC,EACF,GAAG,CACJ,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,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 { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestClose } from \"./use-request-close.js\";\n\ndescribe(\"useRequestClose\", () => {\n describe(\"apps-sdk host\", () => {\n let requestCloseMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n requestCloseMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n requestClose: requestCloseMock,\n });\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return a function that calls window.openai.requestClose\", async () => {\n const { result } = renderHook(() => useRequestClose());\n\n await result.current();\n\n expect(requestCloseMock).toHaveBeenCalledTimes(1);\n expect(requestCloseMock).toHaveBeenCalledWith();\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n McpAppBridge.resetInstance();\n });\n\n it(\"should send a ui/notifications/request-teardown notification to the MCP host\", async () => {\n const { result } = renderHook(() => useRequestClose());\n\n await result.current();\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/request-teardown\",\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { getAdaptor } from \"../bridges/get-adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestClose } from \"./use-request-close.js\";\n\ndescribe(\"useRequestClose\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"calls app.requestTeardown via the MCP path\", async () => {\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n\n it(\"calls app.requestTeardown even when window.openai is present\", async () => {\n vi.stubGlobal(\"openai\", { requestClose: vi.fn() });\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n});\n"]}
@@ -1,6 +1,21 @@
1
1
  import { type RequestModalOptions } from "../bridges/index.js";
2
2
  /**
3
- * Triggers a modal containing the view rendered in display mode "modal"
3
+ * Open the current view in a modal overlay (`displayMode === "modal"`).
4
+ *
5
+ * Returns `{ isOpen, params, open }`: `open(opts)` triggers the host to render
6
+ * the view in a modal, optionally passing `params` that are surfaced back via
7
+ * `params` here. Useful for confirmation flows, detail panels, or any modal
8
+ * lifecycle owned by the host.
9
+ *
10
+ * Use {@link useDisplayMode} for non-modal display modes.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const { isOpen, open } = useRequestModal();
15
+ * <button onClick={() => open({ params: { id: 42 } })}>Show details</button>
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-request-modal
4
19
  */
5
20
  export declare function useRequestModal(): {
6
21
  isOpen: boolean;
@@ -1,7 +1,22 @@
1
1
  import { useCallback } from "react";
2
2
  import { getAdaptor, useHostContext, } from "../bridges/index.js";
3
3
  /**
4
- * Triggers a modal containing the view rendered in display mode "modal"
4
+ * Open the current view in a modal overlay (`displayMode === "modal"`).
5
+ *
6
+ * Returns `{ isOpen, params, open }`: `open(opts)` triggers the host to render
7
+ * the view in a modal, optionally passing `params` that are surfaced back via
8
+ * `params` here. Useful for confirmation flows, detail panels, or any modal
9
+ * lifecycle owned by the host.
10
+ *
11
+ * Use {@link useDisplayMode} for non-modal display modes.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const { isOpen, open } = useRequestModal();
16
+ * <button onClick={() => open({ params: { id: 42 } })}>Show details</button>
17
+ * ```
18
+ *
19
+ * @see https://docs.skybridge.tech/api-reference/use-request-modal
5
20
  */
6
21
  export function useRequestModal() {
7
22
  const adaptor = getAdaptor();
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-modal.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,UAAU,EAEV,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,IAAyB,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,EACtD,CAAC,OAAO,CAAC,CACV,CAAC;IACF,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,OAAO;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI;KACL,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n getAdaptor,\n type RequestModalOptions,\n useHostContext,\n} from \"../bridges/index.js\";\n\n/**\n * Triggers a modal containing the view rendered in display mode \"modal\"\n */\nexport function useRequestModal() {\n const adaptor = getAdaptor();\n const display = useHostContext(\"display\");\n const open = useCallback(\n (opts: RequestModalOptions) => adaptor.openModal(opts),\n [adaptor],\n );\n return {\n isOpen: display.mode === \"modal\",\n params: display.params,\n open,\n };\n}\n"]}
1
+ {"version":3,"file":"use-request-modal.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,UAAU,EAEV,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,IAAyB,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,EACtD,CAAC,OAAO,CAAC,CACV,CAAC;IACF,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,OAAO;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI;KACL,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n getAdaptor,\n type RequestModalOptions,\n useHostContext,\n} from \"../bridges/index.js\";\n\n/**\n * Open the current view in a modal overlay (`displayMode === \"modal\"`).\n *\n * Returns `{ isOpen, params, open }`: `open(opts)` triggers the host to render\n * the view in a modal, optionally passing `params` that are surfaced back via\n * `params` here. Useful for confirmation flows, detail panels, or any modal\n * lifecycle owned by the host.\n *\n * Use {@link useDisplayMode} for non-modal display modes.\n *\n * @example\n * ```tsx\n * const { isOpen, open } = useRequestModal();\n * <button onClick={() => open({ params: { id: 42 } })}>Show details</button>\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-modal\n */\nexport function useRequestModal() {\n const adaptor = getAdaptor();\n const display = useHostContext(\"display\");\n const open = useCallback(\n (opts: RequestModalOptions) => adaptor.openModal(opts),\n [adaptor],\n );\n return {\n isOpen: display.mode === \"modal\",\n params: display.params,\n open,\n };\n}\n"]}
@@ -1,11 +1,18 @@
1
1
  import { renderHook } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
4
+ import { AppsSdkBridge } from "../bridges/apps-sdk/bridge.js";
5
+ import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
3
6
  import { useRequestModal } from "./use-request-modal.js";
4
7
  describe("useRequestModal", () => {
5
8
  let requestModalMock;
6
9
  beforeEach(() => {
10
+ HostAdaptor.resetInstance();
11
+ McpAppBridge.resetInstance();
12
+ AppsSdkBridge.resetInstance();
7
13
  requestModalMock = vi.fn();
8
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
14
+ vi.stubGlobal("skybridge", {});
15
+ vi.stubGlobal("parent", { postMessage: vi.fn() });
9
16
  vi.stubGlobal("openai", {
10
17
  requestModal: requestModalMock,
11
18
  view: { mode: "inline" },
@@ -14,6 +21,9 @@ describe("useRequestModal", () => {
14
21
  afterEach(() => {
15
22
  vi.unstubAllGlobals();
16
23
  vi.resetAllMocks();
24
+ HostAdaptor.resetInstance();
25
+ McpAppBridge.resetInstance();
26
+ AppsSdkBridge.resetInstance();
17
27
  });
18
28
  it("should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal", () => {
19
29
  const { result } = renderHook(() => useRequestModal());
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { useRequestModal } from \"./use-request-modal.js\";\n\ndescribe(\"useRequestModal\", () => {\n let requestModalMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n requestModalMock = vi.fn();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"inline\" },\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal\", () => {\n const { result } = renderHook(() => useRequestModal());\n\n expect(typeof result.current).toBe(\"object\");\n expect(result.current).toHaveProperty(\"open\");\n expect(result.current).toHaveProperty(\"isOpen\");\n expect(result.current).toHaveProperty(\"params\");\n\n const { open, isOpen, params } = result.current;\n expect(typeof open).toBe(\"function\");\n expect(isOpen).toBe(false);\n expect(params).toBeUndefined();\n });\n\n it(\"should return isOpen as true when mode is modal\", () => {\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\" },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { isOpen } = result.current;\n\n expect(isOpen).toBe(true);\n });\n\n it(\"should return params from view when available\", () => {\n const testParams = { foo: \"bar\", baz: 42 };\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\", params: testParams },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { params } = result.current;\n\n expect(params).toEqual(testParams);\n });\n\n it(\"should call window.openai.requestModal with the options when open is called\", () => {\n const { result } = renderHook(() => useRequestModal());\n const { open } = result.current;\n\n const options = {\n title: \"Test Modal\",\n params: { foo: \"bar\" },\n template: \"ui://view/modal-template.html\",\n };\n open(options);\n\n expect(requestModalMock).toHaveBeenCalledTimes(1);\n expect(requestModalMock).toHaveBeenCalledWith(options);\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestModal } from \"./use-request-modal.js\";\n\ndescribe(\"useRequestModal\", () => {\n let requestModalMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n requestModalMock = vi.fn();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"inline\" },\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal\", () => {\n const { result } = renderHook(() => useRequestModal());\n\n expect(typeof result.current).toBe(\"object\");\n expect(result.current).toHaveProperty(\"open\");\n expect(result.current).toHaveProperty(\"isOpen\");\n expect(result.current).toHaveProperty(\"params\");\n\n const { open, isOpen, params } = result.current;\n expect(typeof open).toBe(\"function\");\n expect(isOpen).toBe(false);\n expect(params).toBeUndefined();\n });\n\n it(\"should return isOpen as true when mode is modal\", () => {\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\" },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { isOpen } = result.current;\n\n expect(isOpen).toBe(true);\n });\n\n it(\"should return params from view when available\", () => {\n const testParams = { foo: \"bar\", baz: 42 };\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\", params: testParams },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { params } = result.current;\n\n expect(params).toEqual(testParams);\n });\n\n it(\"should call window.openai.requestModal with the options when open is called\", () => {\n const { result } = renderHook(() => useRequestModal());\n const { open } = result.current;\n\n const options = {\n title: \"Test Modal\",\n params: { foo: \"bar\" },\n template: \"ui://view/modal-template.html\",\n };\n open(options);\n\n expect(requestModalMock).toHaveBeenCalledTimes(1);\n expect(requestModalMock).toHaveBeenCalledWith(options);\n });\n});\n"]}
@@ -1,3 +1,20 @@
1
1
  import type { RequestSizeOptions } from "../bridges/types.js";
2
+ /** Function that asks the host to resize the view, returned by {@link useRequestSize}. */
2
3
  export type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;
4
+ /**
5
+ * Ask the host to resize the view iframe. The applied size is host-driven —
6
+ * the host decides whether and how to honor the request, and {@link useViewport}
7
+ * still reports the final `maxHeight` it allows.
8
+ *
9
+ * Pair with a `ResizeObserver` on your root element to react to content size
10
+ * changes without hard-coded values.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const requestSize = useRequestSize();
15
+ * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-request-size
19
+ */
3
20
  export declare function useRequestSize(): RequestSizeFn;
@@ -1,5 +1,21 @@
1
1
  import { useCallback } from "react";
2
2
  import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Ask the host to resize the view iframe. The applied size is host-driven —
5
+ * the host decides whether and how to honor the request, and {@link useViewport}
6
+ * still reports the final `maxHeight` it allows.
7
+ *
8
+ * Pair with a `ResizeObserver` on your root element to react to content size
9
+ * changes without hard-coded values.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const requestSize = useRequestSize();
14
+ * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);
15
+ * ```
16
+ *
17
+ * @see https://docs.skybridge.tech/api-reference/use-request-size
18
+ */
3
19
  export function useRequestSize() {
4
20
  const adaptor = getAdaptor();
5
21
  const requestSize = useCallback((size) => adaptor.requestSize(size), [adaptor]);
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAKjD,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\nexport function useRequestSize(): RequestSizeFn {\n const adaptor = getAdaptor();\n const requestSize = useCallback(\n (size: RequestSizeOptions) => adaptor.requestSize(size),\n [adaptor],\n );\n\n return requestSize;\n}\n"]}
1
+ {"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\n/** Function that asks the host to resize the view, returned by {@link useRequestSize}. */\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\n/**\n * Ask the host to resize the view iframe. The applied size is host-driven —\n * the host decides whether and how to honor the request, and {@link useViewport}\n * still reports the final `maxHeight` it allows.\n *\n * Pair with a `ResizeObserver` on your root element to react to content size\n * changes without hard-coded values.\n *\n * @example\n * ```tsx\n * const requestSize = useRequestSize();\n * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-size\n */\nexport function useRequestSize(): RequestSizeFn {\n const adaptor = getAdaptor();\n const requestSize = useCallback(\n (size: RequestSizeOptions) => adaptor.requestSize(size),\n [adaptor],\n );\n\n return requestSize;\n}\n"]}
@@ -1,64 +1,46 @@
1
1
  import { renderHook, waitFor } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
- import { AppsSdkAdaptor } from "../bridges/apps-sdk/adaptor.js";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
4
4
  import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
5
5
  import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
6
6
  import { useRequestSize } from "./use-request-size.js";
7
7
  describe("useRequestSize", () => {
8
- describe("apps-sdk host", () => {
9
- let consoleWarnSpy;
10
- beforeEach(() => {
11
- AppsSdkAdaptor.resetInstance();
12
- vi.stubGlobal("openai", {});
13
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
14
- consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
15
- });
16
- afterEach(() => {
17
- AppsSdkAdaptor.resetInstance();
18
- vi.unstubAllGlobals();
19
- vi.resetAllMocks();
20
- });
21
- it("warns that requestSize is not supported on Apps SDK", async () => {
22
- const { result } = renderHook(() => useRequestSize());
23
- await result.current({ height: 400 });
24
- expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
25
- expect(consoleWarnSpy.mock.calls[0]?.[0]).toContain("not supported");
26
- });
8
+ let postMessageMock;
9
+ beforeEach(() => {
10
+ HostAdaptor.resetInstance();
11
+ McpAppBridge.resetInstance();
12
+ vi.stubGlobal("skybridge", {});
13
+ vi.stubGlobal("openai", undefined);
14
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
15
+ postMessageMock = getMcpAppHostPostMessageMock();
16
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
27
17
  });
28
- describe("mcp-app host", () => {
29
- let postMessageMock;
30
- beforeEach(() => {
31
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
32
- vi.stubGlobal("ResizeObserver", MockResizeObserver);
33
- postMessageMock = getMcpAppHostPostMessageMock();
34
- vi.stubGlobal("parent", { postMessage: postMessageMock });
35
- });
36
- afterEach(async () => {
37
- vi.unstubAllGlobals();
38
- vi.resetAllMocks();
39
- McpAppBridge.resetInstance();
40
- });
41
- it("sends a ui/notifications/size-changed notification with width and height", async () => {
42
- const { result } = renderHook(() => useRequestSize());
43
- await result.current({ width: 800, height: 400 });
44
- await waitFor(() => {
45
- expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
46
- jsonrpc: "2.0",
47
- method: "ui/notifications/size-changed",
48
- params: { width: 800, height: 400 },
49
- }), "*");
50
- });
18
+ afterEach(() => {
19
+ vi.unstubAllGlobals();
20
+ vi.resetAllMocks();
21
+ HostAdaptor.resetInstance();
22
+ McpAppBridge.resetInstance();
23
+ });
24
+ it("sends a ui/notifications/size-changed notification with width and height", async () => {
25
+ const { result } = renderHook(() => useRequestSize());
26
+ await result.current({ width: 800, height: 400 });
27
+ await waitFor(() => {
28
+ expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
29
+ jsonrpc: "2.0",
30
+ method: "ui/notifications/size-changed",
31
+ params: { width: 800, height: 400 },
32
+ }), "*");
51
33
  });
52
- it("forwards height-only payloads as-is", async () => {
53
- const { result } = renderHook(() => useRequestSize());
54
- await result.current({ height: 400 });
55
- await waitFor(() => {
56
- expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
57
- jsonrpc: "2.0",
58
- method: "ui/notifications/size-changed",
59
- params: { height: 400 },
60
- }), "*");
61
- });
34
+ });
35
+ it("forwards height-only payloads as-is", async () => {
36
+ const { result } = renderHook(() => useRequestSize());
37
+ await result.current({ height: 400 });
38
+ await waitFor(() => {
39
+ expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
40
+ jsonrpc: "2.0",
41
+ method: "ui/notifications/size-changed",
42
+ params: { height: 400 },
43
+ }), "*");
62
44
  });
63
45
  });
64
46
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { AppsSdkAdaptor } from \"../bridges/apps-sdk/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestSize } from \"./use-request-size.js\";\n\ndescribe(\"useRequestSize\", () => {\n describe(\"apps-sdk host\", () => {\n let consoleWarnSpy: ReturnType<typeof vi.spyOn>;\n\n beforeEach(() => {\n AppsSdkAdaptor.resetInstance();\n vi.stubGlobal(\"openai\", {});\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n consoleWarnSpy = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n });\n\n afterEach(() => {\n AppsSdkAdaptor.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"warns that requestSize is not supported on Apps SDK\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n expect(consoleWarnSpy).toHaveBeenCalledTimes(1);\n expect(consoleWarnSpy.mock.calls[0]?.[0]).toContain(\"not supported\");\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends a ui/notifications/size-changed notification with width and height\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ width: 800, height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { width: 800, height: 400 },\n }),\n \"*\",\n );\n });\n });\n\n it(\"forwards height-only payloads as-is\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { height: 400 },\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,eAAgE,CAAC;IAErE,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,eAAe,GAAG,4BAA4B,EAAE,CAAC;QACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+BAA+B;gBACvC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;aACpC,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAEtC,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+BAA+B;gBACvC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;aACxB,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestSize } from \"./use-request-size.js\";\n\ndescribe(\"useRequestSize\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends a ui/notifications/size-changed notification with width and height\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ width: 800, height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { width: 800, height: 400 },\n }),\n \"*\",\n );\n });\n });\n\n it(\"forwards height-only payloads as-is\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { height: 400 },\n }),\n \"*\",\n );\n });\n });\n});\n"]}
@@ -1,2 +1,25 @@
1
- import { type SendFollowUpMessageOptions } from "../bridges/index.js";
2
- export declare function useSendFollowUpMessage(): (prompt: string, options?: SendFollowUpMessageOptions) => Promise<void>;
1
+ import { type FollowUpMessage, type SendFollowUpMessageOptions } from "../bridges/index.js";
2
+ /**
3
+ * Send a follow-up message to the LLM on behalf of the view, as if the user
4
+ * had sent it. Use to chain interactions from view UI (e.g. a button that
5
+ * triggers the next assistant turn).
6
+ *
7
+ * Pass `scrollToBottom: false` to keep the chat scroll position when the host
8
+ * posts the message. This option is Apps-SDK-only; it is silently ignored in
9
+ * the MCP Apps runtime.
10
+ *
11
+ * `prompt` can also be an array of content blocks. On ChatGPT, a text block
12
+ * with `_meta["openai/title"]` becomes a labeled item the user can remove, and
13
+ * `target: "new"` sends the message to a new conversation. Both use the OpenAI
14
+ * MCP extensions: other hosts ignore the title, and `target: "new"` rejects
15
+ * with `NotSupportedError` on hosts that don't advertise `openai/message`.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const send = useSendFollowUpMessage();
20
+ * <button onClick={() => send("Summarize the last 5 results")}>Summarize</button>
21
+ * ```
22
+ *
23
+ * @see https://docs.skybridge.tech/api-reference/use-send-follow-up-message
24
+ */
25
+ export declare function useSendFollowUpMessage(): (prompt: FollowUpMessage, options?: SendFollowUpMessageOptions) => Promise<void>;
@@ -1,5 +1,28 @@
1
1
  import { useCallback } from "react";
2
2
  import { getAdaptor, } from "../bridges/index.js";
3
+ /**
4
+ * Send a follow-up message to the LLM on behalf of the view, as if the user
5
+ * had sent it. Use to chain interactions from view UI (e.g. a button that
6
+ * triggers the next assistant turn).
7
+ *
8
+ * Pass `scrollToBottom: false` to keep the chat scroll position when the host
9
+ * posts the message. This option is Apps-SDK-only; it is silently ignored in
10
+ * the MCP Apps runtime.
11
+ *
12
+ * `prompt` can also be an array of content blocks. On ChatGPT, a text block
13
+ * with `_meta["openai/title"]` becomes a labeled item the user can remove, and
14
+ * `target: "new"` sends the message to a new conversation. Both use the OpenAI
15
+ * MCP extensions: other hosts ignore the title, and `target: "new"` rejects
16
+ * with `NotSupportedError` on hosts that don't advertise `openai/message`.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * const send = useSendFollowUpMessage();
21
+ * <button onClick={() => send("Summarize the last 5 results")}>Summarize</button>
22
+ * ```
23
+ *
24
+ * @see https://docs.skybridge.tech/api-reference/use-send-follow-up-message
25
+ */
3
26
  export function useSendFollowUpMessage() {
4
27
  const adaptor = getAdaptor();
5
28
  const sendFollowUpMessage = useCallback((prompt, options) => adaptor.sendFollowUpMessage(prompt, options), [adaptor]);
@@ -1 +1 @@
1
- {"version":3,"file":"use-send-follow-up-message.js","sourceRoot":"","sources":["../../../src/web/hooks/use-send-follow-up-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,UAAU,GAEX,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,sBAAsB;IACpC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,MAAc,EAAE,OAAoC,EAAE,EAAE,CACvD,OAAO,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9C,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,mBAAmB,CAAC;AAC7B,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n getAdaptor,\n type SendFollowUpMessageOptions,\n} from \"../bridges/index.js\";\n\nexport function useSendFollowUpMessage() {\n const adaptor = getAdaptor();\n const sendFollowUpMessage = useCallback(\n (prompt: string, options?: SendFollowUpMessageOptions) =>\n adaptor.sendFollowUpMessage(prompt, options),\n [adaptor],\n );\n\n return sendFollowUpMessage;\n}\n"]}
1
+ {"version":3,"file":"use-send-follow-up-message.js","sourceRoot":"","sources":["../../../src/web/hooks/use-send-follow-up-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAEL,UAAU,GAEX,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,MAAuB,EAAE,OAAoC,EAAE,EAAE,CAChE,OAAO,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9C,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,mBAAmB,CAAC;AAC7B,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n type FollowUpMessage,\n getAdaptor,\n type SendFollowUpMessageOptions,\n} from \"../bridges/index.js\";\n\n/**\n * Send a follow-up message to the LLM on behalf of the view, as if the user\n * had sent it. Use to chain interactions from view UI (e.g. a button that\n * triggers the next assistant turn).\n *\n * Pass `scrollToBottom: false` to keep the chat scroll position when the host\n * posts the message. This option is Apps-SDK-only; it is silently ignored in\n * the MCP Apps runtime.\n *\n * `prompt` can also be an array of content blocks. On ChatGPT, a text block\n * with `_meta[\"openai/title\"]` becomes a labeled item the user can remove, and\n * `target: \"new\"` sends the message to a new conversation. Both use the OpenAI\n * MCP extensions: other hosts ignore the title, and `target: \"new\"` rejects\n * with `NotSupportedError` on hosts that don't advertise `openai/message`.\n *\n * @example\n * ```tsx\n * const send = useSendFollowUpMessage();\n * <button onClick={() => send(\"Summarize the last 5 results\")}>Summarize</button>\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-send-follow-up-message\n */\nexport function useSendFollowUpMessage() {\n const adaptor = getAdaptor();\n const sendFollowUpMessage = useCallback(\n (prompt: FollowUpMessage, options?: SendFollowUpMessageOptions) =>\n adaptor.sendFollowUpMessage(prompt, options),\n [adaptor],\n );\n\n return sendFollowUpMessage;\n}\n"]}
@@ -1 +1,18 @@
1
+ /**
2
+ * Override the target URL the host opens from its fullscreen "Open in <App>"
3
+ * affordance. If unset, the host opens the view's current iframe path.
4
+ *
5
+ * Currently Apps-SDK-only — calling this from MCP Apps throws.
6
+ *
7
+ * Call this once your view has enough context to construct the canonical URL
8
+ * (e.g. a permalink to the entity the user is currently viewing).
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const setOpenInAppUrl = useSetOpenInAppUrl();
13
+ * useEffect(() => { setOpenInAppUrl(`https://example.com/orders/${orderId}`); }, [orderId]);
14
+ * ```
15
+ *
16
+ * @see https://docs.skybridge.tech/api-reference/use-set-open-in-app-url
17
+ */
1
18
  export declare function useSetOpenInAppUrl(): (href: string) => Promise<void>;
@@ -1,5 +1,22 @@
1
1
  import { useCallback } from "react";
2
2
  import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Override the target URL the host opens from its fullscreen "Open in <App>"
5
+ * affordance. If unset, the host opens the view's current iframe path.
6
+ *
7
+ * Currently Apps-SDK-only — calling this from MCP Apps throws.
8
+ *
9
+ * Call this once your view has enough context to construct the canonical URL
10
+ * (e.g. a permalink to the entity the user is currently viewing).
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const setOpenInAppUrl = useSetOpenInAppUrl();
15
+ * useEffect(() => { setOpenInAppUrl(`https://example.com/orders/${orderId}`); }, [orderId]);
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-set-open-in-app-url
19
+ */
3
20
  export function useSetOpenInAppUrl() {
4
21
  const adaptor = getAdaptor();
5
22
  const setOpenInAppUrl = useCallback((href) => adaptor.setOpenInAppUrl(href), [adaptor]);
@@ -1 +1 @@
1
- {"version":3,"file":"use-set-open-in-app-url.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,EAC/C,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\nexport function useSetOpenInAppUrl() {\n const adaptor = getAdaptor();\n const setOpenInAppUrl = useCallback(\n (href: string) => adaptor.setOpenInAppUrl(href),\n [adaptor],\n );\n\n return setOpenInAppUrl;\n}\n"]}
1
+ {"version":3,"file":"use-set-open-in-app-url.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,EAC/C,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\n/**\n * Override the target URL the host opens from its fullscreen \"Open in <App>\"\n * affordance. If unset, the host opens the view's current iframe path.\n *\n * Currently Apps-SDK-only — calling this from MCP Apps throws.\n *\n * Call this once your view has enough context to construct the canonical URL\n * (e.g. a permalink to the entity the user is currently viewing).\n *\n * @example\n * ```tsx\n * const setOpenInAppUrl = useSetOpenInAppUrl();\n * useEffect(() => { setOpenInAppUrl(`https://example.com/orders/${orderId}`); }, [orderId]);\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-set-open-in-app-url\n */\nexport function useSetOpenInAppUrl() {\n const adaptor = getAdaptor();\n const setOpenInAppUrl = useCallback(\n (href: string) => adaptor.setOpenInAppUrl(href),\n [adaptor],\n );\n\n return setOpenInAppUrl;\n}\n"]}
@@ -1,8 +1,18 @@
1
1
  import { renderHook } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
- import { AppsSdkAdaptor } from "../bridges/apps-sdk/adaptor.js";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
4
+ import { AppsSdkBridge } from "../bridges/apps-sdk/bridge.js";
5
+ import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
6
+ import { NotSupportedError } from "../bridges/types.js";
4
7
  import { useSetOpenInAppUrl } from "./use-set-open-in-app-url.js";
5
8
  describe("useSetOpenInAppUrl", () => {
9
+ afterEach(() => {
10
+ vi.unstubAllGlobals();
11
+ vi.resetAllMocks();
12
+ HostAdaptor.resetInstance();
13
+ AppsSdkBridge.resetInstance();
14
+ McpAppBridge.resetInstance();
15
+ });
6
16
  describe("apps-sdk host", () => {
7
17
  let setOpenInAppUrlMock;
8
18
  beforeEach(() => {
@@ -10,15 +20,8 @@ describe("useSetOpenInAppUrl", () => {
10
20
  vi.stubGlobal("openai", {
11
21
  setOpenInAppUrl: setOpenInAppUrlMock,
12
22
  });
13
- vi.stubGlobal("skybridge", {
14
- hostType: "apps-sdk",
15
- serverUrl: "https://example.com",
16
- });
17
- });
18
- afterEach(() => {
19
- vi.unstubAllGlobals();
20
- vi.resetAllMocks();
21
- AppsSdkAdaptor.resetInstance();
23
+ vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
24
+ vi.stubGlobal("parent", { postMessage: vi.fn() });
22
25
  });
23
26
  it("should return a function that calls window.openai.setOpenInAppUrl with the href", async () => {
24
27
  const { result } = renderHook(() => useSetOpenInAppUrl());
@@ -27,9 +30,9 @@ describe("useSetOpenInAppUrl", () => {
27
30
  expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);
28
31
  expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });
29
32
  });
30
- it("should throw an error when href is empty", () => {
33
+ it("should reject when href is empty", async () => {
31
34
  const { result } = renderHook(() => useSetOpenInAppUrl());
32
- expect(() => result.current("")).toThrow("The href parameter is required.");
35
+ await expect(result.current("")).rejects.toThrow("The href parameter is required.");
33
36
  });
34
37
  it("should call setOpenInAppUrl when href origin differs from serverUrl origin", async () => {
35
38
  const { result } = renderHook(() => useSetOpenInAppUrl());
@@ -39,5 +42,16 @@ describe("useSetOpenInAppUrl", () => {
39
42
  expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });
40
43
  });
41
44
  });
45
+ describe("mcp-app host", () => {
46
+ beforeEach(() => {
47
+ vi.stubGlobal("openai", undefined);
48
+ vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
49
+ vi.stubGlobal("parent", { postMessage: vi.fn() });
50
+ });
51
+ it("should throw NotSupportedError when called from an MCP App runtime", async () => {
52
+ const { result } = renderHook(() => useSetOpenInAppUrl());
53
+ await expect(result.current("https://example.com/path")).rejects.toBeInstanceOf(NotSupportedError);
54
+ });
55
+ });
42
56
  });
43
57
  //# sourceMappingURL=use-set-open-in-app-url.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,IAAI,mBAA6C,CAAC;QAElD,UAAU,CAAC,GAAG,EAAE;YACd,mBAAmB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YAC3D,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACtB,eAAe,EAAE,mBAAmB;aACrC,CAAC,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE;gBACzB,QAAQ,EAAE,UAAU;gBACpB,SAAS,EAAE,qBAAqB;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACtB,EAAE,CAAC,aAAa,EAAE,CAAC;YACnB,cAAc,CAAC,aAAa,EAAE,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;YAC/F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,IAAI,GAAG,0BAA0B,CAAC;YACxC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE3B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CACtC,iCAAiC,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;YAC1F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,IAAI,GAAG,mCAAmC,CAAC;YACjD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE3B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { AppsSdkAdaptor } from \"../bridges/apps-sdk/adaptor.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", {\n hostType: \"apps-sdk\",\n serverUrl: \"https://example.com\",\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n AppsSdkAdaptor.resetInstance();\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should throw an error when href is empty\", () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n expect(() => result.current(\"\")).toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { NotSupportedError } from \"../bridges/types.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n AppsSdkBridge.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should reject when href is empty\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(result.current(\"\")).rejects.toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n\n describe(\"mcp-app host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should throw NotSupportedError when called from an MCP App runtime\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(\n result.current(\"https://example.com/path\"),\n ).rejects.toBeInstanceOf(NotSupportedError);\n });\n });\n});\n"]}