skybridge 0.0.0-dev.d8b52a9 → 0.0.0-dev.d91554c

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 (427) hide show
  1. package/LICENSE +21 -674
  2. package/README.md +95 -265
  3. package/bin/run.js +5 -0
  4. package/dist/cli/detect-port.d.ts +18 -0
  5. package/dist/cli/detect-port.js +61 -0
  6. package/dist/cli/detect-port.js.map +1 -0
  7. package/dist/cli/header.d.ts +4 -0
  8. package/dist/cli/header.js +6 -0
  9. package/dist/cli/header.js.map +1 -0
  10. package/dist/cli/run-command.d.ts +2 -0
  11. package/dist/cli/run-command.js +43 -0
  12. package/dist/cli/run-command.js.map +1 -0
  13. package/dist/cli/telemetry.d.ts +7 -0
  14. package/dist/cli/telemetry.js +123 -0
  15. package/dist/cli/telemetry.js.map +1 -0
  16. package/dist/cli/tunnel-control-server.d.ts +9 -0
  17. package/dist/cli/tunnel-control-server.js +31 -0
  18. package/dist/cli/tunnel-control-server.js.map +1 -0
  19. package/dist/cli/tunnel-control-server.test.js +39 -0
  20. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  21. package/dist/cli/tunnel-handler.d.ts +3 -0
  22. package/dist/cli/tunnel-handler.js +48 -0
  23. package/dist/cli/tunnel-handler.js.map +1 -0
  24. package/dist/cli/tunnel-handler.test.js +105 -0
  25. package/dist/cli/tunnel-handler.test.js.map +1 -0
  26. package/dist/cli/tunnel.d.ts +57 -0
  27. package/dist/cli/tunnel.js +154 -0
  28. package/dist/cli/tunnel.js.map +1 -0
  29. package/dist/cli/tunnel.test.js +190 -0
  30. package/dist/cli/tunnel.test.js.map +1 -0
  31. package/dist/cli/types.d.ts +5 -0
  32. package/dist/cli/types.js +2 -0
  33. package/dist/cli/types.js.map +1 -0
  34. package/dist/cli/use-execute-steps.d.ts +11 -0
  35. package/dist/cli/use-execute-steps.js +36 -0
  36. package/dist/cli/use-execute-steps.js.map +1 -0
  37. package/dist/cli/use-messages.d.ts +3 -0
  38. package/dist/cli/use-messages.js +11 -0
  39. package/dist/cli/use-messages.js.map +1 -0
  40. package/dist/cli/use-nodemon.d.ts +2 -0
  41. package/dist/cli/use-nodemon.js +73 -0
  42. package/dist/cli/use-nodemon.js.map +1 -0
  43. package/dist/cli/use-open-browser.d.ts +1 -0
  44. package/dist/cli/use-open-browser.js +44 -0
  45. package/dist/cli/use-open-browser.js.map +1 -0
  46. package/dist/cli/use-tunnel.d.ts +14 -0
  47. package/dist/cli/use-tunnel.js +131 -0
  48. package/dist/cli/use-tunnel.js.map +1 -0
  49. package/dist/cli/use-typescript-check.d.ts +9 -0
  50. package/dist/cli/use-typescript-check.js +94 -0
  51. package/dist/cli/use-typescript-check.js.map +1 -0
  52. package/dist/commands/build.d.ts +9 -0
  53. package/dist/commands/build.js +102 -0
  54. package/dist/commands/build.js.map +1 -0
  55. package/dist/commands/dev.d.ts +12 -0
  56. package/dist/commands/dev.js +80 -0
  57. package/dist/commands/dev.js.map +1 -0
  58. package/dist/commands/start.d.ts +9 -0
  59. package/dist/commands/start.js +49 -0
  60. package/dist/commands/start.js.map +1 -0
  61. package/dist/commands/telemetry/disable.d.ts +5 -0
  62. package/dist/commands/telemetry/disable.js +14 -0
  63. package/dist/commands/telemetry/disable.js.map +1 -0
  64. package/dist/commands/telemetry/enable.d.ts +5 -0
  65. package/dist/commands/telemetry/enable.js +14 -0
  66. package/dist/commands/telemetry/enable.js.map +1 -0
  67. package/dist/commands/telemetry/status.d.ts +5 -0
  68. package/dist/commands/telemetry/status.js +14 -0
  69. package/dist/commands/telemetry/status.js.map +1 -0
  70. package/dist/server/asset-base-url-transform-plugin.d.ts +10 -0
  71. package/dist/server/asset-base-url-transform-plugin.js +33 -0
  72. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  73. package/dist/server/asset-base-url-transform-plugin.test.js +84 -0
  74. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  75. package/dist/server/content-helpers.d.ts +27 -0
  76. package/dist/server/content-helpers.js +46 -0
  77. package/dist/server/content-helpers.js.map +1 -0
  78. package/dist/server/content-helpers.test.js +70 -0
  79. package/dist/server/content-helpers.test.js.map +1 -0
  80. package/dist/server/express.d.ts +11 -0
  81. package/dist/server/express.js +101 -0
  82. package/dist/server/express.js.map +1 -0
  83. package/dist/server/express.test.js +430 -0
  84. package/dist/server/express.test.js.map +1 -0
  85. package/dist/server/index.d.ts +6 -0
  86. package/dist/server/index.js +4 -0
  87. package/dist/server/index.js.map +1 -0
  88. package/dist/server/inferUtilityTypes.d.ts +64 -0
  89. package/dist/server/inferUtilityTypes.js.map +1 -0
  90. package/dist/server/metric.d.ts +14 -0
  91. package/dist/server/metric.js +62 -0
  92. package/dist/server/metric.js.map +1 -0
  93. package/dist/server/middleware.d.ts +124 -0
  94. package/dist/server/middleware.js +93 -0
  95. package/dist/server/middleware.js.map +1 -0
  96. package/dist/server/middleware.test-d.js +75 -0
  97. package/dist/server/middleware.test-d.js.map +1 -0
  98. package/dist/server/middleware.test.js +493 -0
  99. package/dist/server/middleware.test.js.map +1 -0
  100. package/dist/server/server.d.ts +196 -0
  101. package/dist/server/server.js +468 -0
  102. package/dist/server/server.js.map +1 -0
  103. package/dist/{src/server → server}/templateHelper.d.ts +5 -4
  104. package/dist/server/templateHelper.js +11 -0
  105. package/dist/server/templateHelper.js.map +1 -0
  106. package/dist/server/templates.generated.d.ts +4 -0
  107. package/dist/server/templates.generated.js +47 -0
  108. package/dist/server/templates.generated.js.map +1 -0
  109. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  110. package/dist/server/tunnel-proxy-router.js +110 -0
  111. package/dist/server/tunnel-proxy-router.js.map +1 -0
  112. package/dist/server/tunnel-proxy-router.test.js +229 -0
  113. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  114. package/dist/server/viewsDevServer.d.ts +14 -0
  115. package/dist/server/viewsDevServer.js +45 -0
  116. package/dist/server/viewsDevServer.js.map +1 -0
  117. package/dist/test/utils.d.ts +127 -0
  118. package/dist/test/utils.js +247 -0
  119. package/dist/test/utils.js.map +1 -0
  120. package/dist/test/view.test.js +523 -0
  121. package/dist/test/view.test.js.map +1 -0
  122. package/dist/version.d.ts +1 -0
  123. package/dist/version.js +3 -0
  124. package/dist/version.js.map +1 -0
  125. package/dist/web/bridges/apps-sdk/adaptor.d.ts +24 -0
  126. package/dist/web/bridges/apps-sdk/adaptor.js +93 -0
  127. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  128. package/dist/web/bridges/apps-sdk/bridge.d.ts +10 -0
  129. package/dist/web/bridges/apps-sdk/bridge.js +46 -0
  130. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  131. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  132. package/dist/web/bridges/apps-sdk/index.js +5 -0
  133. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  134. package/dist/web/bridges/apps-sdk/types.d.ts +126 -0
  135. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  136. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +2 -0
  137. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +7 -0
  138. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  139. package/dist/web/bridges/get-adaptor.d.ts +2 -0
  140. package/dist/web/bridges/get-adaptor.js +8 -0
  141. package/dist/web/bridges/get-adaptor.js.map +1 -0
  142. package/dist/web/bridges/index.d.ts +5 -0
  143. package/dist/web/bridges/index.js +6 -0
  144. package/dist/web/bridges/index.js.map +1 -0
  145. package/dist/web/bridges/mcp-app/adaptor.d.ts +48 -0
  146. package/dist/web/bridges/mcp-app/adaptor.js +268 -0
  147. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  148. package/dist/web/bridges/mcp-app/bridge.d.ts +26 -0
  149. package/dist/web/bridges/mcp-app/bridge.js +102 -0
  150. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  151. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  152. package/dist/web/bridges/mcp-app/index.js +4 -0
  153. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  154. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  155. package/dist/web/bridges/mcp-app/types.js +2 -0
  156. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  157. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +7 -0
  158. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +7 -0
  159. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  160. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
  161. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  162. package/dist/web/bridges/types.d.ts +109 -0
  163. package/dist/web/bridges/types.js +2 -0
  164. package/dist/web/bridges/types.js.map +1 -0
  165. package/dist/web/bridges/use-host-context.d.ts +2 -0
  166. package/dist/web/bridges/use-host-context.js +8 -0
  167. package/dist/web/bridges/use-host-context.js.map +1 -0
  168. package/dist/web/components/modal-provider.d.ts +4 -0
  169. package/dist/web/components/modal-provider.js +45 -0
  170. package/dist/web/components/modal-provider.js.map +1 -0
  171. package/dist/web/create-store.d.ts +3 -0
  172. package/dist/web/create-store.js +38 -0
  173. package/dist/web/create-store.js.map +1 -0
  174. package/dist/web/create-store.test.js +129 -0
  175. package/dist/web/create-store.test.js.map +1 -0
  176. package/dist/web/data-llm.d.ts +14 -0
  177. package/dist/web/data-llm.js +72 -0
  178. package/dist/web/data-llm.js.map +1 -0
  179. package/dist/web/data-llm.test.js +142 -0
  180. package/dist/web/data-llm.test.js.map +1 -0
  181. package/dist/web/generate-helpers.d.ts +118 -0
  182. package/dist/{src/web/typed-hooks.js → web/generate-helpers.js} +33 -31
  183. package/dist/web/generate-helpers.js.map +1 -0
  184. package/dist/web/generate-helpers.test-d.js +209 -0
  185. package/dist/web/generate-helpers.test-d.js.map +1 -0
  186. package/dist/web/generate-helpers.test.d.ts +1 -0
  187. package/dist/web/generate-helpers.test.js +17 -0
  188. package/dist/web/generate-helpers.test.js.map +1 -0
  189. package/dist/web/helpers/state.d.ts +7 -0
  190. package/dist/web/helpers/state.js +45 -0
  191. package/dist/web/helpers/state.js.map +1 -0
  192. package/dist/web/helpers/state.test.d.ts +1 -0
  193. package/dist/web/helpers/state.test.js +53 -0
  194. package/dist/web/helpers/state.test.js.map +1 -0
  195. package/dist/web/hooks/index.d.ts +11 -0
  196. package/dist/web/hooks/index.js +12 -0
  197. package/dist/web/hooks/index.js.map +1 -0
  198. package/dist/web/hooks/test/utils.d.ts +16 -0
  199. package/dist/web/hooks/test/utils.js +64 -0
  200. package/dist/web/hooks/test/utils.js.map +1 -0
  201. package/dist/web/hooks/use-call-tool.d.ts +101 -0
  202. package/dist/{src/web → web}/hooks/use-call-tool.js +19 -19
  203. package/dist/web/hooks/use-call-tool.js.map +1 -0
  204. package/dist/web/hooks/use-call-tool.test-d.d.ts +1 -0
  205. package/dist/web/hooks/use-call-tool.test-d.js +104 -0
  206. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  207. package/dist/web/hooks/use-call-tool.test.d.ts +1 -0
  208. package/dist/{src/web → web}/hooks/use-call-tool.test.js +40 -13
  209. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  210. package/dist/web/hooks/use-display-mode.d.ts +4 -0
  211. package/dist/web/hooks/use-display-mode.js +9 -0
  212. package/dist/web/hooks/use-display-mode.js.map +1 -0
  213. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  214. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  215. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  216. package/dist/web/hooks/use-display-mode.test.d.ts +1 -0
  217. package/dist/{src/web → web}/hooks/use-display-mode.test.js +3 -2
  218. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  219. package/dist/web/hooks/use-files.d.ts +7 -0
  220. package/dist/web/hooks/use-files.js +10 -0
  221. package/dist/web/hooks/use-files.js.map +1 -0
  222. package/dist/web/hooks/use-files.test.d.ts +1 -0
  223. package/dist/web/hooks/use-files.test.js +54 -0
  224. package/dist/web/hooks/use-files.test.js.map +1 -0
  225. package/dist/web/hooks/use-layout.d.ts +22 -0
  226. package/dist/web/hooks/use-layout.js +23 -0
  227. package/dist/web/hooks/use-layout.js.map +1 -0
  228. package/dist/web/hooks/use-layout.test.d.ts +1 -0
  229. package/dist/web/hooks/use-layout.test.js +96 -0
  230. package/dist/web/hooks/use-layout.test.js.map +1 -0
  231. package/dist/web/hooks/use-open-external.d.ts +3 -0
  232. package/dist/web/hooks/use-open-external.js +8 -0
  233. package/dist/web/hooks/use-open-external.js.map +1 -0
  234. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  235. package/dist/web/hooks/use-open-external.test.js +65 -0
  236. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  237. package/dist/web/hooks/use-request-modal.d.ts +9 -0
  238. package/dist/web/hooks/use-request-modal.js +16 -0
  239. package/dist/web/hooks/use-request-modal.js.map +1 -0
  240. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  241. package/dist/web/hooks/use-request-modal.test.js +61 -0
  242. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  243. package/dist/web/hooks/use-send-follow-up-message.js +8 -0
  244. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  245. package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
  246. package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
  247. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  248. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  249. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  250. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  251. package/dist/{src/web → web}/hooks/use-tool-info.d.ts +13 -2
  252. package/dist/web/hooks/use-tool-info.js +26 -0
  253. package/dist/web/hooks/use-tool-info.js.map +1 -0
  254. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  255. package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +40 -5
  256. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  257. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  258. package/dist/web/hooks/use-tool-info.test.js +130 -0
  259. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  260. package/dist/web/hooks/use-user.d.ts +18 -0
  261. package/dist/web/hooks/use-user.js +35 -0
  262. package/dist/web/hooks/use-user.js.map +1 -0
  263. package/dist/web/hooks/use-user.test.d.ts +1 -0
  264. package/dist/web/hooks/use-user.test.js +122 -0
  265. package/dist/web/hooks/use-user.test.js.map +1 -0
  266. package/dist/web/hooks/use-view-state.d.ts +4 -0
  267. package/dist/web/hooks/use-view-state.js +32 -0
  268. package/dist/web/hooks/use-view-state.js.map +1 -0
  269. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  270. package/dist/web/hooks/use-view-state.test.js +177 -0
  271. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  272. package/dist/web/index.d.ts +7 -0
  273. package/dist/web/index.js +8 -0
  274. package/dist/web/index.js.map +1 -0
  275. package/dist/web/mount-view.d.ts +1 -0
  276. package/dist/{src/web/mount-widget.js → web/mount-view.js} +11 -3
  277. package/dist/web/mount-view.js.map +1 -0
  278. package/dist/web/plugin/data-llm.test.d.ts +1 -0
  279. package/dist/web/plugin/data-llm.test.js +81 -0
  280. package/dist/web/plugin/data-llm.test.js.map +1 -0
  281. package/dist/web/plugin/plugin.d.ts +5 -0
  282. package/dist/web/plugin/plugin.js +156 -0
  283. package/dist/web/plugin/plugin.js.map +1 -0
  284. package/dist/web/plugin/scan-views.d.ts +16 -0
  285. package/dist/web/plugin/scan-views.js +88 -0
  286. package/dist/web/plugin/scan-views.js.map +1 -0
  287. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  288. package/dist/web/plugin/scan-views.test.js +99 -0
  289. package/dist/web/plugin/scan-views.test.js.map +1 -0
  290. package/dist/web/plugin/transform-data-llm.d.ts +12 -0
  291. package/dist/web/plugin/transform-data-llm.js +96 -0
  292. package/dist/web/plugin/transform-data-llm.js.map +1 -0
  293. package/dist/web/plugin/transform-data-llm.test.d.ts +1 -0
  294. package/dist/web/plugin/transform-data-llm.test.js +81 -0
  295. package/dist/web/plugin/transform-data-llm.test.js.map +1 -0
  296. package/dist/web/plugin/validate-view.d.ts +1 -0
  297. package/dist/web/plugin/validate-view.js +9 -0
  298. package/dist/web/plugin/validate-view.js.map +1 -0
  299. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  300. package/dist/web/plugin/validate-view.test.js +24 -0
  301. package/dist/web/plugin/validate-view.test.js.map +1 -0
  302. package/dist/{src/web → web}/proxy.js +6 -2
  303. package/dist/web/proxy.js.map +1 -0
  304. package/dist/web/types.d.ts +16 -0
  305. package/dist/web/types.js +2 -0
  306. package/dist/web/types.js.map +1 -0
  307. package/package.json +81 -36
  308. package/tsconfig.base.json +33 -0
  309. package/dist/src/server/index.d.ts +0 -4
  310. package/dist/src/server/index.js +0 -3
  311. package/dist/src/server/index.js.map +0 -1
  312. package/dist/src/server/inferUtilityTypes.d.ts +0 -44
  313. package/dist/src/server/inferUtilityTypes.js.map +0 -1
  314. package/dist/src/server/server.d.ts +0 -19
  315. package/dist/src/server/server.js +0 -58
  316. package/dist/src/server/server.js.map +0 -1
  317. package/dist/src/server/templateHelper.js +0 -29
  318. package/dist/src/server/templateHelper.js.map +0 -1
  319. package/dist/src/server/templates/development.hbs +0 -12
  320. package/dist/src/server/templates/production.hbs +0 -6
  321. package/dist/src/server/widgetsDevServer.d.ts +0 -12
  322. package/dist/src/server/widgetsDevServer.js +0 -39
  323. package/dist/src/server/widgetsDevServer.js.map +0 -1
  324. package/dist/src/test/utils.d.ts +0 -28
  325. package/dist/src/test/utils.js +0 -43
  326. package/dist/src/test/utils.js.map +0 -1
  327. package/dist/src/test/widget.test.js +0 -90
  328. package/dist/src/test/widget.test.js.map +0 -1
  329. package/dist/src/web/hooks/index.d.ts +0 -14
  330. package/dist/src/web/hooks/index.js +0 -15
  331. package/dist/src/web/hooks/index.js.map +0 -1
  332. package/dist/src/web/hooks/use-call-tool.d.ts +0 -62
  333. package/dist/src/web/hooks/use-call-tool.js.map +0 -1
  334. package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
  335. package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
  336. package/dist/src/web/hooks/use-display-mode.js +0 -7
  337. package/dist/src/web/hooks/use-display-mode.js.map +0 -1
  338. package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
  339. package/dist/src/web/hooks/use-files.d.ts +0 -10
  340. package/dist/src/web/hooks/use-files.js +0 -7
  341. package/dist/src/web/hooks/use-files.js.map +0 -1
  342. package/dist/src/web/hooks/use-files.test.js +0 -29
  343. package/dist/src/web/hooks/use-files.test.js.map +0 -1
  344. package/dist/src/web/hooks/use-locale.d.ts +0 -1
  345. package/dist/src/web/hooks/use-locale.js +0 -5
  346. package/dist/src/web/hooks/use-locale.js.map +0 -1
  347. package/dist/src/web/hooks/use-locale.test.js +0 -21
  348. package/dist/src/web/hooks/use-locale.test.js.map +0 -1
  349. package/dist/src/web/hooks/use-open-external.d.ts +0 -1
  350. package/dist/src/web/hooks/use-open-external.js +0 -6
  351. package/dist/src/web/hooks/use-open-external.js.map +0 -1
  352. package/dist/src/web/hooks/use-open-external.test.js +0 -24
  353. package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
  354. package/dist/src/web/hooks/use-openai-global.d.ts +0 -2
  355. package/dist/src/web/hooks/use-openai-global.js +0 -23
  356. package/dist/src/web/hooks/use-openai-global.js.map +0 -1
  357. package/dist/src/web/hooks/use-request-modal.d.ts +0 -6
  358. package/dist/src/web/hooks/use-request-modal.js +0 -9
  359. package/dist/src/web/hooks/use-request-modal.js.map +0 -1
  360. package/dist/src/web/hooks/use-request-modal.test.js +0 -24
  361. package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
  362. package/dist/src/web/hooks/use-send-follow-up-message.js +0 -11
  363. package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
  364. package/dist/src/web/hooks/use-theme.d.ts +0 -1
  365. package/dist/src/web/hooks/use-theme.js +0 -5
  366. package/dist/src/web/hooks/use-theme.js.map +0 -1
  367. package/dist/src/web/hooks/use-theme.test.js +0 -26
  368. package/dist/src/web/hooks/use-theme.test.js.map +0 -1
  369. package/dist/src/web/hooks/use-tool-info.js +0 -22
  370. package/dist/src/web/hooks/use-tool-info.js.map +0 -1
  371. package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
  372. package/dist/src/web/hooks/use-tool-info.test.js +0 -59
  373. package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
  374. package/dist/src/web/hooks/use-tool-output.d.ts +0 -4
  375. package/dist/src/web/hooks/use-tool-output.js +0 -9
  376. package/dist/src/web/hooks/use-tool-output.js.map +0 -1
  377. package/dist/src/web/hooks/use-tool-response-metadata.d.ts +0 -4
  378. package/dist/src/web/hooks/use-tool-response-metadata.js +0 -8
  379. package/dist/src/web/hooks/use-tool-response-metadata.js.map +0 -1
  380. package/dist/src/web/hooks/use-user-agent.d.ts +0 -1
  381. package/dist/src/web/hooks/use-user-agent.js +0 -5
  382. package/dist/src/web/hooks/use-user-agent.js.map +0 -1
  383. package/dist/src/web/hooks/use-user-agent.test.js +0 -31
  384. package/dist/src/web/hooks/use-user-agent.test.js.map +0 -1
  385. package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
  386. package/dist/src/web/hooks/use-widget-state.js +0 -30
  387. package/dist/src/web/hooks/use-widget-state.js.map +0 -1
  388. package/dist/src/web/hooks/use-widget-state.test.js +0 -60
  389. package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
  390. package/dist/src/web/index.d.ts +0 -5
  391. package/dist/src/web/index.js +0 -6
  392. package/dist/src/web/index.js.map +0 -1
  393. package/dist/src/web/mount-widget.d.ts +0 -1
  394. package/dist/src/web/mount-widget.js.map +0 -1
  395. package/dist/src/web/plugin.d.ts +0 -2
  396. package/dist/src/web/plugin.js +0 -28
  397. package/dist/src/web/plugin.js.map +0 -1
  398. package/dist/src/web/proxy.js.map +0 -1
  399. package/dist/src/web/typed-hooks.d.ts +0 -107
  400. package/dist/src/web/typed-hooks.js.map +0 -1
  401. package/dist/src/web/typed-hooks.test-d.js +0 -72
  402. package/dist/src/web/typed-hooks.test-d.js.map +0 -1
  403. package/dist/src/web/typed-hooks.test.js +0 -10
  404. package/dist/src/web/typed-hooks.test.js.map +0 -1
  405. package/dist/src/web/types.d.ts +0 -119
  406. package/dist/src/web/types.js.map +0 -1
  407. package/dist/vitest.config.d.ts +0 -2
  408. package/dist/vitest.config.js +0 -8
  409. package/dist/vitest.config.js.map +0 -1
  410. /package/dist/{src/test/widget.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  411. /package/dist/{src/web/hooks/use-call-tool.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  412. /package/dist/{src/web/hooks/use-display-mode.test.d.ts → cli/tunnel.test.d.ts} +0 -0
  413. /package/dist/{src/web/hooks/use-files.test.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
  414. /package/dist/{src/web/hooks/use-locale.test.d.ts → server/content-helpers.test.d.ts} +0 -0
  415. /package/dist/{src/web/hooks/use-open-external.test.d.ts → server/express.test.d.ts} +0 -0
  416. /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
  417. /package/dist/{src/web/hooks/use-request-modal.test.d.ts → server/middleware.test-d.d.ts} +0 -0
  418. /package/dist/{src/web/hooks/use-theme.test.d.ts → server/middleware.test.d.ts} +0 -0
  419. /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → server/tunnel-proxy-router.test.d.ts} +0 -0
  420. /package/dist/{src/web/hooks/use-tool-info.test.d.ts → test/view.test.d.ts} +0 -0
  421. /package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -0
  422. /package/dist/{src/web/hooks/use-user-agent.test.d.ts → web/bridges/mcp-app/use-mcp-app-context.test.d.ts} +0 -0
  423. /package/dist/{src/web/hooks/use-widget-state.test.d.ts → web/create-store.test.d.ts} +0 -0
  424. /package/dist/{src/web/typed-hooks.test-d.d.ts → web/data-llm.test.d.ts} +0 -0
  425. /package/dist/{src/web/typed-hooks.test.d.ts → web/generate-helpers.test-d.d.ts} +0 -0
  426. /package/dist/{src/web → web}/hooks/use-send-follow-up-message.d.ts +0 -0
  427. /package/dist/{src/web → web}/proxy.d.ts +0 -0
@@ -0,0 +1,8 @@
1
+ import { useCallback } from "react";
2
+ import { getAdaptor } from "../bridges/index.js";
3
+ export function useSetOpenInAppUrl() {
4
+ const adaptor = getAdaptor();
5
+ const setOpenInAppUrl = useCallback((href) => adaptor.setOpenInAppUrl(href), [adaptor]);
6
+ return setOpenInAppUrl;
7
+ }
8
+ //# sourceMappingURL=use-set-open-in-app-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-set-open-in-app-url.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,EAC/C,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\n\nexport function useSetOpenInAppUrl() {\n const adaptor = getAdaptor();\n const setOpenInAppUrl = useCallback(\n (href: string) => adaptor.setOpenInAppUrl(href),\n [adaptor],\n );\n\n return setOpenInAppUrl;\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import { renderHook } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { AppsSdkAdaptor } from "../bridges/apps-sdk/adaptor.js";
4
+ import { useSetOpenInAppUrl } from "./use-set-open-in-app-url.js";
5
+ describe("useSetOpenInAppUrl", () => {
6
+ describe("apps-sdk host", () => {
7
+ let setOpenInAppUrlMock;
8
+ beforeEach(() => {
9
+ setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);
10
+ vi.stubGlobal("openai", {
11
+ setOpenInAppUrl: setOpenInAppUrlMock,
12
+ });
13
+ vi.stubGlobal("skybridge", {
14
+ hostType: "apps-sdk",
15
+ serverUrl: "https://example.com",
16
+ });
17
+ });
18
+ afterEach(() => {
19
+ vi.unstubAllGlobals();
20
+ vi.resetAllMocks();
21
+ AppsSdkAdaptor.resetInstance();
22
+ });
23
+ it("should return a function that calls window.openai.setOpenInAppUrl with the href", async () => {
24
+ const { result } = renderHook(() => useSetOpenInAppUrl());
25
+ const href = "https://example.com/path";
26
+ await result.current(href);
27
+ expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);
28
+ expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });
29
+ });
30
+ it("should throw an error when href is empty", () => {
31
+ const { result } = renderHook(() => useSetOpenInAppUrl());
32
+ expect(() => result.current("")).toThrow("The href parameter is required.");
33
+ });
34
+ it("should call setOpenInAppUrl when href origin differs from serverUrl origin", async () => {
35
+ const { result } = renderHook(() => useSetOpenInAppUrl());
36
+ const href = "https://different-domain.com/path";
37
+ await result.current(href);
38
+ expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);
39
+ expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });
40
+ });
41
+ });
42
+ });
43
+ //# sourceMappingURL=use-set-open-in-app-url.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,IAAI,mBAA6C,CAAC;QAElD,UAAU,CAAC,GAAG,EAAE;YACd,mBAAmB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YAC3D,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACtB,eAAe,EAAE,mBAAmB;aACrC,CAAC,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE;gBACzB,QAAQ,EAAE,UAAU;gBACpB,SAAS,EAAE,qBAAqB;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACtB,EAAE,CAAC,aAAa,EAAE,CAAC;YACnB,cAAc,CAAC,aAAa,EAAE,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;YAC/F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,IAAI,GAAG,0BAA0B,CAAC;YACxC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE3B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CACtC,iCAAiC,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;YAC1F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE1D,MAAM,IAAI,GAAG,mCAAmC,CAAC;YACjD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE3B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { AppsSdkAdaptor } from \"../bridges/apps-sdk/adaptor.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", {\n hostType: \"apps-sdk\",\n serverUrl: \"https://example.com\",\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n AppsSdkAdaptor.resetInstance();\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should throw an error when href is empty\", () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n expect(() => result.current(\"\")).toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n});\n"]}
@@ -1,6 +1,16 @@
1
1
  import type { UnknownObject } from "../types.js";
