skybridge 0.0.0-dev.ff50fdb → 0.0.0-dev.ffaef7a

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 (437) hide show
  1. package/README.md +124 -114
  2. package/dist/cli/build-helpers.d.ts +10 -0
  3. package/dist/cli/build-helpers.js +93 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.js +89 -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 +68 -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-views-dir.d.ts +1 -0
  19. package/dist/cli/resolve-views-dir.js +17 -0
  20. package/dist/cli/resolve-views-dir.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.js.map +1 -1
  26. package/dist/cli/tunnel-control-server.d.ts +9 -0
  27. package/dist/cli/tunnel-control-server.js +31 -0
  28. package/dist/cli/tunnel-control-server.js.map +1 -0
  29. package/dist/cli/tunnel-control-server.test.d.ts +1 -0
  30. package/dist/cli/tunnel-control-server.test.js +39 -0
  31. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  32. package/dist/cli/tunnel-handler.d.ts +3 -0
  33. package/dist/cli/tunnel-handler.js +48 -0
  34. package/dist/cli/tunnel-handler.js.map +1 -0
  35. package/dist/cli/tunnel-handler.test.d.ts +1 -0
  36. package/dist/cli/tunnel-handler.test.js +105 -0
  37. package/dist/cli/tunnel-handler.test.js.map +1 -0
  38. package/dist/cli/tunnel.d.ts +57 -0
  39. package/dist/cli/tunnel.js +154 -0
  40. package/dist/cli/tunnel.js.map +1 -0
  41. package/dist/cli/tunnel.test.d.ts +1 -0
  42. package/dist/cli/tunnel.test.js +190 -0
  43. package/dist/cli/tunnel.test.js.map +1 -0
  44. package/dist/cli/types.d.ts +5 -0
  45. package/dist/cli/types.js +2 -0
  46. package/dist/cli/types.js.map +1 -0
  47. package/dist/cli/use-execute-steps.d.ts +3 -2
  48. package/dist/cli/use-execute-steps.js +6 -1
  49. package/dist/cli/use-execute-steps.js.map +1 -1
  50. package/dist/cli/use-messages.d.ts +3 -0
  51. package/dist/cli/use-messages.js +11 -0
  52. package/dist/cli/use-messages.js.map +1 -0
  53. package/dist/cli/use-nodemon.d.ts +16 -0
  54. package/dist/cli/use-nodemon.js +84 -0
  55. package/dist/cli/use-nodemon.js.map +1 -0
  56. package/dist/cli/use-open-browser.d.ts +1 -0
  57. package/dist/cli/use-open-browser.js +44 -0
  58. package/dist/cli/use-open-browser.js.map +1 -0
  59. package/dist/cli/use-tunnel.d.ts +14 -0
  60. package/dist/cli/use-tunnel.js +131 -0
  61. package/dist/cli/use-tunnel.js.map +1 -0
  62. package/dist/cli/use-typescript-check.d.ts +15 -0
  63. package/dist/cli/use-typescript-check.js +97 -0
  64. package/dist/cli/use-typescript-check.js.map +1 -0
  65. package/dist/commands/build.d.ts +0 -3
  66. package/dist/commands/build.js +3 -16
  67. package/dist/commands/build.js.map +1 -1
  68. package/dist/commands/create.d.ts +9 -0
  69. package/dist/commands/create.js +30 -0
  70. package/dist/commands/create.js.map +1 -0
  71. package/dist/commands/dev.d.ts +5 -1
  72. package/dist/commands/dev.js +109 -13
  73. package/dist/commands/dev.js.map +1 -1
  74. package/dist/commands/start.d.ts +3 -1
  75. package/dist/commands/start.js +37 -15
  76. package/dist/commands/start.js.map +1 -1
  77. package/dist/commands/telemetry/disable.js.map +1 -1
  78. package/dist/commands/telemetry/enable.js.map +1 -1
  79. package/dist/commands/telemetry/status.js.map +1 -1
  80. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  81. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  82. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  83. package/dist/server/asset-base-url-transform-plugin.test.d.ts +1 -0
  84. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  85. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  86. package/dist/server/auth/discovery.d.ts +32 -0
  87. package/dist/server/auth/discovery.js +56 -0
  88. package/dist/server/auth/discovery.js.map +1 -0
  89. package/dist/server/auth/discovery.test.d.ts +1 -0
  90. package/dist/server/auth/discovery.test.js +93 -0
  91. package/dist/server/auth/discovery.test.js.map +1 -0
  92. package/dist/server/auth/index.d.ts +18 -0
  93. package/dist/server/auth/index.js +2 -0
  94. package/dist/server/auth/index.js.map +1 -0
  95. package/dist/server/auth/providers/auth0.d.ts +18 -0
  96. package/dist/server/auth/providers/auth0.js +31 -0
  97. package/dist/server/auth/providers/auth0.js.map +1 -0
  98. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  99. package/dist/server/auth/providers/auth0.test.js +48 -0
  100. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  101. package/dist/server/auth/providers/clerk.d.ts +14 -0
  102. package/dist/server/auth/providers/clerk.js +16 -0
  103. package/dist/server/auth/providers/clerk.js.map +1 -0
  104. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  105. package/dist/server/auth/providers/clerk.test.js +28 -0
  106. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  107. package/dist/server/auth/providers/custom.d.ts +24 -0
  108. package/dist/server/auth/providers/custom.js +37 -0
  109. package/dist/server/auth/providers/custom.js.map +1 -0
  110. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  111. package/dist/server/auth/providers/custom.test.js +107 -0
  112. package/dist/server/auth/providers/custom.test.js.map +1 -0
  113. package/dist/server/auth/providers/descope.d.ts +15 -0
  114. package/dist/server/auth/providers/descope.js +33 -0
  115. package/dist/server/auth/providers/descope.js.map +1 -0
  116. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  117. package/dist/server/auth/providers/descope.test.js +37 -0
  118. package/dist/server/auth/providers/descope.test.js.map +1 -0
  119. package/dist/server/auth/providers/shared.d.ts +2 -0
  120. package/dist/server/auth/providers/shared.js +6 -0
  121. package/dist/server/auth/providers/shared.js.map +1 -0
  122. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  123. package/dist/server/auth/providers/shared.test.js +10 -0
  124. package/dist/server/auth/providers/shared.test.js.map +1 -0
  125. package/dist/server/auth/providers/stytch.d.ts +12 -0
  126. package/dist/server/auth/providers/stytch.js +13 -0
  127. package/dist/server/auth/providers/stytch.js.map +1 -0
  128. package/dist/server/auth/providers/workos.d.ts +11 -0
  129. package/dist/server/auth/providers/workos.js +12 -0
  130. package/dist/server/auth/providers/workos.js.map +1 -0
  131. package/dist/server/auth/security-schemes.d.ts +13 -0
  132. package/dist/server/auth/security-schemes.js +53 -0
  133. package/dist/server/auth/security-schemes.js.map +1 -0
  134. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  135. package/dist/server/auth/security-schemes.test.js +90 -0
  136. package/dist/server/auth/security-schemes.test.js.map +1 -0
  137. package/dist/server/auth/setup.d.ts +6 -0
  138. package/dist/server/auth/setup.js +98 -0
  139. package/dist/server/auth/setup.js.map +1 -0
  140. package/dist/server/auth/setup.test.d.ts +1 -0
  141. package/dist/server/auth/setup.test.js +450 -0
  142. package/dist/server/auth/setup.test.js.map +1 -0
  143. package/dist/server/auth/verify.d.ts +12 -0
  144. package/dist/server/auth/verify.js +38 -0
  145. package/dist/server/auth/verify.js.map +1 -0
  146. package/dist/server/auth/verify.test.d.ts +1 -0
  147. package/dist/server/auth/verify.test.js +100 -0
  148. package/dist/server/auth/verify.test.js.map +1 -0
  149. package/dist/server/auth.d.ts +20 -0
  150. package/dist/server/auth.js +28 -0
  151. package/dist/server/auth.js.map +1 -0
  152. package/dist/server/build-manifest.test.d.ts +1 -0
  153. package/dist/server/build-manifest.test.js +27 -0
  154. package/dist/server/build-manifest.test.js.map +1 -0
  155. package/dist/server/content-helpers.d.ts +67 -0
  156. package/dist/server/content-helpers.js +79 -0
  157. package/dist/server/content-helpers.js.map +1 -0
  158. package/dist/server/content-helpers.test.d.ts +1 -0
  159. package/dist/server/content-helpers.test.js +70 -0
  160. package/dist/server/content-helpers.test.js.map +1 -0
  161. package/dist/server/express.d.ts +11 -0
  162. package/dist/server/express.js +101 -0
  163. package/dist/server/express.js.map +1 -0
  164. package/dist/server/express.test.d.ts +1 -0
  165. package/dist/server/express.test.js +491 -0
  166. package/dist/server/express.test.js.map +1 -0
  167. package/dist/server/file-ref.d.ts +28 -0
  168. package/dist/server/file-ref.js +27 -0
  169. package/dist/server/file-ref.js.map +1 -0
  170. package/dist/server/index.d.ts +14 -3
  171. package/dist/server/index.js +11 -2
  172. package/dist/server/index.js.map +1 -1
  173. package/dist/server/inferUtilityTypes.d.ts +6 -6
  174. package/dist/server/inferUtilityTypes.js.map +1 -1
  175. package/dist/server/metric.d.ts +14 -0
  176. package/dist/server/metric.js +62 -0
  177. package/dist/server/metric.js.map +1 -0
  178. package/dist/server/middleware.d.ts +137 -0
  179. package/dist/server/middleware.js +93 -0
  180. package/dist/server/middleware.js.map +1 -0
  181. package/dist/server/middleware.test-d.d.ts +1 -0
  182. package/dist/server/middleware.test-d.js +75 -0
  183. package/dist/server/middleware.test-d.js.map +1 -0
  184. package/dist/server/middleware.test.d.ts +1 -0
  185. package/dist/server/middleware.test.js +493 -0
  186. package/dist/server/middleware.test.js.map +1 -0
  187. package/dist/server/requestOrigin.d.ts +7 -0
  188. package/dist/server/requestOrigin.js +25 -0
  189. package/dist/server/requestOrigin.js.map +1 -0
  190. package/dist/server/server.d.ts +391 -58
  191. package/dist/server/server.js +644 -97
  192. package/dist/server/server.js.map +1 -1
  193. package/dist/server/templateHelper.d.ts +5 -7
  194. package/dist/server/templateHelper.js +3 -22
  195. package/dist/server/templateHelper.js.map +1 -1
  196. package/dist/server/templates.generated.d.ts +4 -0
  197. package/dist/server/templates.generated.js +47 -0
  198. package/dist/server/templates.generated.js.map +1 -0
  199. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  200. package/dist/server/tunnel-proxy-router.js +110 -0
  201. package/dist/server/tunnel-proxy-router.js.map +1 -0
  202. package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
  203. package/dist/server/tunnel-proxy-router.test.js +229 -0
  204. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  205. package/dist/server/view-name.test-d.d.ts +1 -0
  206. package/dist/server/view-name.test-d.js +8 -0
  207. package/dist/server/view-name.test-d.js.map +1 -0
  208. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  209. package/dist/server/view-resource-resolution.test.js +171 -0
  210. package/dist/server/view-resource-resolution.test.js.map +1 -0
  211. package/dist/server/viewsDevServer.d.ts +14 -0
  212. package/dist/server/viewsDevServer.js +45 -0
  213. package/dist/server/viewsDevServer.js.map +1 -0
  214. package/dist/test/utils.d.ts +13 -21
  215. package/dist/test/utils.js +42 -37
  216. package/dist/test/utils.js.map +1 -1
  217. package/dist/test/view.test.d.ts +1 -0
  218. package/dist/test/view.test.js +536 -0
  219. package/dist/test/view.test.js.map +1 -0
  220. package/dist/version.d.ts +1 -0
  221. package/dist/version.js +3 -0
  222. package/dist/version.js.map +1 -0
  223. package/dist/web/bridges/adaptor.d.ts +51 -0
  224. package/dist/web/bridges/adaptor.js +330 -0
  225. package/dist/web/bridges/adaptor.js.map +1 -0
  226. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  227. package/dist/web/bridges/adaptor.test.js +208 -0
  228. package/dist/web/bridges/adaptor.test.js.map +1 -0
  229. package/dist/web/bridges/apps-sdk/bridge.d.ts +7 -2
  230. package/dist/web/bridges/apps-sdk/bridge.js +15 -3
  231. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  232. package/dist/web/bridges/apps-sdk/index.d.ts +1 -2
  233. package/dist/web/bridges/apps-sdk/index.js +0 -1
  234. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  235. package/dist/web/bridges/apps-sdk/types.d.ts +32 -14
  236. package/dist/web/bridges/apps-sdk/types.js.map +1 -1
  237. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
  238. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
  239. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  240. package/dist/web/bridges/get-adaptor.d.ts +7 -0
  241. package/dist/web/bridges/get-adaptor.js +9 -7
  242. package/dist/web/bridges/get-adaptor.js.map +1 -1
  243. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  244. package/dist/web/bridges/get-adaptor.test.js +32 -0
  245. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  246. package/dist/web/bridges/index.js.map +1 -1
  247. package/dist/web/bridges/mcp-app/bridge.d.ts +27 -31
  248. package/dist/web/bridges/mcp-app/bridge.js +109 -198
  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.js.map +1 -1
  257. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +17 -3
  258. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +14 -2
  259. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  260. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -41
  261. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  262. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  263. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  264. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  265. package/dist/web/bridges/types.d.ts +130 -14
  266. package/dist/web/bridges/types.js +14 -1
  267. package/dist/web/bridges/types.js.map +1 -1
  268. package/dist/web/bridges/types.test.d.ts +1 -0
  269. package/dist/web/bridges/types.test.js +19 -0
  270. package/dist/web/bridges/types.test.js.map +1 -0
  271. package/dist/web/bridges/use-host-context.d.ts +5 -0
  272. package/dist/web/bridges/use-host-context.js +5 -0
  273. package/dist/web/bridges/use-host-context.js.map +1 -1
  274. package/dist/web/components/modal-provider.d.ts +1 -1
  275. package/dist/web/components/modal-provider.js +5 -6
  276. package/dist/web/components/modal-provider.js.map +1 -1
  277. package/dist/web/create-store.d.ts +26 -0
  278. package/dist/web/create-store.js +43 -3
  279. package/dist/web/create-store.js.map +1 -1
  280. package/dist/web/create-store.test.js +31 -25
  281. package/dist/web/create-store.test.js.map +1 -1
  282. package/dist/web/data-llm.d.ts +35 -2
  283. package/dist/web/data-llm.js +31 -3
  284. package/dist/web/data-llm.js.map +1 -1
  285. package/dist/web/data-llm.test.js +50 -35
  286. package/dist/web/data-llm.test.js.map +1 -1
  287. package/dist/web/generate-helpers.d.ts +22 -18
  288. package/dist/web/generate-helpers.js +22 -18
  289. package/dist/web/generate-helpers.js.map +1 -1
  290. package/dist/web/generate-helpers.test-d.js +30 -28
  291. package/dist/web/generate-helpers.test-d.js.map +1 -1
  292. package/dist/web/generate-helpers.test.js.map +1 -1
  293. package/dist/web/helpers/state.d.ts +2 -2
  294. package/dist/web/helpers/state.js +11 -11
  295. package/dist/web/helpers/state.js.map +1 -1
  296. package/dist/web/helpers/state.test.js +9 -9
  297. package/dist/web/helpers/state.test.js.map +1 -1
  298. package/dist/web/hooks/index.d.ts +6 -2
  299. package/dist/web/hooks/index.js +5 -1
  300. package/dist/web/hooks/index.js.map +1 -1
  301. package/dist/web/hooks/test/utils.d.ts +6 -2
  302. package/dist/web/hooks/test/utils.js +17 -2
  303. package/dist/web/hooks/test/utils.js.map +1 -1
  304. package/dist/web/hooks/use-call-tool.d.ts +45 -0
  305. package/dist/web/hooks/use-call-tool.js +28 -0
  306. package/dist/web/hooks/use-call-tool.js.map +1 -1
  307. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
  308. package/dist/web/hooks/use-call-tool.test.js +62 -27
  309. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  310. package/dist/web/hooks/use-display-mode.d.ts +23 -3
  311. package/dist/web/hooks/use-display-mode.js +20 -0
  312. package/dist/web/hooks/use-display-mode.js.map +1 -1
  313. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  314. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  315. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  316. package/dist/web/hooks/use-display-mode.test.js +56 -20
  317. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  318. package/dist/web/hooks/use-download.d.ts +5 -0
  319. package/dist/web/hooks/use-download.js +8 -0
  320. package/dist/web/hooks/use-download.js.map +1 -0
  321. package/dist/web/hooks/use-download.test.d.ts +1 -0
  322. package/dist/web/hooks/use-download.test.js +103 -0
  323. package/dist/web/hooks/use-download.test.js.map +1 -0
  324. package/dist/web/hooks/use-files.d.ts +34 -1
  325. package/dist/web/hooks/use-files.js +33 -0
  326. package/dist/web/hooks/use-files.js.map +1 -1
  327. package/dist/web/hooks/use-files.test.js +35 -3
  328. package/dist/web/hooks/use-files.test.js.map +1 -1
  329. package/dist/web/hooks/use-layout.d.ts +2 -0
  330. package/dist/web/hooks/use-layout.js +2 -0
  331. package/dist/web/hooks/use-layout.js.map +1 -1
  332. package/dist/web/hooks/use-layout.test.js +62 -29
  333. package/dist/web/hooks/use-layout.test.js.map +1 -1
  334. package/dist/web/hooks/use-open-external.d.ts +20 -1
  335. package/dist/web/hooks/use-open-external.js +17 -1
  336. package/dist/web/hooks/use-open-external.js.map +1 -1
  337. package/dist/web/hooks/use-open-external.test.js +38 -13
  338. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  339. package/dist/web/hooks/use-register-view-tool.d.ts +38 -0
  340. package/dist/web/hooks/use-register-view-tool.js +50 -0
  341. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  342. package/dist/web/hooks/use-request-close.d.ts +16 -0
  343. package/dist/web/hooks/use-request-close.js +21 -0
  344. package/dist/web/hooks/use-request-close.js.map +1 -0
  345. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  346. package/dist/web/hooks/use-request-close.test.js +47 -0
  347. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  348. package/dist/web/hooks/use-request-modal.d.ts +16 -1
  349. package/dist/web/hooks/use-request-modal.js +19 -4
  350. package/dist/web/hooks/use-request-modal.js.map +1 -1
  351. package/dist/web/hooks/use-request-modal.test.js +15 -1
  352. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  353. package/dist/web/hooks/use-request-size.d.ts +20 -0
  354. package/dist/web/hooks/use-request-size.js +24 -0
  355. package/dist/web/hooks/use-request-size.js.map +1 -0
  356. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  357. package/dist/web/hooks/use-request-size.test.js +47 -0
  358. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  359. package/dist/web/hooks/use-send-follow-up-message.d.ts +19 -1
  360. package/dist/web/hooks/use-send-follow-up-message.js +19 -2
  361. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  362. package/dist/web/hooks/use-set-open-in-app-url.d.ts +17 -0
  363. package/dist/web/hooks/use-set-open-in-app-url.js +17 -0
  364. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
  365. package/dist/web/hooks/use-set-open-in-app-url.test.js +30 -16
  366. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  367. package/dist/web/hooks/use-tool-info.d.ts +53 -2
  368. package/dist/web/hooks/use-tool-info.js +30 -7
  369. package/dist/web/hooks/use-tool-info.js.map +1 -1
  370. package/dist/web/hooks/use-tool-info.test-d.js +11 -29
  371. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  372. package/dist/web/hooks/use-tool-info.test.js +43 -33
  373. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  374. package/dist/web/hooks/use-user.d.ts +2 -0
  375. package/dist/web/hooks/use-user.js +20 -2
  376. package/dist/web/hooks/use-user.js.map +1 -1
  377. package/dist/web/hooks/use-user.test.js +101 -27
  378. package/dist/web/hooks/use-user.test.js.map +1 -1
  379. package/dist/web/hooks/use-view-state.d.ts +25 -0
  380. package/dist/web/hooks/use-view-state.js +32 -0
  381. package/dist/web/hooks/use-view-state.js.map +1 -0
  382. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  383. package/dist/web/hooks/use-view-state.test.js +181 -0
  384. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  385. package/dist/web/index.d.ts +1 -2
  386. package/dist/web/index.js +1 -2
  387. package/dist/web/index.js.map +1 -1
  388. package/dist/web/mount-view.d.ts +20 -0
  389. package/dist/web/{mount-widget.js → mount-view.js} +21 -2
  390. package/dist/web/mount-view.js.map +1 -0
  391. package/dist/web/plugin/data-llm.test.js.map +1 -1
  392. package/dist/web/plugin/plugin.d.ts +32 -1
  393. package/dist/web/plugin/plugin.js +167 -18
  394. package/dist/web/plugin/plugin.js.map +1 -1
  395. package/dist/web/plugin/scan-views.d.ts +16 -0
  396. package/dist/web/plugin/scan-views.js +88 -0
  397. package/dist/web/plugin/scan-views.js.map +1 -0
  398. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  399. package/dist/web/plugin/scan-views.test.js +99 -0
  400. package/dist/web/plugin/scan-views.test.js.map +1 -0
  401. package/dist/web/plugin/transform-data-llm.js +1 -1
  402. package/dist/web/plugin/transform-data-llm.js.map +1 -1
  403. package/dist/web/plugin/transform-data-llm.test.js.map +1 -1
  404. package/dist/web/plugin/validate-view.d.ts +1 -0
  405. package/dist/web/plugin/validate-view.js +9 -0
  406. package/dist/web/plugin/validate-view.js.map +1 -0
  407. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  408. package/dist/web/plugin/validate-view.test.js +24 -0
  409. package/dist/web/plugin/validate-view.test.js.map +1 -0
  410. package/dist/web/proxy.js +0 -1
  411. package/dist/web/proxy.js.map +1 -1
  412. package/dist/web/types.d.ts +4 -0
  413. package/dist/web/types.js.map +1 -1
  414. package/package.json +51 -29
  415. package/tsconfig.base.json +33 -0
  416. package/dist/server/templates/development.hbs +0 -66
  417. package/dist/server/templates/production.hbs +0 -7
  418. package/dist/server/widgetsDevServer.d.ts +0 -12
  419. package/dist/server/widgetsDevServer.js +0 -47
  420. package/dist/server/widgetsDevServer.js.map +0 -1
  421. package/dist/test/widget.test.js +0 -255
  422. package/dist/test/widget.test.js.map +0 -1
  423. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -22
  424. package/dist/web/bridges/apps-sdk/adaptor.js +0 -64
  425. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  426. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -36
  427. package/dist/web/bridges/mcp-app/adaptor.js +0 -185
  428. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
  429. package/dist/web/hooks/use-widget-state.d.ts +0 -4
  430. package/dist/web/hooks/use-widget-state.js +0 -32
  431. package/dist/web/hooks/use-widget-state.js.map +0 -1
  432. package/dist/web/hooks/use-widget-state.test.js +0 -61
  433. package/dist/web/hooks/use-widget-state.test.js.map +0 -1
  434. package/dist/web/mount-widget.d.ts +0 -1
  435. package/dist/web/mount-widget.js.map +0 -1
  436. /package/dist/{test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  437. /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/build-steps.test.d.ts} +0 -0
