skybridge 0.0.0-dev.f5759ba → 0.0.0-dev.f58ff90

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 (662) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +155 -0
  3. package/bin/run.js +5 -0
  4. package/dist/cli/build-helpers.d.ts +11 -0
  5. package/dist/cli/build-helpers.js +115 -0
  6. package/dist/cli/build-helpers.js.map +1 -0
  7. package/dist/cli/build-helpers.test.js +156 -0
  8. package/dist/cli/build-helpers.test.js.map +1 -0
  9. package/dist/cli/build-steps.d.ts +2 -0
  10. package/dist/cli/build-steps.js +84 -0
  11. package/dist/cli/build-steps.js.map +1 -0
  12. package/dist/cli/build-steps.test.js +72 -0
  13. package/dist/cli/build-steps.test.js.map +1 -0
  14. package/dist/cli/detect-port.d.ts +18 -0
  15. package/dist/cli/detect-port.js +49 -0
  16. package/dist/cli/detect-port.js.map +1 -0
  17. package/dist/cli/header.d.ts +4 -0
  18. package/dist/cli/header.js +6 -0
  19. package/dist/cli/header.js.map +1 -0
  20. package/dist/cli/resolve-skybridge-config.d.ts +6 -0
  21. package/dist/cli/resolve-skybridge-config.js +28 -0
  22. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  23. package/dist/cli/run-command.d.ts +2 -0
  24. package/dist/cli/run-command.js +43 -0
  25. package/dist/cli/run-command.js.map +1 -0
  26. package/dist/cli/run-plain.d.ts +18 -0
  27. package/dist/cli/run-plain.js +90 -0
  28. package/dist/cli/run-plain.js.map +1 -0
  29. package/dist/cli/telemetry.d.ts +7 -0
  30. package/dist/cli/telemetry.js +125 -0
  31. package/dist/cli/telemetry.js.map +1 -0
  32. package/dist/cli/tunnel-control-server.d.ts +9 -0
  33. package/dist/cli/tunnel-control-server.js +31 -0
  34. package/dist/cli/tunnel-control-server.js.map +1 -0
  35. package/dist/cli/tunnel-control-server.test.js +39 -0
  36. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  37. package/dist/cli/tunnel-handler.d.ts +3 -0
  38. package/dist/cli/tunnel-handler.js +48 -0
  39. package/dist/cli/tunnel-handler.js.map +1 -0
  40. package/dist/cli/tunnel-handler.test.js +105 -0
  41. package/dist/cli/tunnel-handler.test.js.map +1 -0
  42. package/dist/cli/tunnel.d.ts +57 -0
  43. package/dist/cli/tunnel.js +154 -0
  44. package/dist/cli/tunnel.js.map +1 -0
  45. package/dist/cli/tunnel.test.js +190 -0
  46. package/dist/cli/tunnel.test.js.map +1 -0
  47. package/dist/cli/types.d.ts +5 -0
  48. package/dist/cli/types.js +2 -0
  49. package/dist/cli/types.js.map +1 -0
  50. package/dist/cli/use-execute-steps.d.ts +11 -0
  51. package/dist/cli/use-execute-steps.js +36 -0
  52. package/dist/cli/use-execute-steps.js.map +1 -0
  53. package/dist/cli/use-messages.d.ts +3 -0
  54. package/dist/cli/use-messages.js +11 -0
  55. package/dist/cli/use-messages.js.map +1 -0
  56. package/dist/cli/use-nodemon.d.ts +26 -0
  57. package/dist/cli/use-nodemon.js +106 -0
  58. package/dist/cli/use-nodemon.js.map +1 -0
  59. package/dist/cli/use-open-browser.d.ts +1 -0
  60. package/dist/cli/use-open-browser.js +44 -0
  61. package/dist/cli/use-open-browser.js.map +1 -0
  62. package/dist/cli/use-tunnel.d.ts +14 -0
  63. package/dist/cli/use-tunnel.js +131 -0
  64. package/dist/cli/use-tunnel.js.map +1 -0
  65. package/dist/cli/use-typescript-check.d.ts +15 -0
  66. package/dist/cli/use-typescript-check.js +99 -0
  67. package/dist/cli/use-typescript-check.js.map +1 -0
  68. package/dist/commands/build.d.ts +6 -0
  69. package/dist/commands/build.js +31 -0
  70. package/dist/commands/build.js.map +1 -0
  71. package/dist/commands/create.d.ts +9 -0
  72. package/dist/commands/create.js +30 -0
  73. package/dist/commands/create.js.map +1 -0
  74. package/dist/commands/dev.d.ts +13 -0
  75. package/dist/commands/dev.js +128 -0
  76. package/dist/commands/dev.js.map +1 -0
  77. package/dist/commands/start.d.ts +9 -0
  78. package/dist/commands/start.js +55 -0
  79. package/dist/commands/start.js.map +1 -0
  80. package/dist/commands/telemetry/disable.d.ts +5 -0
  81. package/dist/commands/telemetry/disable.js +14 -0
  82. package/dist/commands/telemetry/disable.js.map +1 -0
  83. package/dist/commands/telemetry/enable.d.ts +5 -0
  84. package/dist/commands/telemetry/enable.js +14 -0
  85. package/dist/commands/telemetry/enable.js.map +1 -0
  86. package/dist/commands/telemetry/status.d.ts +5 -0
  87. package/dist/commands/telemetry/status.js +14 -0
  88. package/dist/commands/telemetry/status.js.map +1 -0
  89. package/dist/context-warnings.d.ts +5 -0
  90. package/dist/context-warnings.js +31 -0
  91. package/dist/context-warnings.js.map +1 -0
  92. package/dist/context-warnings.test.js +28 -0
  93. package/dist/context-warnings.test.js.map +1 -0
  94. package/dist/server/app.d.ts +211 -0
  95. package/dist/server/app.js +277 -0
  96. package/dist/server/app.js.map +1 -0
  97. package/dist/server/app.test.js +178 -0
  98. package/dist/server/app.test.js.map +1 -0
  99. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  100. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  101. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  102. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  103. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  104. package/dist/server/auth/discovery.d.ts +33 -0
  105. package/dist/server/auth/discovery.js +56 -0
  106. package/dist/server/auth/discovery.js.map +1 -0
  107. package/dist/server/auth/discovery.test.js +93 -0
  108. package/dist/server/auth/discovery.test.js.map +1 -0
  109. package/dist/server/auth/index.d.ts +48 -0
  110. package/dist/server/auth/index.js +2 -0
  111. package/dist/server/auth/index.js.map +1 -0
  112. package/dist/server/auth/providers/auth0.d.ts +40 -0
  113. package/dist/server/auth/providers/auth0.js +36 -0
  114. package/dist/server/auth/providers/auth0.js.map +1 -0
  115. package/dist/server/auth/providers/auth0.test.js +50 -0
  116. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  117. package/dist/server/auth/providers/authplane.d.ts +49 -0
  118. package/dist/server/auth/providers/authplane.js +57 -0
  119. package/dist/server/auth/providers/authplane.js.map +1 -0
  120. package/dist/server/auth/providers/authplane.test.js +143 -0
  121. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  122. package/dist/server/auth/providers/clerk.d.ts +51 -0
  123. package/dist/server/auth/providers/clerk.js +19 -0
  124. package/dist/server/auth/providers/clerk.js.map +1 -0
  125. package/dist/server/auth/providers/clerk.test.js +30 -0
  126. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  127. package/dist/server/auth/providers/custom.d.ts +42 -0
  128. package/dist/server/auth/providers/custom.js +59 -0
  129. package/dist/server/auth/providers/custom.js.map +1 -0
  130. package/dist/server/auth/providers/custom.test.js +161 -0
  131. package/dist/server/auth/providers/custom.test.js.map +1 -0
  132. package/dist/server/auth/providers/descope.d.ts +44 -0
  133. package/dist/server/auth/providers/descope.js +44 -0
  134. package/dist/server/auth/providers/descope.js.map +1 -0
  135. package/dist/server/auth/providers/descope.test.js +62 -0
  136. package/dist/server/auth/providers/descope.test.js.map +1 -0
  137. package/dist/server/auth/providers/shared.d.ts +2 -0
  138. package/dist/server/auth/providers/shared.js +6 -0
  139. package/dist/server/auth/providers/shared.js.map +1 -0
  140. package/dist/server/auth/providers/shared.test.js +10 -0
  141. package/dist/server/auth/providers/shared.test.js.map +1 -0
  142. package/dist/server/auth/providers/stytch.d.ts +25 -0
  143. package/dist/server/auth/providers/stytch.js +16 -0
  144. package/dist/server/auth/providers/stytch.js.map +1 -0
  145. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  146. package/dist/server/auth/providers/verify-spy.js +21 -0
  147. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  148. package/dist/server/auth/providers/workos.d.ts +34 -0
  149. package/dist/server/auth/providers/workos.js +16 -0
  150. package/dist/server/auth/providers/workos.js.map +1 -0
  151. package/dist/server/auth/security-schemes.d.ts +23 -0
  152. package/dist/server/auth/security-schemes.js +64 -0
  153. package/dist/server/auth/security-schemes.js.map +1 -0
  154. package/dist/server/auth/security-schemes.test.js +99 -0
  155. package/dist/server/auth/security-schemes.test.js.map +1 -0
  156. package/dist/server/auth/setup.d.ts +6 -0
  157. package/dist/server/auth/setup.js +91 -0
  158. package/dist/server/auth/setup.js.map +1 -0
  159. package/dist/server/auth/setup.test.js +514 -0
  160. package/dist/server/auth/setup.test.js.map +1 -0
  161. package/dist/server/auth/verify.d.ts +48 -0
  162. package/dist/server/auth/verify.js +62 -0
  163. package/dist/server/auth/verify.js.map +1 -0
  164. package/dist/server/auth/verify.test.js +165 -0
  165. package/dist/server/auth/verify.test.js.map +1 -0
  166. package/dist/server/auth-extra.test-d.js +130 -0
  167. package/dist/server/auth-extra.test-d.js.map +1 -0
  168. package/dist/server/auth.d.ts +57 -0
  169. package/dist/server/auth.js +27 -0
  170. package/dist/server/auth.js.map +1 -0
  171. package/dist/server/build-manifest.test.js +28 -0
  172. package/dist/server/build-manifest.test.js.map +1 -0
  173. package/dist/server/content-helpers.d.ts +67 -0
  174. package/dist/server/content-helpers.js +79 -0
  175. package/dist/server/content-helpers.js.map +1 -0
  176. package/dist/server/content-helpers.test.d.ts +1 -0
  177. package/dist/server/content-helpers.test.js +70 -0
  178. package/dist/server/content-helpers.test.js.map +1 -0
  179. package/dist/server/events.d.ts +113 -0
  180. package/dist/server/events.js +318 -0
  181. package/dist/server/events.js.map +1 -0
  182. package/dist/server/events.test.d.ts +1 -0
  183. package/dist/server/events.test.js +172 -0
  184. package/dist/server/events.test.js.map +1 -0
  185. package/dist/server/express.d.ts +32 -0
  186. package/dist/server/express.js +113 -0
  187. package/dist/server/express.js.map +1 -0
  188. package/dist/server/express.test.d.ts +1 -0
  189. package/dist/server/express.test.js +653 -0
  190. package/dist/server/express.test.js.map +1 -0
  191. package/dist/server/file-ref.d.ts +28 -0
  192. package/dist/server/file-ref.js +27 -0
  193. package/dist/server/file-ref.js.map +1 -0
  194. package/dist/server/form-input.d.ts +120 -0
  195. package/dist/server/form-input.js +89 -0
  196. package/dist/server/form-input.js.map +1 -0
  197. package/dist/server/host.d.ts +2 -0
  198. package/dist/server/host.js +11 -0
  199. package/dist/server/host.js.map +1 -0
  200. package/dist/server/host.test.d.ts +1 -0
  201. package/dist/server/host.test.js +13 -0
  202. package/dist/server/host.test.js.map +1 -0
  203. package/dist/server/index.d.ts +24 -0
  204. package/dist/server/index.js +20 -0
  205. package/dist/server/index.js.map +1 -0
  206. package/dist/{src/server → server}/inferUtilityTypes.d.ts +6 -6
  207. package/dist/server/inferUtilityTypes.js.map +1 -0
  208. package/dist/server/mcp-errors.test.d.ts +1 -0
  209. package/dist/server/mcp-errors.test.js +229 -0
  210. package/dist/server/mcp-errors.test.js.map +1 -0
  211. package/dist/server/metric.d.ts +16 -0
  212. package/dist/server/metric.js +62 -0
  213. package/dist/server/metric.js.map +1 -0
  214. package/dist/server/middleware.d.ts +162 -0
  215. package/dist/server/middleware.js +126 -0
  216. package/dist/server/middleware.js.map +1 -0
  217. package/dist/server/middleware.test-d.d.ts +1 -0
  218. package/dist/server/middleware.test-d.js +75 -0
  219. package/dist/server/middleware.test-d.js.map +1 -0
  220. package/dist/server/middleware.test.d.ts +1 -0
  221. package/dist/server/middleware.test.js +601 -0
  222. package/dist/server/middleware.test.js.map +1 -0
  223. package/dist/server/register-tool.test.d.ts +1 -0
  224. package/dist/server/register-tool.test.js +230 -0
  225. package/dist/server/register-tool.test.js.map +1 -0
  226. package/dist/server/requestOrigin.d.ts +7 -0
  227. package/dist/server/requestOrigin.js +25 -0
  228. package/dist/server/requestOrigin.js.map +1 -0
  229. package/dist/server/server.d.ts +665 -0
  230. package/dist/server/server.js +815 -0
  231. package/dist/server/server.js.map +1 -0
  232. package/dist/server/skills-integration.test.d.ts +1 -0
  233. package/dist/server/skills-integration.test.js +86 -0
  234. package/dist/server/skills-integration.test.js.map +1 -0
  235. package/dist/server/skills.d.ts +27 -0
  236. package/dist/server/skills.js +188 -0
  237. package/dist/server/skills.js.map +1 -0
  238. package/dist/server/skills.test.d.ts +1 -0
  239. package/dist/server/skills.test.js +243 -0
  240. package/dist/server/skills.test.js.map +1 -0
  241. package/dist/{src/server → server}/templateHelper.d.ts +3 -7
  242. package/dist/server/templateHelper.js +11 -0
  243. package/dist/server/templateHelper.js.map +1 -0
  244. package/dist/server/templates.generated.d.ts +4 -0
  245. package/dist/server/templates.generated.js +57 -0
  246. package/dist/server/templates.generated.js.map +1 -0
  247. package/dist/server/tool-extra.test.d.ts +1 -0
  248. package/dist/server/tool-extra.test.js +167 -0
  249. package/dist/server/tool-extra.test.js.map +1 -0
  250. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  251. package/dist/server/tunnel-proxy-router.js +110 -0
  252. package/dist/server/tunnel-proxy-router.js.map +1 -0
  253. package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
  254. package/dist/server/tunnel-proxy-router.test.js +229 -0
  255. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  256. package/dist/server/view-name.test-d.d.ts +1 -0
  257. package/dist/server/view-name.test-d.js +8 -0
  258. package/dist/server/view-name.test-d.js.map +1 -0
  259. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  260. package/dist/server/view-resource-resolution.test.js +211 -0
  261. package/dist/server/view-resource-resolution.test.js.map +1 -0
  262. package/dist/server/viewsDevServer.d.ts +14 -0
  263. package/dist/server/viewsDevServer.js +48 -0
  264. package/dist/server/viewsDevServer.js.map +1 -0
  265. package/dist/{src/test → test}/utils.d.ts +21 -31
  266. package/dist/test/utils.js +266 -0
  267. package/dist/test/utils.js.map +1 -0
  268. package/dist/test/view.test.d.ts +1 -0
  269. package/dist/test/view.test.js +540 -0
  270. package/dist/test/view.test.js.map +1 -0
  271. package/dist/version.d.ts +1 -0
  272. package/dist/version.js +3 -0
  273. package/dist/version.js.map +1 -0
  274. package/dist/views/index.d.ts +10 -0
  275. package/dist/views/index.js +3 -0
  276. package/dist/views/index.js.map +1 -0
  277. package/dist/views/scan-views.d.ts +16 -0
  278. package/dist/views/scan-views.js +88 -0
  279. package/dist/views/scan-views.js.map +1 -0
  280. package/dist/views/scan-views.test.d.ts +1 -0
  281. package/dist/views/scan-views.test.js +99 -0
  282. package/dist/views/scan-views.test.js.map +1 -0
  283. package/dist/views/validate-view.d.ts +1 -0
  284. package/dist/views/validate-view.js +9 -0
  285. package/dist/views/validate-view.js.map +1 -0
  286. package/dist/views/validate-view.test.d.ts +1 -0
  287. package/dist/views/validate-view.test.js +24 -0
  288. package/dist/views/validate-view.test.js.map +1 -0
  289. package/dist/web/bridges/adaptor.d.ts +62 -0
  290. package/dist/web/bridges/adaptor.js +480 -0
  291. package/dist/web/bridges/adaptor.js.map +1 -0
  292. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  293. package/dist/web/bridges/adaptor.test.js +292 -0
  294. package/dist/web/bridges/adaptor.test.js.map +1 -0
  295. package/dist/web/bridges/apps-sdk/bridge.d.ts +15 -0
  296. package/dist/web/bridges/apps-sdk/bridge.js +58 -0
  297. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  298. package/dist/web/bridges/apps-sdk/index.d.ts +4 -0
  299. package/dist/web/bridges/apps-sdk/index.js +4 -0
  300. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  301. package/dist/web/bridges/apps-sdk/types.d.ts +132 -0
  302. package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -1
  303. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  304. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +13 -0
  305. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +18 -0
  306. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  307. package/dist/web/bridges/get-adaptor.d.ts +9 -0
  308. package/dist/web/bridges/get-adaptor.js +10 -0
  309. package/dist/web/bridges/get-adaptor.js.map +1 -0
  310. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  311. package/dist/web/bridges/get-adaptor.test.js +32 -0
  312. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  313. package/dist/web/bridges/index.d.ts +5 -0
  314. package/dist/web/bridges/index.js +6 -0
  315. package/dist/web/bridges/index.js.map +1 -0
  316. package/dist/web/bridges/mcp-app/bridge.d.ts +39 -0
  317. package/dist/web/bridges/mcp-app/bridge.js +175 -0
  318. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  319. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  320. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  321. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  322. package/dist/web/bridges/mcp-app/index.d.ts +3 -0
  323. package/dist/web/bridges/mcp-app/index.js +3 -0
  324. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  325. package/dist/web/bridges/mcp-app/types.d.ts +25 -0
  326. package/dist/web/bridges/mcp-app/types.js +2 -0
  327. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  328. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +19 -0
  329. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +19 -0
  330. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  331. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.d.ts +1 -0
  332. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
  333. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  334. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  335. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  336. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  337. package/dist/web/bridges/types.d.ts +272 -0
  338. package/dist/web/bridges/types.js +15 -0
  339. package/dist/web/bridges/types.js.map +1 -0
  340. package/dist/web/bridges/types.test.d.ts +1 -0
  341. package/dist/web/bridges/types.test.js +19 -0
  342. package/dist/web/bridges/types.test.js.map +1 -0
  343. package/dist/web/bridges/use-host-context.d.ts +7 -0
  344. package/dist/web/bridges/use-host-context.js +13 -0
  345. package/dist/web/bridges/use-host-context.js.map +1 -0
  346. package/dist/web/components/modal-provider.d.ts +4 -0
  347. package/dist/web/components/modal-provider.js +46 -0
  348. package/dist/web/components/modal-provider.js.map +1 -0
  349. package/dist/web/create-store.d.ts +29 -0
  350. package/dist/web/create-store.js +64 -0
  351. package/dist/web/create-store.js.map +1 -0
  352. package/dist/web/create-store.test.d.ts +1 -0
  353. package/dist/web/create-store.test.js +132 -0
  354. package/dist/web/create-store.test.js.map +1 -0
  355. package/dist/web/data-llm.d.ts +47 -0
  356. package/dist/{src/web → web}/data-llm.js +42 -9
  357. package/dist/web/data-llm.js.map +1 -0
  358. package/dist/web/data-llm.test.d.ts +1 -0
  359. package/dist/web/data-llm.test.js +161 -0
  360. package/dist/web/data-llm.test.js.map +1 -0
  361. package/dist/{src/web → web}/generate-helpers.d.ts +41 -32
  362. package/dist/{src/web → web}/generate-helpers.js +38 -30
  363. package/dist/web/generate-helpers.js.map +1 -0
  364. package/dist/web/generate-helpers.test-d.d.ts +1 -0
  365. package/dist/{src/web → web}/generate-helpers.test-d.js +35 -30
  366. package/dist/web/generate-helpers.test-d.js.map +1 -0
  367. package/dist/web/generate-helpers.test.d.ts +1 -0
  368. package/dist/{src/web → web}/generate-helpers.test.js +2 -2
  369. package/dist/web/generate-helpers.test.js.map +1 -0
  370. package/dist/{src/web → web}/helpers/state.d.ts +2 -2
  371. package/dist/web/helpers/state.js +45 -0
  372. package/dist/web/helpers/state.js.map +1 -0
  373. package/dist/web/helpers/state.test.d.ts +1 -0
  374. package/dist/{src/web → web}/helpers/state.test.js +9 -9
  375. package/dist/web/helpers/state.test.js.map +1 -0
  376. package/dist/web/hooks/index.d.ts +20 -0
  377. package/dist/web/hooks/index.js +21 -0
  378. package/dist/web/hooks/index.js.map +1 -0
  379. package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
  380. package/dist/web/hooks/openai-extensions.test.js +107 -0
  381. package/dist/web/hooks/openai-extensions.test.js.map +1 -0
  382. package/dist/web/hooks/test/utils.d.ts +21 -0
  383. package/dist/web/hooks/test/utils.js +75 -0
  384. package/dist/web/hooks/test/utils.js.map +1 -0
  385. package/dist/{src/web → web}/hooks/use-call-tool.d.ts +48 -2
  386. package/dist/web/hooks/use-call-tool.js +101 -0
  387. package/dist/web/hooks/use-call-tool.js.map +1 -0
  388. package/dist/web/hooks/use-call-tool.test-d.d.ts +1 -0
  389. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  390. package/dist/web/hooks/use-call-tool.test.d.ts +1 -0
  391. package/dist/{src/web → web}/hooks/use-call-tool.test.js +95 -24
  392. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  393. package/dist/web/hooks/use-deep-link.d.ts +22 -0
  394. package/dist/web/hooks/use-deep-link.js +34 -0
  395. package/dist/web/hooks/use-deep-link.js.map +1 -0
  396. package/dist/web/hooks/use-display-mode.d.ts +24 -0
  397. package/dist/web/hooks/use-display-mode.js +29 -0
  398. package/dist/web/hooks/use-display-mode.js.map +1 -0
  399. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  400. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  401. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  402. package/dist/web/hooks/use-display-mode.test.d.ts +1 -0
  403. package/dist/web/hooks/use-display-mode.test.js +77 -0
  404. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  405. package/dist/web/hooks/use-download.d.ts +3 -0
  406. package/dist/web/hooks/use-download.js +7 -0
  407. package/dist/web/hooks/use-download.js.map +1 -0
  408. package/dist/web/hooks/use-download.test.d.ts +1 -0
  409. package/dist/web/hooks/use-download.test.js +103 -0
  410. package/dist/web/hooks/use-download.test.js.map +1 -0
  411. package/dist/web/hooks/use-file-resource.d.ts +37 -0
  412. package/dist/web/hooks/use-file-resource.js +98 -0
  413. package/dist/web/hooks/use-file-resource.js.map +1 -0
  414. package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
  415. package/dist/web/hooks/use-file-resource.test.js +65 -0
  416. package/dist/web/hooks/use-file-resource.test.js.map +1 -0
  417. package/dist/web/hooks/use-files.d.ts +39 -0
  418. package/dist/web/hooks/use-files.js +42 -0
  419. package/dist/web/hooks/use-files.js.map +1 -0
  420. package/dist/web/hooks/use-files.test.d.ts +1 -0
  421. package/dist/web/hooks/use-files.test.js +62 -0
  422. package/dist/web/hooks/use-files.test.js.map +1 -0
  423. package/dist/web/hooks/use-host.d.ts +44 -0
  424. package/dist/web/hooks/use-host.js +45 -0
  425. package/dist/web/hooks/use-host.js.map +1 -0
  426. package/dist/web/hooks/use-host.test.d.ts +1 -0
  427. package/dist/web/hooks/use-host.test.js +59 -0
  428. package/dist/web/hooks/use-host.test.js.map +1 -0
  429. package/dist/web/hooks/use-model-context.d.ts +44 -0
  430. package/dist/web/hooks/use-model-context.js +63 -0
  431. package/dist/web/hooks/use-model-context.js.map +1 -0
  432. package/dist/web/hooks/use-open-external.d.ts +20 -0
  433. package/dist/web/hooks/use-open-external.js +24 -0
  434. package/dist/web/hooks/use-open-external.js.map +1 -0
  435. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  436. package/dist/web/hooks/use-open-external.test.js +75 -0
  437. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  438. package/dist/web/hooks/use-open-file.d.ts +20 -0
  439. package/dist/web/hooks/use-open-file.js +25 -0
  440. package/dist/web/hooks/use-open-file.js.map +1 -0
  441. package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
  442. package/dist/web/hooks/use-register-view-tool.js +50 -0
  443. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  444. package/dist/web/hooks/use-request-close.d.ts +16 -0
  445. package/dist/web/hooks/use-request-close.js +21 -0
  446. package/dist/web/hooks/use-request-close.js.map +1 -0
  447. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  448. package/dist/web/hooks/use-request-close.test.js +47 -0
  449. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  450. package/dist/web/hooks/use-request-modal.d.ts +24 -0
  451. package/dist/web/hooks/use-request-modal.js +31 -0
  452. package/dist/web/hooks/use-request-modal.js.map +1 -0
  453. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  454. package/dist/web/hooks/use-request-modal.test.js +71 -0
  455. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  456. package/dist/web/hooks/use-request-size.d.ts +20 -0
  457. package/dist/web/hooks/use-request-size.js +24 -0
  458. package/dist/web/hooks/use-request-size.js.map +1 -0
  459. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  460. package/dist/web/hooks/use-request-size.test.js +47 -0
  461. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  462. package/dist/web/hooks/use-send-follow-up-message.d.ts +25 -0
  463. package/dist/web/hooks/use-send-follow-up-message.js +31 -0
  464. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  465. package/dist/web/hooks/use-set-open-in-app-url.d.ts +18 -0
  466. package/dist/web/hooks/use-set-open-in-app-url.js +25 -0
  467. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  468. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  469. package/dist/web/hooks/use-set-open-in-app-url.test.js +57 -0
  470. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  471. package/dist/web/hooks/use-tool-info.d.ts +68 -0
  472. package/dist/web/hooks/use-tool-info.js +48 -0
  473. package/dist/web/hooks/use-tool-info.js.map +1 -0
  474. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  475. package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +19 -6
  476. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  477. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  478. package/dist/web/hooks/use-tool-info.test.js +135 -0
  479. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  480. package/dist/{src/web → web}/hooks/use-user.d.ts +5 -2
  481. package/dist/web/hooks/use-user.js +38 -0
  482. package/dist/web/hooks/use-user.js.map +1 -0
  483. package/dist/web/hooks/use-user.test.d.ts +1 -0
  484. package/dist/web/hooks/use-user.test.js +170 -0
  485. package/dist/web/hooks/use-user.test.js.map +1 -0
  486. package/dist/web/hooks/use-view-state.d.ts +25 -0
  487. package/dist/web/hooks/use-view-state.js +42 -0
  488. package/dist/web/hooks/use-view-state.js.map +1 -0
  489. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  490. package/dist/web/hooks/use-view-state.test.js +212 -0
  491. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  492. package/dist/web/hooks/use-viewport.d.ts +20 -0
  493. package/dist/web/hooks/use-viewport.js +21 -0
  494. package/dist/web/hooks/use-viewport.js.map +1 -0
  495. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  496. package/dist/web/hooks/use-viewport.test.js +109 -0
  497. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  498. package/dist/{src/web → web}/index.d.ts +1 -2
  499. package/dist/{src/web → web}/index.js +1 -2
  500. package/dist/web/index.js.map +1 -0
  501. package/dist/web/mount-view.d.ts +21 -0
  502. package/dist/web/mount-view.js +41 -0
  503. package/dist/web/mount-view.js.map +1 -0
  504. package/dist/{src/web → web}/proxy.js +0 -1
  505. package/dist/web/proxy.js.map +1 -0
  506. package/dist/web/types.d.ts +20 -0
  507. package/dist/web/types.js +2 -0
  508. package/dist/web/types.js.map +1 -0
  509. package/package.json +92 -41
  510. package/tsconfig.base.json +33 -0
  511. package/dist/src/server/devtoolsStaticServer.d.ts +0 -15
  512. package/dist/src/server/devtoolsStaticServer.js +0 -38
  513. package/dist/src/server/devtoolsStaticServer.js.map +0 -1
  514. package/dist/src/server/index.d.ts +0 -5
  515. package/dist/src/server/index.js +0 -4
  516. package/dist/src/server/index.js.map +0 -1
  517. package/dist/src/server/inferUtilityTypes.js.map +0 -1
  518. package/dist/src/server/server.d.ts +0 -74
  519. package/dist/src/server/server.js +0 -82
  520. package/dist/src/server/server.js.map +0 -1
  521. package/dist/src/server/templateHelper.js +0 -30
  522. package/dist/src/server/templateHelper.js.map +0 -1
  523. package/dist/src/server/templates/development.hbs +0 -13
  524. package/dist/src/server/templates/production.hbs +0 -7
  525. package/dist/src/server/widgetsDevServer.d.ts +0 -12
  526. package/dist/src/server/widgetsDevServer.js +0 -39
  527. package/dist/src/server/widgetsDevServer.js.map +0 -1
  528. package/dist/src/test/utils.js +0 -242
  529. package/dist/src/test/utils.js.map +0 -1
  530. package/dist/src/test/widget.test.js +0 -146
  531. package/dist/src/test/widget.test.js.map +0 -1
  532. package/dist/src/web/bridges/apps-sdk-bridge.d.ts +0 -8
  533. package/dist/src/web/bridges/apps-sdk-bridge.js +0 -41
  534. package/dist/src/web/bridges/apps-sdk-bridge.js.map +0 -1
  535. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.d.ts +0 -2
  536. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js +0 -7
  537. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js.map +0 -1
  538. package/dist/src/web/bridges/hooks/use-bridge.d.ts +0 -3
  539. package/dist/src/web/bridges/hooks/use-bridge.js +0 -27
  540. package/dist/src/web/bridges/hooks/use-bridge.js.map +0 -1
  541. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.d.ts +0 -4
  542. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js +0 -7
  543. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js.map +0 -1
  544. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js +0 -58
  545. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js.map +0 -1
  546. package/dist/src/web/bridges/index.d.ts +0 -3
  547. package/dist/src/web/bridges/index.js +0 -4
  548. package/dist/src/web/bridges/index.js.map +0 -1
  549. package/dist/src/web/bridges/mcp-app-bridge.d.ts +0 -26
  550. package/dist/src/web/bridges/mcp-app-bridge.js +0 -130
  551. package/dist/src/web/bridges/mcp-app-bridge.js.map +0 -1
  552. package/dist/src/web/create-store.d.ts +0 -3
  553. package/dist/src/web/create-store.js +0 -25
  554. package/dist/src/web/create-store.js.map +0 -1
  555. package/dist/src/web/create-store.test.js +0 -70
  556. package/dist/src/web/create-store.test.js.map +0 -1
  557. package/dist/src/web/data-llm.d.ts +0 -14
  558. package/dist/src/web/data-llm.js.map +0 -1
  559. package/dist/src/web/data-llm.test.js +0 -76
  560. package/dist/src/web/data-llm.test.js.map +0 -1
  561. package/dist/src/web/generate-helpers.js.map +0 -1
  562. package/dist/src/web/generate-helpers.test-d.js.map +0 -1
  563. package/dist/src/web/generate-helpers.test.js.map +0 -1
  564. package/dist/src/web/helpers/state.js +0 -40
  565. package/dist/src/web/helpers/state.js.map +0 -1
  566. package/dist/src/web/helpers/state.test.js.map +0 -1
  567. package/dist/src/web/hooks/index.d.ts +0 -11
  568. package/dist/src/web/hooks/index.js +0 -12
  569. package/dist/src/web/hooks/index.js.map +0 -1
  570. package/dist/src/web/hooks/use-call-tool.js +0 -60
  571. package/dist/src/web/hooks/use-call-tool.js.map +0 -1
  572. package/dist/src/web/hooks/use-call-tool.test-d.js.map +0 -1
  573. package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
  574. package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
  575. package/dist/src/web/hooks/use-display-mode.js +0 -7
  576. package/dist/src/web/hooks/use-display-mode.js.map +0 -1
  577. package/dist/src/web/hooks/use-display-mode.test.js +0 -41
  578. package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
  579. package/dist/src/web/hooks/use-files.d.ts +0 -10
  580. package/dist/src/web/hooks/use-files.js +0 -7
  581. package/dist/src/web/hooks/use-files.js.map +0 -1
  582. package/dist/src/web/hooks/use-files.test.js +0 -29
  583. package/dist/src/web/hooks/use-files.test.js.map +0 -1
  584. package/dist/src/web/hooks/use-layout.d.ts +0 -22
  585. package/dist/src/web/hooks/use-layout.js +0 -23
  586. package/dist/src/web/hooks/use-layout.js.map +0 -1
  587. package/dist/src/web/hooks/use-layout.test.js +0 -46
  588. package/dist/src/web/hooks/use-layout.test.js.map +0 -1
  589. package/dist/src/web/hooks/use-open-external.d.ts +0 -1
  590. package/dist/src/web/hooks/use-open-external.js +0 -6
  591. package/dist/src/web/hooks/use-open-external.js.map +0 -1
  592. package/dist/src/web/hooks/use-open-external.test.js +0 -24
  593. package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
  594. package/dist/src/web/hooks/use-openai-global.d.ts +0 -3
  595. package/dist/src/web/hooks/use-openai-global.js +0 -6
  596. package/dist/src/web/hooks/use-openai-global.js.map +0 -1
  597. package/dist/src/web/hooks/use-request-modal.d.ts +0 -6
  598. package/dist/src/web/hooks/use-request-modal.js +0 -9
  599. package/dist/src/web/hooks/use-request-modal.js.map +0 -1
  600. package/dist/src/web/hooks/use-request-modal.test.js +0 -24
  601. package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
  602. package/dist/src/web/hooks/use-send-follow-up-message.d.ts +0 -1
  603. package/dist/src/web/hooks/use-send-follow-up-message.js +0 -11
  604. package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
  605. package/dist/src/web/hooks/use-tool-info.d.ts +0 -25
  606. package/dist/src/web/hooks/use-tool-info.js +0 -20
  607. package/dist/src/web/hooks/use-tool-info.js.map +0 -1
  608. package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
  609. package/dist/src/web/hooks/use-tool-info.test.js +0 -60
  610. package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
  611. package/dist/src/web/hooks/use-user.js +0 -19
  612. package/dist/src/web/hooks/use-user.js.map +0 -1
  613. package/dist/src/web/hooks/use-user.test.js +0 -44
  614. package/dist/src/web/hooks/use-user.test.js.map +0 -1
  615. package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
  616. package/dist/src/web/hooks/use-widget-state.js +0 -32
  617. package/dist/src/web/hooks/use-widget-state.js.map +0 -1
  618. package/dist/src/web/hooks/use-widget-state.test.js +0 -61
  619. package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
  620. package/dist/src/web/index.js.map +0 -1
  621. package/dist/src/web/mount-widget.d.ts +0 -1
  622. package/dist/src/web/mount-widget.js +0 -19
  623. package/dist/src/web/mount-widget.js.map +0 -1
  624. package/dist/src/web/plugin/data-llm.test.js +0 -81
  625. package/dist/src/web/plugin/data-llm.test.js.map +0 -1
  626. package/dist/src/web/plugin/plugin.d.ts +0 -2
  627. package/dist/src/web/plugin/plugin.js +0 -39
  628. package/dist/src/web/plugin/plugin.js.map +0 -1
  629. package/dist/src/web/plugin/transform-data-llm.d.ts +0 -12
  630. package/dist/src/web/plugin/transform-data-llm.js +0 -93
  631. package/dist/src/web/plugin/transform-data-llm.js.map +0 -1
  632. package/dist/src/web/plugin/transform-data-llm.test.js +0 -81
  633. package/dist/src/web/plugin/transform-data-llm.test.js.map +0 -1
  634. package/dist/src/web/proxy.js.map +0 -1
  635. package/dist/src/web/types.d.ts +0 -138
  636. package/dist/src/web/types.js.map +0 -1
  637. package/dist/vitest.config.d.ts +0 -2
  638. package/dist/vitest.config.js +0 -8
  639. package/dist/vitest.config.js.map +0 -1
  640. /package/dist/{src/test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  641. /package/dist/{src/web/bridges/hooks/use-mcp-app-bridge.test.d.ts → cli/build-steps.test.d.ts} +0 -0
  642. /package/dist/{src/web/create-store.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  643. /package/dist/{src/web/data-llm.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  644. /package/dist/{src/web/generate-helpers.test-d.d.ts → cli/tunnel.test.d.ts} +0 -0
  645. /package/dist/{src/web/generate-helpers.test.d.ts → context-warnings.test.d.ts} +0 -0
  646. /package/dist/{src/web/helpers/state.test.d.ts → server/app.test.d.ts} +0 -0
  647. /package/dist/{src/web/hooks/use-call-tool.test-d.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
  648. /package/dist/{src/web/hooks/use-display-mode.test.d.ts → server/auth/discovery.test.d.ts} +0 -0
  649. /package/dist/{src/web/hooks/use-files.test.d.ts → server/auth/providers/auth0.test.d.ts} +0 -0
  650. /package/dist/{src/web/hooks/use-layout.test.d.ts → server/auth/providers/authplane.test.d.ts} +0 -0
  651. /package/dist/{src/web/hooks/use-open-external.test.d.ts → server/auth/providers/clerk.test.d.ts} +0 -0
  652. /package/dist/{src/web/hooks/use-request-modal.test.d.ts → server/auth/providers/custom.test.d.ts} +0 -0
  653. /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → server/auth/providers/descope.test.d.ts} +0 -0
  654. /package/dist/{src/web/hooks/use-tool-info.test.d.ts → server/auth/providers/shared.test.d.ts} +0 -0
  655. /package/dist/{src/web/hooks/use-user.test.d.ts → server/auth/security-schemes.test.d.ts} +0 -0
  656. /package/dist/{src/web/hooks/use-widget-state.test.d.ts → server/auth/setup.test.d.ts} +0 -0
  657. /package/dist/{src/web/plugin/data-llm.test.d.ts → server/auth/verify.test.d.ts} +0 -0
  658. /package/dist/{src/web/hooks/use-call-tool.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
  659. /package/dist/{src/web/plugin/transform-data-llm.test.d.ts → server/build-manifest.test.d.ts} +0 -0
  660. /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
  661. /package/dist/{src/web → web}/hooks/use-call-tool.test-d.js +0 -0
  662. /package/dist/{src/web → web}/proxy.d.ts +0 -0
@@ -0,0 +1,44 @@
1
+ import type { OpenAIHostContext } from "../bridges/mcp-app/types.js";
2
+ import type { ModelContextParams } from "../bridges/types.js";
3
+ /** Model context the view attached, as ChatGPT reports it back. */
4
+ export type ModelContextState = OpenAIHostContext["openai/modelContext"];
5
+ /**
6
+ * Send content to the model through the MCP Apps `ui/update-model-context`
7
+ * request. Each `update` replaces what this hook sent before. Outside ChatGPT
8
+ * it is merged with the {@link useViewState} state, which wins on shared
9
+ * `structuredContent` keys.
10
+ *
11
+ * ChatGPT also reads the OpenAI presentation metadata, shows each block as a
12
+ * composer attachment and reports the attached context back:
13
+ * `_meta["openai/title"]`, `_meta["openai/thumbnail"]` on text blocks, and
14
+ * `annotations.audience: ["assistant"]` to hide a block from the user.
15
+ *
16
+ * - `supported`: whether the host advertises `updateModelContext` or
17
+ * `openai/modelContext`.
18
+ * - `context`: ChatGPT only, the attached context; `null` once the user
19
+ * removed it, `undefined` when the host never reported one.
20
+ * - `update`: replaces the context and resolves with ChatGPT's `updateId`,
21
+ * to compare with `context.updateId`. Rejects with `NotSupportedError` on
22
+ * hosts that don't advertise model context updates.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { supported, update } = useModelContext();
27
+ * update({
28
+ * content: [
29
+ * {
30
+ * type: "text",
31
+ * text: "Selected: M6 hex bolt",
32
+ * _meta: { "openai/title": "Hex bolt" },
33
+ * },
34
+ * ],
35
+ * });
36
+ * ```
37
+ *
38
+ * @see https://docs.skybridge.tech/api-reference/use-model-context
39
+ */
40
+ export declare function useModelContext(): {
41
+ supported: boolean;
42
+ context: ModelContextState;
43
+ update: (params: ModelContextParams) => Promise<string | undefined>;
44
+ };
@@ -0,0 +1,63 @@
1
+ import { ContentBlockSchema } from "@modelcontextprotocol/core";
2
+ import { useCallback, useMemo } from "react";
3
+ import * as z from "zod/v4";
4
+ import { getAdaptor, useMcpAppContext } from "../bridges/index.js";
5
+ import { useHost } from "./use-host.js";
6
+ const ModelContextSchema = z
7
+ .object({
8
+ updateId: z.string().min(1),
9
+ content: z.array(ContentBlockSchema).optional(),
10
+ structuredContent: z.record(z.string(), z.unknown()).optional(),
11
+ })
12
+ .nullable();
13
+ /**
14
+ * Send content to the model through the MCP Apps `ui/update-model-context`
15
+ * request. Each `update` replaces what this hook sent before. Outside ChatGPT
16
+ * it is merged with the {@link useViewState} state, which wins on shared
17
+ * `structuredContent` keys.
18
+ *
19
+ * ChatGPT also reads the OpenAI presentation metadata, shows each block as a
20
+ * composer attachment and reports the attached context back:
21
+ * `_meta["openai/title"]`, `_meta["openai/thumbnail"]` on text blocks, and
22
+ * `annotations.audience: ["assistant"]` to hide a block from the user.
23
+ *
24
+ * - `supported`: whether the host advertises `updateModelContext` or
25
+ * `openai/modelContext`.
26
+ * - `context`: ChatGPT only, the attached context; `null` once the user
27
+ * removed it, `undefined` when the host never reported one.
28
+ * - `update`: replaces the context and resolves with ChatGPT's `updateId`,
29
+ * to compare with `context.updateId`. Rejects with `NotSupportedError` on
30
+ * hosts that don't advertise model context updates.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const { supported, update } = useModelContext();
35
+ * update({
36
+ * content: [
37
+ * {
38
+ * type: "text",
39
+ * text: "Selected: M6 hex bolt",
40
+ * _meta: { "openai/title": "Hex bolt" },
41
+ * },
42
+ * ],
43
+ * });
44
+ * ```
45
+ *
46
+ * @see https://docs.skybridge.tech/api-reference/use-model-context
47
+ */
48
+ export function useModelContext() {
49
+ const { capabilities, openaiCapabilities } = useHost();
50
+ const reported = useMcpAppContext("openai/modelContext");
51
+ const context = useMemo(() => {
52
+ const parsed = ModelContextSchema.safeParse(reported);
53
+ return parsed.success ? parsed.data : undefined;
54
+ }, [reported]);
55
+ const update = useCallback((params) => getAdaptor().updateModelContext(params), []);
56
+ return {
57
+ supported: Boolean(capabilities?.updateModelContext) ||
58
+ openaiCapabilities.modelContext,
59
+ context,
60
+ update,
61
+ };
62
+ }
63
+ //# sourceMappingURL=use-model-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-model-context.js","sourceRoot":"","sources":["../../../src/web/hooks/use-model-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,kBAAkB,GAAG,CAAC;KACzB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE;IAC/C,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;CAChE,CAAC;KACD,QAAQ,EAAE,CAAC;AAKd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,eAAe;IAK7B,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE;QAC3B,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACf,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,MAA0B,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,EACvE,EAAE,CACH,CAAC;IAEF,OAAO;QACL,SAAS,EACP,OAAO,CAAC,YAAY,EAAE,kBAAkB,CAAC;YACzC,kBAAkB,CAAC,YAAY;QACjC,OAAO;QACP,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["import { ContentBlockSchema } from \"@modelcontextprotocol/core\";\nimport { useCallback, useMemo } from \"react\";\nimport * as z from \"zod/v4\";\nimport { getAdaptor, useMcpAppContext } from \"../bridges/index.js\";\nimport type { OpenAIHostContext } from \"../bridges/mcp-app/types.js\";\nimport type { ModelContextParams } from \"../bridges/types.js\";\nimport { useHost } from \"./use-host.js\";\n\nconst ModelContextSchema = z\n .object({\n updateId: z.string().min(1),\n content: z.array(ContentBlockSchema).optional(),\n structuredContent: z.record(z.string(), z.unknown()).optional(),\n })\n .nullable();\n\n/** Model context the view attached, as ChatGPT reports it back. */\nexport type ModelContextState = OpenAIHostContext[\"openai/modelContext\"];\n\n/**\n * Send content to the model through the MCP Apps `ui/update-model-context`\n * request. Each `update` replaces what this hook sent before. Outside ChatGPT\n * it is merged with the {@link useViewState} state, which wins on shared\n * `structuredContent` keys.\n *\n * ChatGPT also reads the OpenAI presentation metadata, shows each block as a\n * composer attachment and reports the attached context back:\n * `_meta[\"openai/title\"]`, `_meta[\"openai/thumbnail\"]` on text blocks, and\n * `annotations.audience: [\"assistant\"]` to hide a block from the user.\n *\n * - `supported`: whether the host advertises `updateModelContext` or\n * `openai/modelContext`.\n * - `context`: ChatGPT only, the attached context; `null` once the user\n * removed it, `undefined` when the host never reported one.\n * - `update`: replaces the context and resolves with ChatGPT's `updateId`,\n * to compare with `context.updateId`. Rejects with `NotSupportedError` on\n * hosts that don't advertise model context updates.\n *\n * @example\n * ```tsx\n * const { supported, update } = useModelContext();\n * update({\n * content: [\n * {\n * type: \"text\",\n * text: \"Selected: M6 hex bolt\",\n * _meta: { \"openai/title\": \"Hex bolt\" },\n * },\n * ],\n * });\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-model-context\n */\nexport function useModelContext(): {\n supported: boolean;\n context: ModelContextState;\n update: (params: ModelContextParams) => Promise<string | undefined>;\n} {\n const { capabilities, openaiCapabilities } = useHost();\n const reported = useMcpAppContext(\"openai/modelContext\");\n const context = useMemo(() => {\n const parsed = ModelContextSchema.safeParse(reported);\n return parsed.success ? parsed.data : undefined;\n }, [reported]);\n const update = useCallback(\n (params: ModelContextParams) => getAdaptor().updateModelContext(params),\n [],\n );\n\n return {\n supported:\n Boolean(capabilities?.updateModelContext) ||\n openaiCapabilities.modelContext,\n context,\n update,\n };\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { OpenExternalOptions } from "../bridges/types.js";
2
+ /** Function that opens a URL outside the view's iframe, returned by {@link useOpenExternal}. */
3
+ export type OpenExternalFn = (href: string, options?: OpenExternalOptions) => void;
4
+ /**
5
+ * Open an external URL through the host (e.g. in the user's browser).
6
+ *
7
+ * Use this instead of `window.open` or anchor `target="_blank"`, which are
8
+ * unreliable inside a sandboxed iframe. Hosts may transform the URL (e.g.
9
+ * ChatGPT appends a `?redirectUrl=…` parameter for allowlisted targets — pass
10
+ * `redirectUrl: false` to suppress it).
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const openExternal = useOpenExternal();
15
+ * <button onClick={() => openExternal("https://example.com")}>Open docs</button>
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-open-external
19
+ */
20
+ export declare function useOpenExternal(): OpenExternalFn;
@@ -0,0 +1,24 @@
1
+ import { useCallback } from "react";
2
+ import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Open an external URL through the host (e.g. in the user's browser).
5
+ *
6
+ * Use this instead of `window.open` or anchor `target="_blank"`, which are
7
+ * unreliable inside a sandboxed iframe. Hosts may transform the URL (e.g.
8
+ * ChatGPT appends a `?redirectUrl=…` parameter for allowlisted targets — pass
9
+ * `redirectUrl: false` to suppress it).
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const openExternal = useOpenExternal();
14
+ * <button onClick={() => openExternal("https://example.com")}>Open docs</button>
15
+ * ```
16
+ *
17
+ * @see https://docs.skybridge.tech/api-reference/use-open-external
18
+ */
19
+ export function useOpenExternal() {
20
+ const adaptor = getAdaptor();
21
+ const openExternal = useCallback((href, options) => adaptor.openExternal(href, options), [adaptor]);
22
+ return openExternal;
23
+ }
24
+ //# sourceMappingURL=use-open-external.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-open-external.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AASjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,IAAY,EAAE,OAA6B,EAAE,EAAE,CAC9C,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,EACrC,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { OpenExternalOptions } from \"../bridges/types.js\";\n\n/** Function that opens a URL outside the view's iframe, returned by {@link useOpenExternal}. */\nexport type OpenExternalFn = (\n href: string,\n options?: OpenExternalOptions,\n) => void;\n\n/**\n * Open an external URL through the host (e.g. in the user's browser).\n *\n * Use this instead of `window.open` or anchor `target=\"_blank\"`, which are\n * unreliable inside a sandboxed iframe. Hosts may transform the URL (e.g.\n * ChatGPT appends a `?redirectUrl=…` parameter for allowlisted targets — pass\n * `redirectUrl: false` to suppress it).\n *\n * @example\n * ```tsx\n * const openExternal = useOpenExternal();\n * <button onClick={() => openExternal(\"https://example.com\")}>Open docs</button>\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-open-external\n */\nexport function useOpenExternal(): OpenExternalFn {\n const adaptor = getAdaptor();\n const openExternal = useCallback(\n (href: string, options?: OpenExternalOptions) =>\n adaptor.openExternal(href, options),\n [adaptor],\n );\n\n return openExternal;\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
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 { useOpenExternal } from "./use-open-external.js";
7
+ describe("useOpenExternal", () => {
8
+ describe("apps-sdk host", () => {
9
+ let openExternalMock;
10
+ let postMessageMock;
11
+ beforeEach(() => {
12
+ openExternalMock = vi.fn();
13
+ vi.stubGlobal("openai", {
14
+ openExternal: openExternalMock,
15
+ });
16
+ vi.stubGlobal("skybridge", {});
17
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
18
+ postMessageMock = getMcpAppHostPostMessageMock();
19
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
20
+ });
21
+ afterEach(() => {
22
+ HostAdaptor.resetInstance();
23
+ McpAppBridge.resetInstance();
24
+ vi.unstubAllGlobals();
25
+ vi.resetAllMocks();
26
+ });
27
+ it("should call window.openai.openExternal even without a redirectUrl option", () => {
28
+ const { result } = renderHook(() => useOpenExternal());
29
+ const href = "https://example.com";
30
+ result.current(href);
31
+ expect(openExternalMock).toHaveBeenCalledTimes(1);
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
+ });
44
+ });
45
+ });
46
+ describe("mcp-app host", () => {
47
+ let postMessageMock;
48
+ beforeEach(() => {
49
+ vi.stubGlobal("openai", undefined);
50
+ vi.stubGlobal("skybridge", {});
51
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
52
+ postMessageMock = getMcpAppHostPostMessageMock();
53
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
54
+ });
55
+ afterEach(async () => {
56
+ HostAdaptor.resetInstance();
57
+ McpAppBridge.resetInstance();
58
+ vi.unstubAllGlobals();
59
+ vi.resetAllMocks();
60
+ });
61
+ it("should return a function that sends ui/open-link request to the MCP host", async () => {
62
+ const { result } = renderHook(() => useOpenExternal());
63
+ const href = "https://example.com";
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
+ });
72
+ });
73
+ });
74
+ });
75
+ //# sourceMappingURL=use-open-external.test.js.map
@@ -0,0 +1 @@
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\", {});\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\", {});\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,20 @@
1
+ /**
2
+ * Ask ChatGPT to open a local file by its absolute path, through the OpenAI
3
+ * MCP extensions (`openai/files/open`). ChatGPT desktop only, with a path on
4
+ * the machine that runs ChatGPT, which shows the file in its built-in viewer
5
+ * rather than in the app's own file entrypoint. Rejects with `NotSupportedError` on
6
+ * hosts that don't advertise `openai/files`: check `useHost().openaiCapabilities.files`
7
+ * before showing the control.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const { openaiCapabilities } = useHost();
12
+ * const openFile = useOpenFile();
13
+ * if (openaiCapabilities.files) {
14
+ * return <button onClick={() => openFile(part.path)}>Open in ChatGPT</button>;
15
+ * }
16
+ * ```
17
+ *
18
+ * @see https://docs.skybridge.tech/api-reference/use-open-file
19
+ */
20
+ export declare function useOpenFile(): (path: string) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ import { useCallback } from "react";
2
+ import { getAdaptor } from "../bridges/index.js";
3
+ /**
4
+ * Ask ChatGPT to open a local file by its absolute path, through the OpenAI
5
+ * MCP extensions (`openai/files/open`). ChatGPT desktop only, with a path on
6
+ * the machine that runs ChatGPT, which shows the file in its built-in viewer
7
+ * rather than in the app's own file entrypoint. Rejects with `NotSupportedError` on
8
+ * hosts that don't advertise `openai/files`: check `useHost().openaiCapabilities.files`
9
+ * before showing the control.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const { openaiCapabilities } = useHost();
14
+ * const openFile = useOpenFile();
15
+ * if (openaiCapabilities.files) {
16
+ * return <button onClick={() => openFile(part.path)}>Open in ChatGPT</button>;
17
+ * }
18
+ * ```
19
+ *
20
+ * @see https://docs.skybridge.tech/api-reference/use-open-file
21
+ */
22
+ export function useOpenFile() {
23
+ return useCallback((path) => getAdaptor().openFile(path), []);
24
+ }
25
+ //# sourceMappingURL=use-open-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-open-file.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,WAAW,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\n/**\n * Ask ChatGPT to open a local file by its absolute path, through the OpenAI\n * MCP extensions (`openai/files/open`). ChatGPT desktop only, with a path on\n * the machine that runs ChatGPT, which shows the file in its built-in viewer\n * rather than in the app's own file entrypoint. Rejects with `NotSupportedError` on\n * hosts that don't advertise `openai/files`: check `useHost().openaiCapabilities.files`\n * before showing the control.\n *\n * @example\n * ```tsx\n * const { openaiCapabilities } = useHost();\n * const openFile = useOpenFile();\n * if (openaiCapabilities.files) {\n * return <button onClick={() => openFile(part.path)}>Open in ChatGPT</button>;\n * }\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-open-file\n */\nexport function useOpenFile(): (path: string) => Promise<void> {\n return useCallback((path: string) => getAdaptor().openFile(path), []);\n}\n"]}
@@ -0,0 +1,37 @@
1
+ import type { ViewToolConfig, ViewToolHandler, ViewToolInputShape } from "../bridges/types.js";
2
+ /**
3
+ * Register a tool the view exposes to the host and model — the MCP Apps
4
+ * "app-provided tools" feature. A view tool runs *inside the view*: the host
5
+ * discovers it via `tools/list` and invokes it via `tools/call`, and the
6
+ * handler executes against the view's live state. It is the inverse of
7
+ * {@link useCallTool} (which calls a server tool). Registered on mount, removed
8
+ * on unmount; re-registered when `config.name` changes.
9
+ *
10
+ * MCP Apps only — on the ChatGPT (`window.openai`) runtime it is a no-op.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import * as z from "zod";
15
+ * import { useRegisterViewTool } from "skybridge/web";
16
+ *
17
+ * useRegisterViewTool(
18
+ * {
19
+ * name: "chess_make_move",
20
+ * description: "Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.",
21
+ * inputSchema: { san: z.string() },
22
+ * annotations: { readOnlyHint: false },
23
+ * },
24
+ * ({ san }) => {
25
+ * const move = game.move(san);
26
+ * return {
27
+ * content: [{ type: "text", text: move ? `Played ${move.san}` : "Illegal move" }],
28
+ * structuredContent: { fen: game.fen() },
29
+ * isError: !move,
30
+ * };
31
+ * },
32
+ * );
33
+ * ```
34
+ *
35
+ * @see https://docs.skybridge.tech/api-reference/use-register-view-tool
36
+ */
37
+ export declare const useRegisterViewTool: <TInput extends ViewToolInputShape = ViewToolInputShape>(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 ChatGPT (`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":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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 { useEffect, useRef } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type {\n AnyViewToolHandler,\n ViewToolConfig,\n ViewToolHandler,\n ViewToolInputShape,\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 ChatGPT (`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 ViewToolInputShape = ViewToolInputShape,\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", {});
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\", {});\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"]}
@@ -0,0 +1,24 @@
1
+ import { type RequestModalOptions } from "../bridges/index.js";
2
+ /**
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
19
+ */
20
+ export declare function useRequestModal(): {
21
+ isOpen: boolean;
22
+ params: Record<string, unknown> | undefined;
23
+ open: (opts: RequestModalOptions) => void;
24
+ };
@@ -0,0 +1,31 @@
1
+ import { useCallback } from "react";
2
+ import { getAdaptor, useHostContext, } from "../bridges/index.js";
3
+ /**
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
20
+ */
21
+ export function useRequestModal() {
22
+ const adaptor = getAdaptor();
23
+ const display = useHostContext("display");
24
+ const open = useCallback((opts) => adaptor.openModal(opts), [adaptor]);
25
+ return {
26
+ isOpen: display.mode === "modal",
27
+ params: display.params,
28
+ open,
29
+ };
30
+ }
31
+ //# sourceMappingURL=use-request-modal.js.map
@@ -0,0 +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;;;;;;;;;;;;;;;;;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"]}
@@ -0,0 +1 @@
1
+ export {};