2
+ export type ToolIdleState = {
3
+ status: "idle";
4
+ isIdle: true;
5
+ isPending: false;
6
+ isSuccess: false;
7
+ input: undefined;
8
+ output: undefined;
9
+ responseMetadata: undefined;
10
+ };
2
11
  export type ToolPendingState<ToolInput extends UnknownObject> = {
3
12
  status: "pending";
13
+ isIdle: false;
4
14
  isPending: true;
5
15
  isSuccess: false;
6
16
  input: ToolInput;
@@ -9,17 +19,18 @@ export type ToolPendingState<ToolInput extends UnknownObject> = {
9
19
  };
10
20
  export type ToolSuccessState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = {
11
21
  status: "success";
22
+ isIdle: false;
12
23
  isPending: false;
13
24
  isSuccess: true;
14
25
  input: ToolInput;
15
26
  output: ToolOutput;
16
27
  responseMetadata: ToolResponseMetadata;
17
28
  };
18
- type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = ToolPendingState<ToolInput> | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;
29
+ export type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = ToolIdleState | ToolPendingState<ToolInput> | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;
19
30
  type ToolSignature = {
20
31
  input: UnknownObject;
21
32
  output: UnknownObject;
22
33
  responseMetadata: UnknownObject;
23
34
  };
24
- export declare function useToolInfo<TS extends Partial<ToolSignature> = {}>(): ToolState<UnknownObject & TS["input"], UnknownObject & TS["output"], UnknownObject & TS["responseMetadata"]>;
35
+ export declare function useToolInfo<TS extends Partial<ToolSignature> = Record<string, never>>(): ToolState<UnknownObject & TS["input"], UnknownObject & TS["output"], UnknownObject & TS["responseMetadata"]>;
25
36
  export {};
@@ -0,0 +1,26 @@
1
+ import { useHostContext } from "../bridges/index.js";
2
+ function deriveStatus(input, output, responseMetadata) {
3
+ if (input === null) {
4
+ return "idle";
5
+ }
6
+ if (output === null && responseMetadata === null) {
7
+ return "pending";
8
+ }
9
+ return "success";
10
+ }
11
+ export function useToolInfo() {
12
+ const input = useHostContext("toolInput");
13
+ const output = useHostContext("toolOutput");
14
+ const responseMetadata = useHostContext("toolResponseMetadata");
15
+ const status = deriveStatus(input, output, responseMetadata);
16
+ return {
17
+ input,
18
+ status,
19
+ isIdle: status === "idle",
20
+ isPending: status === "pending",
21
+ isSuccess: status === "success",
22
+ output,
23
+ responseMetadata,
24
+ };
25
+ }
26
+ //# sourceMappingURL=use-tool-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tool-info.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAoDrD,SAAS,YAAY,CACnB,KAAqC,EACrC,MAAsC,EACtC,gBAAgD;IAEhD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW;IAGzB,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAM7D,OAAO;QACL,KAAK;QACL,MAAM;QACN,MAAM,EAAE,MAAM,KAAK,MAAM;QACzB,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,MAAM;QACN,gBAAgB;KACqB,CAAC;AAC1C,CAAC","sourcesContent":["import { useHostContext } from \"../bridges/index.js\";\nimport type { UnknownObject } from \"../types.js\";\n\nexport type ToolIdleState = {\n status: \"idle\";\n isIdle: true;\n isPending: false;\n isSuccess: false;\n input: undefined;\n output: undefined;\n responseMetadata: undefined;\n};\n\nexport type ToolPendingState<ToolInput extends UnknownObject> = {\n status: \"pending\";\n isIdle: false;\n isPending: true;\n isSuccess: false;\n input: ToolInput;\n output: undefined;\n responseMetadata: undefined;\n};\n\nexport type ToolSuccessState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> = {\n status: \"success\";\n isIdle: false;\n isPending: false;\n isSuccess: true;\n input: ToolInput;\n output: ToolOutput;\n responseMetadata: ToolResponseMetadata;\n};\n\nexport type ToolState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> =\n | ToolIdleState\n | ToolPendingState<ToolInput>\n | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;\n\ntype ToolSignature = {\n input: UnknownObject;\n output: UnknownObject;\n responseMetadata: UnknownObject;\n};\n\nfunction deriveStatus(\n input: Record<string, unknown> | null,\n output: Record<string, unknown> | null,\n responseMetadata: Record<string, unknown> | null,\n): \"idle\" | \"pending\" | \"success\" {\n if (input === null) {\n return \"idle\";\n }\n if (output === null && responseMetadata === null) {\n return \"pending\";\n }\n return \"success\";\n}\n\nexport function useToolInfo<\n TS extends Partial<ToolSignature> = Record<string, never>,\n>() {\n const input = useHostContext(\"toolInput\");\n const output = useHostContext(\"toolOutput\");\n const responseMetadata = useHostContext(\"toolResponseMetadata\");\n\n const status = deriveStatus(input, output, responseMetadata);\n\n type Input = UnknownObject & TS[\"input\"];\n type Output = UnknownObject & TS[\"output\"];\n type Metadata = UnknownObject & TS[\"responseMetadata\"];\n\n return {\n input,\n status,\n isIdle: status === \"idle\",\n isPending: status === \"pending\",\n isSuccess: status === \"success\",\n output,\n responseMetadata,\n } as ToolState<Input, Output, Metadata>;\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,4 @@
1
1
  import { expectTypeOf, test } from "vitest";
2
- import { renderHook } from "@testing-library/react";
3
2
  import { useToolInfo } from "./use-tool-info.js";
4
3
  test("useToolInfo - TypeScript typing", () => {
5
4
  test("should have correct types when no generic parameter is provided", () => {
@@ -7,27 +6,46 @@ test("useToolInfo - TypeScript typing", () => {
7
6
  expectTypeOf(result.status);
8
7
  expectTypeOf(result.isPending);
9
8
  expectTypeOf(result.isSuccess);
9
+ expectTypeOf(result.isIdle);
10
10
  expectTypeOf(result.input);
11
11
  });
12
12
  test("should correctly type input, output, and responseMetadata with explicit ToolSignature", () => {
13
13
  const result = useToolInfo();
14
- expectTypeOf(result.input);
14
+ // When idle, input should be undefined
15
+ if (result.status === "idle") {
16
+ expectTypeOf(result.input);
17
+ expectTypeOf(result.output);
18
+ expectTypeOf(result.responseMetadata);
19
+ }
15
20
  // When pending, output and responseMetadata should be undefined
16
21
  if (result.status === "pending") {
22
+ expectTypeOf(result.input);
17
23
  expectTypeOf(result.output);
18
24
  expectTypeOf(result.responseMetadata);
19
25
  }
20
26
  // When success, output and responseMetadata should be defined
21
27
  if (result.status === "success") {
28
+ expectTypeOf(result.input);
22
29
  expectTypeOf(result.output);
23
30
  expectTypeOf(result.responseMetadata);
24
31
  }
25
32
  });
26
33
  test("should correctly narrow types based on status discriminated union", () => {
27
34
  const result = useToolInfo();
28
- // Test type narrowing
35
+ // Test type narrowing for idle
36
+ if (result.isIdle) {
37
+ expectTypeOf(result.status);
38
+ expectTypeOf(result.isIdle);
39
+ expectTypeOf(result.isPending);
40
+ expectTypeOf(result.isSuccess);
41
+ expectTypeOf(result.input);
42
+ expectTypeOf(result.output);
43
+ expectTypeOf(result.responseMetadata);
44
+ }
45
+ // Test type narrowing for pending
29
46
  if (result.isPending) {
30
47
  expectTypeOf(result.status);
48
+ expectTypeOf(result.isIdle);
31
49
  expectTypeOf(result.isPending);
32
50
  expectTypeOf(result.isSuccess);
33
51
  expectTypeOf(result.output);
@@ -35,13 +53,23 @@ test("useToolInfo - TypeScript typing", () => {
35
53
  }
36
54
  if (result.isSuccess) {
37
55
  expectTypeOf(result.status);
56
+ expectTypeOf(result.isIdle);
38
57
  expectTypeOf(result.isPending);
39
58
  expectTypeOf(result.isSuccess);
40
59
  expectTypeOf(result.output);
41
60
  expectTypeOf(result.responseMetadata);
42
61
  }
62
+ if (result.status === "idle") {
63
+ expectTypeOf(result.isIdle);
64
+ expectTypeOf(result.isPending);
65
+ expectTypeOf(result.isSuccess);
66
+ expectTypeOf(result.input);
67
+ expectTypeOf(result.output);
68
+ expectTypeOf(result.responseMetadata);
69
+ }
43
70
  if (result.status === "pending") {
44
71
  expectTypeOf(result.input);
72
+ expectTypeOf(result.isIdle);
45
73
  expectTypeOf(result.isPending);
46
74
  expectTypeOf(result.isSuccess);
47
75
  expectTypeOf(result.output);
@@ -49,6 +77,7 @@ test("useToolInfo - TypeScript typing", () => {
49
77
  }
50
78
  if (result.status === "success") {
51
79
  expectTypeOf(result.input);
80
+ expectTypeOf(result.isIdle);
52
81
  expectTypeOf(result.isPending);
53
82
  expectTypeOf(result.isSuccess);
54
83
  expectTypeOf(result.output);
@@ -57,7 +86,10 @@ test("useToolInfo - TypeScript typing", () => {
57
86
  });
58
87
  test("should handle partial ToolSignature with only input specified", () => {
59
88
  const result = useToolInfo();
60
- expectTypeOf(result.input);
89
+ // Input can be TestInput or undefined (when idle)
90
+ if (result.status === "pending" || result.status === "success") {
91
+ expectTypeOf(result.input);
92
+ }
61
93
  if (result.status === "success") {
62
94
  expectTypeOf(result.output);
63
95
  expectTypeOf(result.responseMetadata);
@@ -65,7 +97,10 @@ test("useToolInfo - TypeScript typing", () => {
65
97
  });
66
98
  test("should handle ToolSignature with only output specified", () => {
67
99
  const result = useToolInfo();
68
- expectTypeOf(result.input);
100
+ // Input can be Record<string, unknown> or undefined (when idle)
101
+ if (result.status === "pending" || result.status === "success") {
102
+ expectTypeOf(result.input);
103
+ }
69
104
  if (result.status === "success") {
70
105
  expectTypeOf(result.output);
71
106
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tool-info.test-d.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { useToolInfo } from \"./use-tool-info.js\";\n\ntest(\"useToolInfo - TypeScript typing\", () => {\n test(\"should have correct types when no generic parameter is provided\", () => {\n const result = useToolInfo();\n\n expectTypeOf<\"idle\" | \"pending\" | \"success\">(result.status);\n expectTypeOf<boolean>(result.isPending);\n expectTypeOf<boolean>(result.isSuccess);\n expectTypeOf<boolean>(result.isIdle);\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n });\n\n test(\"should correctly type input, output, and responseMetadata with explicit ToolSignature\", () => {\n type TestInput = { name: string; args: { name: string } };\n type TestOutput = { name: string; color: string };\n type TestMetadata = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // When idle, input should be undefined\n if (result.status === \"idle\") {\n expectTypeOf<undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n // When pending, output and responseMetadata should be undefined\n if (result.status === \"pending\") {\n expectTypeOf<TestInput>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n // When success, output and responseMetadata should be defined\n if (result.status === \"success\") {\n expectTypeOf<TestInput>(result.input);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should correctly narrow types based on status discriminated union\", () => {\n type TestInput = { query: string };\n type TestOutput = { result: string };\n type TestMetadata = { timestamp: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // Test type narrowing for idle\n if (result.isIdle) {\n expectTypeOf<\"idle\">(result.status);\n expectTypeOf<true>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n // Test type narrowing for pending\n if (result.isPending) {\n expectTypeOf<\"pending\">(result.status);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.isSuccess) {\n expectTypeOf<\"success\">(result.status);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n\n if (result.status === \"idle\") {\n expectTypeOf<true>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.status === \"pending\") {\n expectTypeOf<TestInput>(result.input);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestInput>(result.input);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should handle partial ToolSignature with only input specified\", () => {\n type TestInput = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n }>();\n\n // Input can be TestInput or undefined (when idle)\n if (result.status === \"pending\" || result.status === \"success\") {\n expectTypeOf<TestInput>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<Record<string, unknown>>(result.output);\n expectTypeOf<Record<string, unknown>>(result.responseMetadata);\n }\n });\n\n test(\"should handle ToolSignature with only output specified\", () => {\n type TestOutput = { data: string[] };\n\n const result = useToolInfo<{\n output: TestOutput;\n }>();\n\n // Input can be Record<string, unknown> or undefined (when idle)\n if (result.status === \"pending\" || result.status === \"success\") {\n expectTypeOf<Record<string, unknown>>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestOutput>(result.output);\n }\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,130 @@
1
+ import { act, fireEvent, renderHook, waitFor } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent, } from "../bridges/apps-sdk/index.js";
4
+ import { McpAppAdaptor, McpAppBridge } from "../bridges/mcp-app/index.js";
5
+ import { fireToolInputNotification, fireToolResultNotification, getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
6
+ import { useToolInfo } from "./use-tool-info.js";
7
+ describe("useToolInfo", () => {
8
+ describe("apps-sdk host", () => {
9
+ let OpenaiMock;
10
+ beforeEach(() => {
11
+ OpenaiMock = {
12
+ toolInput: { name: "pokemon", args: { name: "pikachu" } },
13
+ toolOutput: null,
14
+ toolResponseMetadata: null,
15
+ };
16
+ vi.stubGlobal("openai", OpenaiMock);
17
+ vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
18
+ });
19
+ afterEach(() => {
20
+ vi.unstubAllGlobals();
21
+ vi.resetAllMocks();
22
+ });
23
+ it("should return toolInput on initial mount window.openai", () => {
24
+ const { result } = renderHook(() => useToolInfo());
25
+ expect(result.current).toMatchObject({
26
+ input: { name: "pokemon", args: { name: "pikachu" } },
27
+ status: "pending",
28
+ isIdle: false,
29
+ isPending: true,
30
+ isSuccess: false,
31
+ });
32
+ });
33
+ it("should eventually return tool output and response metadata once tool call completes", async () => {
34
+ const toolOutput = {
35
+ name: "pikachu",
36
+ color: "yellow",
37
+ description: "When several of these POKéMON gather, their\felectricity could build and cause lightning storms.",
38
+ };
39
+ const toolResponseMetadata = { id: 12 };
40
+ const { result } = renderHook(() => useToolInfo());
41
+ act(() => {
42
+ OpenaiMock.toolOutput = toolOutput;
43
+ OpenaiMock.toolResponseMetadata = toolResponseMetadata;
44
+ fireEvent(window, new SetGlobalsEvent(SET_GLOBALS_EVENT_TYPE, {
45
+ detail: {
46
+ globals: {
47
+ toolOutput,
48
+ toolResponseMetadata,
49
+ },
50
+ },
51
+ }));
52
+ });
53
+ await waitFor(() => {
54
+ expect(result.current).toMatchObject({
55
+ status: "success",
56
+ isIdle: false,
57
+ isPending: false,
58
+ isSuccess: true,
59
+ output: toolOutput,
60
+ responseMetadata: toolResponseMetadata,
61
+ });
62
+ });
63
+ });
64
+ });
65
+ describe("mcp-app host", () => {
66
+ beforeEach(() => {
67
+ vi.stubGlobal("parent", { postMessage: getMcpAppHostPostMessageMock() });
68
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
69
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
70
+ });
71
+ afterEach(async () => {
72
+ vi.unstubAllGlobals();
73
+ vi.resetAllMocks();
74
+ McpAppBridge.resetInstance();
75
+ McpAppAdaptor.resetInstance();
76
+ });
77
+ it("should return idle state initially when tool input is not yet set", async () => {
78
+ const { result } = renderHook(() => useToolInfo());
79
+ await waitFor(() => {
80
+ expect(result.current).toMatchObject({
81
+ status: "idle",
82
+ isIdle: true,
83
+ isPending: false,
84
+ isSuccess: false,
85
+ input: null,
86
+ output: null,
87
+ responseMetadata: null,
88
+ });
89
+ });
90
+ });
91
+ it("should return pending state with tool input from tool-input notification", async () => {
92
+ const { result } = renderHook(() => useToolInfo());
93
+ act(() => {
94
+ fireToolInputNotification({ name: "pokemon", query: "pikachu" });
95
+ });
96
+ await waitFor(() => {
97
+ expect(result.current).toMatchObject({
98
+ status: "pending",
99
+ isIdle: false,
100
+ isPending: true,
101
+ isSuccess: false,
102
+ input: { name: "pokemon", query: "pikachu" },
103
+ });
104
+ });
105
+ });
106
+ it("should return success state with output from tool-result notification", async () => {
107
+ const { result } = renderHook(() => useToolInfo());
108
+ act(() => {
109
+ fireToolInputNotification({ name: "pokemon", query: "pikachu" });
110
+ fireToolResultNotification({
111
+ content: [{ type: "text", text: "Pikachu data" }],
112
+ structuredContent: { name: "pikachu", color: "yellow" },
113
+ _meta: { requestId: "123" },
114
+ });
115
+ });
116
+ await waitFor(() => {
117
+ expect(result.current).toMatchObject({
118
+ status: "success",
119
+ isIdle: false,
120
+ isPending: false,
121
+ isSuccess: true,
122
+ input: { name: "pokemon", query: "pikachu" },
123
+ output: { name: "pikachu", color: "yellow" },
124
+ responseMetadata: { requestId: "123" },
125
+ });
126
+ });
127
+ });
128
+ });
129
+ });
130
+ //# sourceMappingURL=use-tool-info.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tool-info.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, fireEvent, renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport {\n type AppsSdkContext,\n SET_GLOBALS_EVENT_TYPE,\n SetGlobalsEvent,\n} from \"../bridges/apps-sdk/index.js\";\nimport { McpAppAdaptor, McpAppBridge } from \"../bridges/mcp-app/index.js\";\nimport {\n fireToolInputNotification,\n fireToolResultNotification,\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useToolInfo } from \"./use-tool-info.js\";\n\ndescribe(\"useToolInfo\", () => {\n describe(\"apps-sdk host\", () => {\n let OpenaiMock: Pick<\n AppsSdkContext,\n \"toolInput\" | \"toolOutput\" | \"toolResponseMetadata\"\n >;\n\n beforeEach(() => {\n OpenaiMock = {\n toolInput: { name: \"pokemon\", args: { name: \"pikachu\" } },\n toolOutput: null,\n toolResponseMetadata: null,\n };\n vi.stubGlobal(\"openai\", OpenaiMock);\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return toolInput on initial mount window.openai\", () => {\n const { result } = renderHook(() => useToolInfo());\n\n expect(result.current).toMatchObject({\n input: { name: \"pokemon\", args: { name: \"pikachu\" } },\n status: \"pending\",\n isIdle: false,\n isPending: true,\n isSuccess: false,\n });\n });\n\n it(\"should eventually return tool output and response metadata once tool call completes\", async () => {\n const toolOutput = {\n name: \"pikachu\",\n color: \"yellow\",\n description:\n \"When several of these POKéMON gather, their\\felectricity could build and cause lightning storms.\",\n };\n const toolResponseMetadata = { id: 12 };\n const { result } = renderHook(() => useToolInfo());\n\n act(() => {\n OpenaiMock.toolOutput = toolOutput;\n OpenaiMock.toolResponseMetadata = toolResponseMetadata;\n fireEvent(\n window,\n new SetGlobalsEvent(SET_GLOBALS_EVENT_TYPE, {\n detail: {\n globals: {\n toolOutput,\n toolResponseMetadata,\n },\n },\n }),\n );\n });\n\n await waitFor(() => {\n expect(result.current).toMatchObject({\n status: \"success\",\n isIdle: false,\n isPending: false,\n isSuccess: true,\n output: toolOutput,\n responseMetadata: toolResponseMetadata,\n });\n });\n });\n });\n\n describe(\"mcp-app host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"parent\", { postMessage: getMcpAppHostPostMessageMock() });\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n });\n\n afterEach(async () => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n McpAppBridge.resetInstance();\n McpAppAdaptor.resetInstance();\n });\n\n it(\"should return idle state initially when tool input is not yet set\", async () => {\n const { result } = renderHook(() => useToolInfo());\n\n await waitFor(() => {\n expect(result.current).toMatchObject({\n status: \"idle\",\n isIdle: true,\n isPending: false,\n isSuccess: false,\n input: null,\n output: null,\n responseMetadata: null,\n });\n });\n });\n\n it(\"should return pending state with tool input from tool-input notification\", async () => {\n const { result } = renderHook(() => useToolInfo());\n\n act(() => {\n fireToolInputNotification({ name: \"pokemon\", query: \"pikachu\" });\n });\n\n await waitFor(() => {\n expect(result.current).toMatchObject({\n status: \"pending\",\n isIdle: false,\n isPending: true,\n isSuccess: false,\n input: { name: \"pokemon\", query: \"pikachu\" },\n });\n });\n });\n\n it(\"should return success state with output from tool-result notification\", async () => {\n const { result } = renderHook(() => useToolInfo());\n\n act(() => {\n fireToolInputNotification({ name: \"pokemon\", query: \"pikachu\" });\n fireToolResultNotification({\n content: [{ type: \"text\", text: \"Pikachu data\" }],\n structuredContent: { name: \"pikachu\", color: \"yellow\" },\n _meta: { requestId: \"123\" },\n });\n });\n\n await waitFor(() => {\n expect(result.current).toMatchObject({\n status: \"success\",\n isIdle: false,\n isPending: false,\n isSuccess: true,\n input: { name: \"pokemon\", query: \"pikachu\" },\n output: { name: \"pikachu\", color: \"yellow\" },\n responseMetadata: { requestId: \"123\" },\n });\n });\n });\n });\n});\n"]}
@@ -0,0 +1,18 @@
1
+ import { type UserAgent } from "../bridges/index.js";
2
+ export type UserState = {
3
+ locale: string;
4
+ userAgent: UserAgent;
5
+ };
6
+ /**
7
+ * Hook for accessing session-stable user information.
8
+ * These values are set once at initialization and do not change during the session.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const { locale, userAgent } = useUser();
13
+ *
14
+ * // Access device type
15
+ * const isMobile = userAgent.device.type === "mobile";
16
+ * ```
17
+ */
18
+ export declare function useUser(): UserState;
@@ -0,0 +1,35 @@
1
+ import { useHostContext } from "../bridges/index.js";
2
+ const DEFAULT_LOCALE = "en-US";
3
+ /**
4
+ * Normalizes a locale string to canonical BCP 47 format using {@link Intl.Locale}.
5
+ *
6
+ * Handles underscored identifiers returned by the ChatGPT mobile app (e.g. "fr_FR" → "fr-FR"),
7
+ * incorrect casing (e.g. "en-us" → "en-US"), and complex subtags (e.g. "zh_Hans_CN" → "zh-Hans-CN").
8
+ * Falls back to "en-US" if the locale is invalid.
9
+ */
10
+ function normalizeLocale(locale) {
11
+ try {
12
+ return new Intl.Locale(locale.replace(/_/g, "-")).toString();
13
+ }
14
+ catch {
15
+ return DEFAULT_LOCALE;
16
+ }
17
+ }
18
+ /**
19
+ * Hook for accessing session-stable user information.
20
+ * These values are set once at initialization and do not change during the session.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const { locale, userAgent } = useUser();
25
+ *
26
+ * // Access device type
27
+ * const isMobile = userAgent.device.type === "mobile";
28
+ * ```
29
+ */
30
+ export function useUser() {
31
+ const rawLocale = useHostContext("locale");
32
+ const userAgent = useHostContext("userAgent");
33
+ return { locale: normalizeLocale(rawLocale), userAgent };
34
+ }
35
+ //# sourceMappingURL=use-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-user.js","sourceRoot":"","sources":["../../../src/web/hooks/use-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAOrE,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAE9C,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;AAC3D,CAAC","sourcesContent":["import { type UserAgent, useHostContext } from \"../bridges/index.js\";\n\nexport type UserState = {\n locale: string;\n userAgent: UserAgent;\n};\n\nconst DEFAULT_LOCALE = \"en-US\";\n\n/**\n * Normalizes a locale string to canonical BCP 47 format using {@link Intl.Locale}.\n *\n * Handles underscored identifiers returned by the ChatGPT mobile app (e.g. \"fr_FR\" → \"fr-FR\"),\n * incorrect casing (e.g. \"en-us\" → \"en-US\"), and complex subtags (e.g. \"zh_Hans_CN\" → \"zh-Hans-CN\").\n * Falls back to \"en-US\" if the locale is invalid.\n */\nfunction normalizeLocale(locale: string): string {\n try {\n return new Intl.Locale(locale.replace(/_/g, \"-\")).toString();\n } catch {\n return DEFAULT_LOCALE;\n }\n}\n\n/**\n * Hook for accessing session-stable user information.\n * These values are set once at initialization and do not change during the session.\n *\n * @example\n * ```tsx\n * const { locale, userAgent } = useUser();\n *\n * // Access device type\n * const isMobile = userAgent.device.type === \"mobile\";\n * ```\n */\nexport function useUser(): UserState {\n const rawLocale = useHostContext(\"locale\");\n const userAgent = useHostContext(\"userAgent\");\n\n return { locale: normalizeLocale(rawLocale), userAgent };\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,122 @@
1
+ import { renderHook, waitFor } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { McpAppAdaptor } from "../bridges/mcp-app/adaptor.js";
4
+ import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
5
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
6
+ import { useUser } from "./use-user.js";
7
+ describe("useUser", () => {
8
+ describe("apps-sdk host type", () => {
9
+ let OpenaiMock;
10
+ beforeEach(() => {
11
+ OpenaiMock = {
12
+ locale: "en-US",
13
+ userAgent: {
14
+ device: { type: "desktop" },
15
+ capabilities: { hover: true, touch: false },
16
+ },
17
+ };
18
+ vi.stubGlobal("openai", OpenaiMock);
19
+ vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
20
+ });
21
+ afterEach(() => {
22
+ vi.unstubAllGlobals();
23
+ vi.resetAllMocks();
24
+ });
25
+ it("should return locale and userAgent from window.openai", () => {
26
+ const { result } = renderHook(() => useUser());
27
+ expect(result.current.locale).toBe("en-US");
28
+ expect(result.current.userAgent).toEqual({
29
+ device: { type: "desktop" },
30
+ capabilities: { hover: true, touch: false },
31
+ });
32
+ });
33
+ it("should return mobile userAgent when set to mobile", () => {
34
+ OpenaiMock.userAgent = {
35
+ device: { type: "mobile" },
36
+ capabilities: { hover: false, touch: true },
37
+ };
38
+ const { result } = renderHook(() => useUser());
39
+ expect(result.current.userAgent.device.type).toBe("mobile");
40
+ expect(result.current.userAgent.capabilities.touch).toBe(true);
41
+ });
42
+ it("should return different locale when set", () => {
43
+ OpenaiMock.locale = "es-ES";
44
+ const { result } = renderHook(() => useUser());
45
+ expect(result.current.locale).toBe("es-ES");
46
+ });
47
+ it("should normalize underscore locale to BCP 47 hyphen format", () => {
48
+ OpenaiMock.locale = "fr_FR";
49
+ const { result } = renderHook(() => useUser());
50
+ expect(result.current.locale).toBe("fr-FR");
51
+ });
52
+ it("should canonicalize locale casing", () => {
53
+ OpenaiMock.locale = "en-us";
54
+ const { result } = renderHook(() => useUser());
55
+ expect(result.current.locale).toBe("en-US");
56
+ });
57
+ it("should fall back to en-US for invalid locale", () => {
58
+ OpenaiMock.locale = "not-a-locale-!!";
59
+ const { result } = renderHook(() => useUser());
60
+ expect(result.current.locale).toBe("en-US");
61
+ });
62
+ });
63
+ describe("mcp-app host type", () => {
64
+ beforeEach(() => {
65
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
66
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
67
+ });
68
+ afterEach(async () => {
69
+ vi.unstubAllGlobals();
70
+ vi.resetAllMocks();
71
+ McpAppBridge.resetInstance();
72
+ McpAppAdaptor.resetInstance();
73
+ });
74
+ it("should return locale and userAgent from mcp host context", async () => {
75
+ vi.stubGlobal("parent", {
76
+ postMessage: getMcpAppHostPostMessageMock({
77
+ locale: "fr-FR",
78
+ platform: "web",
79
+ deviceCapabilities: { hover: true, touch: false },
80
+ }),
81
+ });
82
+ const { result } = renderHook(() => useUser());
83
+ await waitFor(() => {
84
+ expect(result.current.locale).toBe("fr-FR");
85
+ expect(result.current.userAgent).toEqual({
86
+ device: { type: "desktop" },
87
+ capabilities: { hover: true, touch: false },
88
+ });
89
+ });
90
+ });
91
+ it("should normalize underscore locale to BCP 47 hyphen format", async () => {
92
+ vi.stubGlobal("parent", {
93
+ postMessage: getMcpAppHostPostMessageMock({
94
+ locale: "fr_FR",
95
+ platform: "web",
96
+ deviceCapabilities: { hover: true, touch: false },
97
+ }),
98
+ });
99
+ const { result } = renderHook(() => useUser());
100
+ await waitFor(() => {
101
+ expect(result.current.locale).toBe("fr-FR");
102
+ });
103
+ });
104
+ it("should maintain userAgent referential stability when data has not changed", async () => {
105
+ vi.stubGlobal("parent", {
106
+ postMessage: getMcpAppHostPostMessageMock({
107
+ locale: "en-US",
108
+ platform: "web",
109
+ deviceCapabilities: { hover: true, touch: false },
110
+ }),
111
+ });
112
+ const { result, rerender } = renderHook(() => useUser());
113
+ await waitFor(() => {
114
+ expect(result.current.userAgent).toBeDefined();
115
+ });
116
+ const initialUserAgent = result.current.userAgent;
117
+ rerender();
118
+ expect(result.current.userAgent).toBe(initialUserAgent);
119
+ });
120
+ });
121
+ });
122
+ //# sourceMappingURL=use-user.test.js.map