@@ -1,49 +1,74 @@
1
- import { renderHook } from "@testing-library/react";
1
+ import { renderHook, waitFor } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
3
4
  import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
5
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
4
6
  import { useOpenExternal } from "./use-open-external.js";
5
7
  describe("useOpenExternal", () => {
6
8
  describe("apps-sdk host", () => {
7
9
  let openExternalMock;
10
+ let postMessageMock;
8
11
  beforeEach(() => {
9
12
  openExternalMock = vi.fn();
10
13
  vi.stubGlobal("openai", {
11
14
  openExternal: openExternalMock,
12
15
  });
13
16
  vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
17
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
18
+ postMessageMock = getMcpAppHostPostMessageMock();
19
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
14
20
  });
15
21
  afterEach(() => {
22
+ HostAdaptor.resetInstance();
23
+ McpAppBridge.resetInstance();
16
24
  vi.unstubAllGlobals();
17
25
  vi.resetAllMocks();
18
26
  });
19
- it("should return a function that calls window.openai.openExternal with the href", () => {
27
+ it("should call window.openai.openExternal even without a redirectUrl option", () => {
20
28
  const { result } = renderHook(() => useOpenExternal());
21
29
  const href = "https://example.com";
22
30
  result.current(href);
23
31
  expect(openExternalMock).toHaveBeenCalledTimes(1);
24
32
  expect(openExternalMock).toHaveBeenCalledWith({ href });
33
+ expect(postMessageMock).not.toHaveBeenCalledWith(expect.objectContaining({ method: "ui/open-link" }), "*");
34
+ });
35
+ it("should call window.openai.openExternal when redirectUrl is false", () => {
36
+ const { result } = renderHook(() => useOpenExternal());
37
+ const href = "https://example.com";
38
+ result.current(href, { redirectUrl: false });
39
+ expect(openExternalMock).toHaveBeenCalledTimes(1);
40
+ expect(openExternalMock).toHaveBeenCalledWith({
41
+ href,
42
+ redirectUrl: false,
43
+ });
25
44
  });
26
45
  });
27
46
  describe("mcp-app host", () => {
28
- const mockPostMessage = vi.fn();
47
+ let postMessageMock;
29
48
  beforeEach(() => {
30
- vi.stubGlobal("parent", { postMessage: mockPostMessage });
49
+ vi.stubGlobal("openai", undefined);
31
50
  vi.stubGlobal("skybridge", { hostType: "mcp-app" });
51
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
52
+ postMessageMock = getMcpAppHostPostMessageMock();
53
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
32
54
  });
33
- afterEach(() => {
55
+ afterEach(async () => {
56
+ HostAdaptor.resetInstance();
57
+ McpAppBridge.resetInstance();
34
58
  vi.unstubAllGlobals();
35
59
  vi.resetAllMocks();
36
- McpAppBridge.resetInstance();
37
60
  });
38
- it("should return a function that sends ui/open-link request to the MCP host", () => {
61
+ it("should return a function that sends ui/open-link request to the MCP host", async () => {
39
62
  const { result } = renderHook(() => useOpenExternal());
40
63
  const href = "https://example.com";
41
- result.current(href);
42
- expect(mockPostMessage).toHaveBeenCalledWith(expect.objectContaining({
43
- jsonrpc: "2.0",
44
- method: "ui/open-link",
45
- params: { url: href },
46
- }), "*");
64
+ result.current(href, { redirectUrl: false });
65
+ await waitFor(() => {
66
+ expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
67
+ jsonrpc: "2.0",
68
+ method: "ui/open-link",
69
+ params: { url: href },
70
+ }), "*");
71
+ });
47
72
  });
48
73
  });
49
74
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.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,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,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;YAC3B,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,8EAA8E,EAAE,GAAG,EAAE;YACtF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAEvD,MAAM,IAAI,GAAG,qBAAqB,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAErB,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,MAAM,eAAe,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAEhC,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;YAC1D,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,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,0EAA0E,EAAE,GAAG,EAAE;YAClF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAEvD,MAAM,IAAI,GAAG,qBAAqB,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAErB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,cAAc;gBACtB,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;aACtB,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.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 { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useOpenExternal } from \"./use-open-external.js\";\n\ndescribe(\"useOpenExternal\", () => {\n describe(\"apps-sdk host\", () => {\n let openExternalMock: ReturnType<typeof vi.fn>;\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n openExternalMock = vi.fn();\n vi.stubGlobal(\"openai\", {\n openExternal: openExternalMock,\n });\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should call window.openai.openExternal even without a redirectUrl option\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href);\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({ href });\n expect(postMessageMock).not.toHaveBeenCalledWith(\n expect.objectContaining({ method: \"ui/open-link\" }),\n \"*\",\n );\n });\n\n it(\"should call window.openai.openExternal when redirectUrl is false\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({\n href,\n redirectUrl: false,\n });\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\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 HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return a function that sends ui/open-link request to the MCP host\", async () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/open-link\",\n params: { url: href },\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
@@ -0,0 +1,38 @@
1
+ import type { ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
2
+ import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
3
+ /**
4
+ * Register a tool the view exposes to the host and model — the MCP Apps
5
+ * "app-provided tools" feature. A view tool runs *inside the view*: the host
6
+ * discovers it via `tools/list` and invokes it via `tools/call`, and the
7
+ * handler executes against the view's live state. It is the inverse of
8
+ * {@link useCallTool} (which calls a server tool). Registered on mount, removed
9
+ * on unmount; re-registered when `config.name` changes.
10
+ *
11
+ * MCP Apps only — on the Apps SDK (`window.openai`) runtime it is a no-op.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import * as z from "zod";
16
+ * import { useRegisterViewTool } from "skybridge/web";
17
+ *
18
+ * useRegisterViewTool(
19
+ * {
20
+ * name: "chess_make_move",
21
+ * description: "Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.",
22
+ * inputSchema: { san: z.string() },
23
+ * annotations: { readOnlyHint: false },
24
+ * },
25
+ * ({ san }) => {
26
+ * const move = game.move(san);
27
+ * return {
28
+ * content: [{ type: "text", text: move ? `Played ${move.san}` : "Illegal move" }],
29
+ * structuredContent: { fen: game.fen() },
30
+ * isError: !move,
31
+ * };
32
+ * },
33
+ * );
34
+ * ```
35
+ *
36
+ * @see https://docs.skybridge.tech/api-reference/use-register-view-tool
37
+ */
38
+ export declare const useRegisterViewTool: <TInput extends ZodRawShapeCompat = ZodRawShapeCompat>(config: ViewToolConfig<TInput>, handler: ViewToolHandler<TInput>) => void;
@@ -0,0 +1,50 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Register a tool the view exposes to the host and model — the MCP Apps
5
+ * "app-provided tools" feature. A view tool runs *inside the view*: the host
6
+ * discovers it via `tools/list` and invokes it via `tools/call`, and the
7
+ * handler executes against the view's live state. It is the inverse of
8
+ * {@link useCallTool} (which calls a server tool). Registered on mount, removed
9
+ * on unmount; re-registered when `config.name` changes.
10
+ *
11
+ * MCP Apps only — on the Apps SDK (`window.openai`) runtime it is a no-op.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import * as z from "zod";
16
+ * import { useRegisterViewTool } from "skybridge/web";
17
+ *
18
+ * useRegisterViewTool(
19
+ * {
20
+ * name: "chess_make_move",
21
+ * description: "Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.",
22
+ * inputSchema: { san: z.string() },
23
+ * annotations: { readOnlyHint: false },
24
+ * },
25
+ * ({ san }) => {
26
+ * const move = game.move(san);
27
+ * return {
28
+ * content: [{ type: "text", text: move ? `Played ${move.san}` : "Illegal move" }],
29
+ * structuredContent: { fen: game.fen() },
30
+ * isError: !move,
31
+ * };
32
+ * },
33
+ * );
34
+ * ```
35
+ *
36
+ * @see https://docs.skybridge.tech/api-reference/use-register-view-tool
37
+ */
38
+ export const useRegisterViewTool = (config, handler) => {
39
+ const { name } = config;
40
+ const configRef = useRef(config);
41
+ configRef.current = config;
42
+ const handlerRef = useRef(handler);
43
+ handlerRef.current = handler;
44
+ useEffect(() => {
45
+ const adaptor = getAdaptor();
46
+ const wrappedHandler = (args) => handlerRef.current(args);
47
+ return adaptor.registerViewTool({ ...configRef.current, name }, wrappedHandler);
48
+ }, [name]);
49
+ };
50
+ //# sourceMappingURL=use-register-view-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-register-view-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-register-view-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAGjC,MAA8B,EAC9B,OAAgC,EAChC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAuB,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,OAAO,CAAC,IAA8C,CAAC,CAAC;QAErE,OAAO,OAAO,CAAC,gBAAgB,CAC7B,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAC9B,cAAc,CACf,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC,CAAC","sourcesContent":["import type { ZodRawShapeCompat } from \"@modelcontextprotocol/sdk/server/zod-compat.js\";\nimport { useEffect, useRef } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type {\n AnyViewToolHandler,\n ViewToolConfig,\n ViewToolHandler,\n} from \"../bridges/types.js\";\n\n/**\n * Register a tool the view exposes to the host and model — the MCP Apps\n * \"app-provided tools\" feature. A view tool runs *inside the view*: the host\n * discovers it via `tools/list` and invokes it via `tools/call`, and the\n * handler executes against the view's live state. It is the inverse of\n * {@link useCallTool} (which calls a server tool). Registered on mount, removed\n * on unmount; re-registered when `config.name` changes.\n *\n * MCP Apps only — on the Apps SDK (`window.openai`) runtime it is a no-op.\n *\n * @example\n * ```tsx\n * import * as z from \"zod\";\n * import { useRegisterViewTool } from \"skybridge/web\";\n *\n * useRegisterViewTool(\n * {\n * name: \"chess_make_move\",\n * description: \"Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.\",\n * inputSchema: { san: z.string() },\n * annotations: { readOnlyHint: false },\n * },\n * ({ san }) => {\n * const move = game.move(san);\n * return {\n * content: [{ type: \"text\", text: move ? `Played ${move.san}` : \"Illegal move\" }],\n * structuredContent: { fen: game.fen() },\n * isError: !move,\n * };\n * },\n * );\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-register-view-tool\n */\nexport const useRegisterViewTool = <\n TInput extends ZodRawShapeCompat = ZodRawShapeCompat,\n>(\n config: ViewToolConfig<TInput>,\n handler: ViewToolHandler<TInput>,\n) => {\n const { name } = config;\n const configRef = useRef(config);\n configRef.current = config;\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n const adaptor = getAdaptor();\n const wrappedHandler: AnyViewToolHandler = (args) =>\n handlerRef.current(args as Parameters<ViewToolHandler<TInput>>[0]);\n\n return adaptor.registerViewTool(\n { ...configRef.current, name },\n wrappedHandler,\n );\n }, [name]);\n};\n"]}
@@ -0,0 +1,16 @@
1
+ /** Function that asks the host to close the current view, returned by {@link useRequestClose}. */
2
+ export type RequestCloseFn = () => Promise<void>;
3
+ /**
4
+ * Ask the host to close (dismiss) the current view. The host decides whether
5
+ * to honor the request. Useful from modal views or after a terminal action
6
+ * like "Done".
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const close = useRequestClose();
11
+ * <button onClick={() => close()}>Done</button>
12
+ * ```
13
+ *
14
+ * @see https://docs.skybridge.tech/api-reference/use-request-close
15
+ */
16
+ export declare function useRequestClose(): RequestCloseFn;
@@ -0,0 +1,21 @@
1
+ import { useCallback } from "react";
2
+ import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Ask the host to close (dismiss) the current view. The host decides whether
5
+ * to honor the request. Useful from modal views or after a terminal action
6
+ * like "Done".
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const close = useRequestClose();
11
+ * <button onClick={() => close()}>Done</button>
12
+ * ```
13
+ *
14
+ * @see https://docs.skybridge.tech/api-reference/use-request-close
15
+ */
16
+ export function useRequestClose() {
17
+ const adaptor = getAdaptor();
18
+ const requestClose = useCallback(() => adaptor.requestClose(), [adaptor]);
19
+ return requestClose;
20
+ }
21
+ //# sourceMappingURL=use-request-close.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-request-close.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAKjD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE1E,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\n/** Function that asks the host to close the current view, returned by {@link useRequestClose}. */\nexport type RequestCloseFn = () => Promise<void>;\n\n/**\n * Ask the host to close (dismiss) the current view. The host decides whether\n * to honor the request. Useful from modal views or after a terminal action\n * like \"Done\".\n *\n * @example\n * ```tsx\n * const close = useRequestClose();\n * <button onClick={() => close()}>Done</button>\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-close\n */\nexport function useRequestClose(): RequestCloseFn {\n const adaptor = getAdaptor();\n const requestClose = useCallback(() => adaptor.requestClose(), [adaptor]);\n\n return requestClose;\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { act, renderHook } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
4
+ import { getAdaptor } from "../bridges/get-adaptor.js";
5
+ import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
6
+ import { useRequestClose } from "./use-request-close.js";
7
+ describe("useRequestClose", () => {
8
+ beforeEach(() => {
9
+ HostAdaptor.resetInstance();
10
+ McpAppBridge.resetInstance();
11
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
12
+ vi.stubGlobal("openai", undefined);
13
+ vi.stubGlobal("parent", { postMessage: vi.fn() });
14
+ });
15
+ afterEach(() => {
16
+ vi.unstubAllGlobals();
17
+ vi.resetAllMocks();
18
+ HostAdaptor.resetInstance();
19
+ McpAppBridge.resetInstance();
20
+ });
21
+ it("calls app.requestTeardown via the MCP path", async () => {
22
+ const requestTeardown = vi.fn().mockResolvedValue(undefined);
23
+ // biome-ignore lint/suspicious/noExplicitAny: test seam
24
+ const adaptor = getAdaptor();
25
+ adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });
26
+ const { result } = renderHook(() => useRequestClose());
27
+ await act(async () => {
28
+ await result.current();
29
+ });
30
+ expect(requestTeardown).toHaveBeenCalledTimes(1);
31
+ });
32
+ it("calls app.requestTeardown even when window.openai is present", async () => {
33
+ vi.stubGlobal("openai", { requestClose: vi.fn() });
34
+ HostAdaptor.resetInstance();
35
+ McpAppBridge.resetInstance();
36
+ const requestTeardown = vi.fn().mockResolvedValue(undefined);
37
+ // biome-ignore lint/suspicious/noExplicitAny: test seam
38
+ const adaptor = getAdaptor();
39
+ adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });
40
+ const { result } = renderHook(() => useRequestClose());
41
+ await act(async () => {
42
+ await result.current();
43
+ });
44
+ expect(requestTeardown).toHaveBeenCalledTimes(1);
45
+ });
46
+ });
47
+ //# sourceMappingURL=use-request-close.test.js.map
@@ -0,0 +1 @@
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\", { hostType: \"mcp-app\" });\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 widget 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,15 +1,30 @@
1
1
  import { useCallback } from "react";
2
2
  import { getAdaptor, useHostContext, } from "../bridges/index.js";
3
3
  /**
4
- * Triggers a modal containing the widget 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();
8
- const view = useHostContext("view");
23
+ const display = useHostContext("display");
9
24
  const open = useCallback((opts) => adaptor.openModal(opts), [adaptor]);
10
25
  return {
11
- isOpen: view.mode === "modal",
12
- params: view.params,
26
+ isOpen: display.mode === "modal",
27
+ params: display.params,
13
28
  open,
14
29
  };
15
30
  }
@@ -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,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,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,IAAI,CAAC,IAAI,KAAK,OAAO;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI;KACL,CAAC;AACJ,CAAC"}
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
14
  vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
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());
@@ -48,7 +58,11 @@ describe("useRequestModal", () => {
48
58
  it("should call window.openai.requestModal with the options when open is called", () => {
49
59
  const { result } = renderHook(() => useRequestModal());
50
60
  const { open } = result.current;
51
- const options = { title: "Test Modal" };
61
+ const options = {
62
+ title: "Test Modal",
63
+ params: { foo: "bar" },
64
+ template: "ui://view/modal-template.html",
65
+ };
52
66
  open(options);
53
67
  expect(requestModalMock).toHaveBeenCalledTimes(1);
54
68
  expect(requestModalMock).toHaveBeenCalledWith(options);
@@ -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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"}
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\", { hostType: \"apps-sdk\" });\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"]}
@@ -0,0 +1,20 @@
1
+ import type { RequestSizeOptions } from "../bridges/types.js";
2
+ /** Function that asks the host to resize the view, returned by {@link useRequestSize}. */
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 useLayout}
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
+ */
20
+ export declare function useRequestSize(): RequestSizeFn;
@@ -0,0 +1,24 @@
1
+ import { useCallback } from "react";
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 useLayout}
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
+ */
19
+ export function useRequestSize() {
20
+ const adaptor = getAdaptor();
21
+ const requestSize = useCallback((size) => adaptor.requestSize(size), [adaptor]);
22
+ return requestSize;
23
+ }
24
+ //# sourceMappingURL=use-request-size.js.map
@@ -0,0 +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;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 useLayout}\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"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { renderHook, waitFor } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { HostAdaptor } from "../bridges/adaptor.js";
4
+ import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
5
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
6
+ import { useRequestSize } from "./use-request-size.js";
7
+ describe("useRequestSize", () => {
8
+ let postMessageMock;
9
+ beforeEach(() => {
10
+ HostAdaptor.resetInstance();
11
+ McpAppBridge.resetInstance();
12
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
13
+ vi.stubGlobal("openai", undefined);
14
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
15
+ postMessageMock = getMcpAppHostPostMessageMock();
16
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
17
+ });
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
+ }), "*");
33
+ });
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
+ }), "*");
44
+ });
45
+ });
46
+ });
47
+ //# sourceMappingURL=use-request-size.test.js.map
@@ -0,0 +1 @@
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,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,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\", { hostType: \"mcp-app\" });\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 +1,19 @@
1
- export declare function useSendFollowUpMessage(): (prompt: string) => Promise<void>;
1
+ import { 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
+ * @example
12
+ * ```tsx
13
+ * const send = useSendFollowUpMessage();
14
+ * <button onClick={() => send("Summarize the last 5 results")}>Summarize</button>
15
+ * ```
16
+ *
17
+ * @see https://docs.skybridge.tech/api-reference/use-send-follow-up-message
18
+ */
19
+ export declare function useSendFollowUpMessage(): (prompt: string, options?: SendFollowUpMessageOptions) => Promise<void>;
@@ -1,8 +1,25 @@
1
1
  import { useCallback } from "react";
2
- import { getAdaptor } from "../bridges/index.js";
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
+ * @example
13
+ * ```tsx
14
+ * const send = useSendFollowUpMessage();
15
+ * <button onClick={() => send("Summarize the last 5 results")}>Summarize</button>
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-send-follow-up-message
19
+ */
3
20
  export function useSendFollowUpMessage() {
4
21
  const adaptor = getAdaptor();
5
- const sendFollowUpMessage = useCallback((prompt) => adaptor.sendFollowUpMessage(prompt), [adaptor]);
22
+ const sendFollowUpMessage = useCallback((prompt, options) => adaptor.sendFollowUpMessage(prompt, options), [adaptor]);
6
23
  return sendFollowUpMessage;
7
24
  }
8
25
  //# sourceMappingURL=use-send-follow-up-message.js.map