skybridge 0.0.0-dev.a664594 → 0.0.0-dev.a6649ca

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 (351) hide show
  1. package/README.md +10 -7
  2. package/dist/cli/build-helpers.d.ts +11 -0
  3. package/dist/cli/build-helpers.js +107 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.js +132 -0
  6. package/dist/cli/build-helpers.test.js.map +1 -0
  7. package/dist/cli/build-steps.d.ts +2 -0
  8. package/dist/cli/build-steps.js +73 -0
  9. package/dist/cli/build-steps.js.map +1 -0
  10. package/dist/cli/build-steps.test.js +52 -0
  11. package/dist/cli/build-steps.test.js.map +1 -0
  12. package/dist/cli/detect-port.d.ts +2 -2
  13. package/dist/cli/detect-port.js +8 -20
  14. package/dist/cli/detect-port.js.map +1 -1
  15. package/dist/cli/header.d.ts +1 -1
  16. package/dist/cli/resolve-skybridge-config.d.ts +5 -0
  17. package/dist/cli/{resolve-views-dir.js → resolve-skybridge-config.js} +4 -3
  18. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  19. package/dist/cli/run-plain.d.ts +18 -0
  20. package/dist/cli/run-plain.js +89 -0
  21. package/dist/cli/run-plain.js.map +1 -0
  22. package/dist/cli/use-execute-steps.d.ts +1 -1
  23. package/dist/cli/use-nodemon.d.ts +14 -0
  24. package/dist/cli/use-nodemon.js +81 -62
  25. package/dist/cli/use-nodemon.js.map +1 -1
  26. package/dist/cli/use-typescript-check.d.ts +8 -2
  27. package/dist/cli/use-typescript-check.js +70 -67
  28. package/dist/cli/use-typescript-check.js.map +1 -1
  29. package/dist/commands/build.d.ts +0 -3
  30. package/dist/commands/build.js +2 -58
  31. package/dist/commands/build.js.map +1 -1
  32. package/dist/commands/dev.d.ts +1 -0
  33. package/dist/commands/dev.js +35 -3
  34. package/dist/commands/dev.js.map +1 -1
  35. package/dist/commands/start.js +7 -1
  36. package/dist/commands/start.js.map +1 -1
  37. package/dist/context-warnings.d.ts +5 -0
  38. package/dist/context-warnings.js +31 -0
  39. package/dist/context-warnings.js.map +1 -0
  40. package/dist/context-warnings.test.js +28 -0
  41. package/dist/context-warnings.test.js.map +1 -0
  42. package/dist/server/app.d.ts +194 -0
  43. package/dist/server/app.js +266 -0
  44. package/dist/server/app.js.map +1 -0
  45. package/dist/server/app.test.js +97 -0
  46. package/dist/server/app.test.js.map +1 -0
  47. package/dist/server/auth/discovery.d.ts +33 -0
  48. package/dist/server/auth/discovery.js +56 -0
  49. package/dist/server/auth/discovery.js.map +1 -0
  50. package/dist/server/auth/discovery.test.d.ts +1 -0
  51. package/dist/server/auth/discovery.test.js +93 -0
  52. package/dist/server/auth/discovery.test.js.map +1 -0
  53. package/dist/server/auth/index.d.ts +48 -0
  54. package/dist/server/auth/index.js +2 -0
  55. package/dist/server/auth/index.js.map +1 -0
  56. package/dist/server/auth/providers/auth0.d.ts +40 -0
  57. package/dist/server/auth/providers/auth0.js +36 -0
  58. package/dist/server/auth/providers/auth0.js.map +1 -0
  59. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  60. package/dist/server/auth/providers/auth0.test.js +50 -0
  61. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  62. package/dist/server/auth/providers/authplane.d.ts +49 -0
  63. package/dist/server/auth/providers/authplane.js +57 -0
  64. package/dist/server/auth/providers/authplane.js.map +1 -0
  65. package/dist/server/auth/providers/authplane.test.d.ts +1 -0
  66. package/dist/server/auth/providers/authplane.test.js +143 -0
  67. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  68. package/dist/server/auth/providers/clerk.d.ts +51 -0
  69. package/dist/server/auth/providers/clerk.js +19 -0
  70. package/dist/server/auth/providers/clerk.js.map +1 -0
  71. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  72. package/dist/server/auth/providers/clerk.test.js +30 -0
  73. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  74. package/dist/server/auth/providers/custom.d.ts +40 -0
  75. package/dist/server/auth/providers/custom.js +59 -0
  76. package/dist/server/auth/providers/custom.js.map +1 -0
  77. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  78. package/dist/server/auth/providers/custom.test.js +161 -0
  79. package/dist/server/auth/providers/custom.test.js.map +1 -0
  80. package/dist/server/auth/providers/descope.d.ts +44 -0
  81. package/dist/server/auth/providers/descope.js +44 -0
  82. package/dist/server/auth/providers/descope.js.map +1 -0
  83. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  84. package/dist/server/auth/providers/descope.test.js +62 -0
  85. package/dist/server/auth/providers/descope.test.js.map +1 -0
  86. package/dist/server/auth/providers/shared.d.ts +2 -0
  87. package/dist/server/auth/providers/shared.js +6 -0
  88. package/dist/server/auth/providers/shared.js.map +1 -0
  89. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  90. package/dist/server/auth/providers/shared.test.js +10 -0
  91. package/dist/server/auth/providers/shared.test.js.map +1 -0
  92. package/dist/server/auth/providers/stytch.d.ts +25 -0
  93. package/dist/server/auth/providers/stytch.js +16 -0
  94. package/dist/server/auth/providers/stytch.js.map +1 -0
  95. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  96. package/dist/server/auth/providers/verify-spy.js +21 -0
  97. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  98. package/dist/server/auth/providers/workos.d.ts +33 -0
  99. package/dist/server/auth/providers/workos.js +15 -0
  100. package/dist/server/auth/providers/workos.js.map +1 -0
  101. package/dist/server/auth/security-schemes.d.ts +23 -0
  102. package/dist/server/auth/security-schemes.js +64 -0
  103. package/dist/server/auth/security-schemes.js.map +1 -0
  104. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  105. package/dist/server/auth/security-schemes.test.js +99 -0
  106. package/dist/server/auth/security-schemes.test.js.map +1 -0
  107. package/dist/server/auth/setup.d.ts +6 -0
  108. package/dist/server/auth/setup.js +91 -0
  109. package/dist/server/auth/setup.js.map +1 -0
  110. package/dist/server/auth/setup.test.d.ts +1 -0
  111. package/dist/server/auth/setup.test.js +514 -0
  112. package/dist/server/auth/setup.test.js.map +1 -0
  113. package/dist/server/auth/verify.d.ts +46 -0
  114. package/dist/server/auth/verify.js +62 -0
  115. package/dist/server/auth/verify.js.map +1 -0
  116. package/dist/server/auth/verify.test.d.ts +1 -0
  117. package/dist/server/auth/verify.test.js +149 -0
  118. package/dist/server/auth/verify.test.js.map +1 -0
  119. package/dist/server/auth-extra.test-d.js +130 -0
  120. package/dist/server/auth-extra.test-d.js.map +1 -0
  121. package/dist/server/auth.d.ts +43 -6
  122. package/dist/server/auth.js +4 -5
  123. package/dist/server/auth.js.map +1 -1
  124. package/dist/server/build-manifest.test.d.ts +1 -0
  125. package/dist/server/build-manifest.test.js +28 -0
  126. package/dist/server/build-manifest.test.js.map +1 -0
  127. package/dist/server/content-helpers.d.ts +1 -1
  128. package/dist/server/content-helpers.js.map +1 -1
  129. package/dist/server/express.d.ts +23 -3
  130. package/dist/server/express.js +38 -32
  131. package/dist/server/express.js.map +1 -1
  132. package/dist/server/express.test.js +268 -90
  133. package/dist/server/express.test.js.map +1 -1
  134. package/dist/server/file-ref.d.ts +1 -1
  135. package/dist/server/file-ref.js +1 -1
  136. package/dist/server/file-ref.js.map +1 -1
  137. package/dist/server/host.d.ts +2 -0
  138. package/dist/server/host.js +11 -0
  139. package/dist/server/host.js.map +1 -0
  140. package/dist/server/host.test.d.ts +1 -0
  141. package/dist/server/host.test.js +13 -0
  142. package/dist/server/host.test.js.map +1 -0
  143. package/dist/server/index.d.ts +17 -3
  144. package/dist/server/index.js +14 -2
  145. package/dist/server/index.js.map +1 -1
  146. package/dist/server/mcp-errors.test.d.ts +1 -0
  147. package/dist/server/mcp-errors.test.js +41 -0
  148. package/dist/server/mcp-errors.test.js.map +1 -0
  149. package/dist/server/middleware.d.ts +35 -10
  150. package/dist/server/middleware.js +33 -0
  151. package/dist/server/middleware.js.map +1 -1
  152. package/dist/server/middleware.test-d.js +1 -1
  153. package/dist/server/middleware.test-d.js.map +1 -1
  154. package/dist/server/middleware.test.js +242 -134
  155. package/dist/server/middleware.test.js.map +1 -1
  156. package/dist/server/register-tool.test.d.ts +1 -0
  157. package/dist/server/register-tool.test.js +27 -0
  158. package/dist/server/register-tool.test.js.map +1 -0
  159. package/dist/server/requestOrigin.d.ts +7 -0
  160. package/dist/server/requestOrigin.js +25 -0
  161. package/dist/server/requestOrigin.js.map +1 -0
  162. package/dist/server/server.d.ts +144 -122
  163. package/dist/server/server.js +313 -328
  164. package/dist/server/server.js.map +1 -1
  165. package/dist/server/skills-integration.test.d.ts +1 -0
  166. package/dist/server/skills-integration.test.js +86 -0
  167. package/dist/server/skills-integration.test.js.map +1 -0
  168. package/dist/server/skills.d.ts +27 -0
  169. package/dist/server/skills.js +188 -0
  170. package/dist/server/skills.js.map +1 -0
  171. package/dist/server/skills.test.d.ts +1 -0
  172. package/dist/server/skills.test.js +243 -0
  173. package/dist/server/skills.test.js.map +1 -0
  174. package/dist/server/templateHelper.d.ts +0 -3
  175. package/dist/server/templateHelper.js.map +1 -1
  176. package/dist/server/templates.generated.js +4 -8
  177. package/dist/server/templates.generated.js.map +1 -1
  178. package/dist/server/tool-extra.test.d.ts +1 -0
  179. package/dist/server/tool-extra.test.js +88 -0
  180. package/dist/server/tool-extra.test.js.map +1 -0
  181. package/dist/server/view-name.test-d.d.ts +1 -0
  182. package/dist/server/view-name.test-d.js +8 -0
  183. package/dist/server/view-name.test-d.js.map +1 -0
  184. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  185. package/dist/server/view-resource-resolution.test.js +176 -0
  186. package/dist/server/view-resource-resolution.test.js.map +1 -0
  187. package/dist/server/viewsDevServer.js +4 -1
  188. package/dist/server/viewsDevServer.js.map +1 -1
  189. package/dist/test/utils.d.ts +9 -11
  190. package/dist/test/utils.js +220 -201
  191. package/dist/test/utils.js.map +1 -1
  192. package/dist/test/view.test.js +105 -133
  193. package/dist/test/view.test.js.map +1 -1
  194. package/dist/views/index.d.ts +10 -0
  195. package/dist/views/index.js +3 -0
  196. package/dist/views/index.js.map +1 -0
  197. package/dist/{web/plugin → views}/scan-views.js +1 -1
  198. package/dist/views/scan-views.js.map +1 -0
  199. package/dist/views/scan-views.test.d.ts +1 -0
  200. package/dist/views/scan-views.test.js.map +1 -0
  201. package/dist/views/validate-view.d.ts +1 -0
  202. package/dist/{web/plugin → views}/validate-view.js +2 -2
  203. package/dist/views/validate-view.js.map +1 -0
  204. package/dist/views/validate-view.test.d.ts +1 -0
  205. package/dist/views/validate-view.test.js.map +1 -0
  206. package/dist/web/bridges/adaptor.d.ts +9 -6
  207. package/dist/web/bridges/adaptor.js +93 -74
  208. package/dist/web/bridges/adaptor.js.map +1 -1
  209. package/dist/web/bridges/adaptor.test.js +94 -244
  210. package/dist/web/bridges/adaptor.test.js.map +1 -1
  211. package/dist/web/bridges/apps-sdk/bridge.d.ts +5 -1
  212. package/dist/web/bridges/apps-sdk/bridge.js +12 -0
  213. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  214. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +1 -1
  215. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +1 -1
  216. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  217. package/dist/web/bridges/get-adaptor.d.ts +0 -2
  218. package/dist/web/bridges/get-adaptor.js +1 -21
  219. package/dist/web/bridges/get-adaptor.js.map +1 -1
  220. package/dist/web/bridges/get-adaptor.test.js +5 -21
  221. package/dist/web/bridges/get-adaptor.test.js.map +1 -1
  222. package/dist/web/bridges/mcp-app/bridge.d.ts +14 -2
  223. package/dist/web/bridges/mcp-app/bridge.js +72 -4
  224. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  225. package/dist/web/bridges/mcp-app/bridge.test.js +2 -6
  226. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -1
  227. package/dist/web/bridges/mcp-app/types.d.ts +2 -0
  228. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  229. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +1 -1
  230. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
  231. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  232. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
  233. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  234. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  235. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  236. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  237. package/dist/web/bridges/types.d.ts +45 -12
  238. package/dist/web/bridges/types.js.map +1 -1
  239. package/dist/web/components/modal-provider.d.ts +1 -1
  240. package/dist/web/create-store.test.js +6 -5
  241. package/dist/web/create-store.test.js.map +1 -1
  242. package/dist/web/data-llm.d.ts +1 -1
  243. package/dist/web/data-llm.test.js +15 -5
  244. package/dist/web/data-llm.test.js.map +1 -1
  245. package/dist/web/generate-helpers.d.ts +22 -18
  246. package/dist/web/generate-helpers.js +19 -15
  247. package/dist/web/generate-helpers.js.map +1 -1
  248. package/dist/web/generate-helpers.test-d.js +7 -5
  249. package/dist/web/generate-helpers.test-d.js.map +1 -1
  250. package/dist/web/generate-helpers.test.js +2 -2
  251. package/dist/web/generate-helpers.test.js.map +1 -1
  252. package/dist/web/hooks/index.d.ts +3 -1
  253. package/dist/web/hooks/index.js +3 -1
  254. package/dist/web/hooks/index.js.map +1 -1
  255. package/dist/web/hooks/test/utils.d.ts +2 -1
  256. package/dist/web/hooks/test/utils.js +1 -1
  257. package/dist/web/hooks/test/utils.js.map +1 -1
  258. package/dist/web/hooks/use-call-tool.test.js +8 -7
  259. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  260. package/dist/web/hooks/use-display-mode.d.ts +1 -1
  261. package/dist/web/hooks/use-display-mode.js +1 -1
  262. package/dist/web/hooks/use-display-mode.js.map +1 -1
  263. package/dist/web/hooks/use-display-mode.test.js +5 -4
  264. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  265. package/dist/web/hooks/use-download.d.ts +1 -3
  266. package/dist/web/hooks/use-download.js +1 -2
  267. package/dist/web/hooks/use-download.js.map +1 -1
  268. package/dist/web/hooks/use-download.test.js +12 -12
  269. package/dist/web/hooks/use-download.test.js.map +1 -1
  270. package/dist/web/hooks/use-files.test.js +4 -4
  271. package/dist/web/hooks/use-files.test.js.map +1 -1
  272. package/dist/web/hooks/use-host.d.ts +22 -0
  273. package/dist/web/hooks/use-host.js +30 -0
  274. package/dist/web/hooks/use-host.js.map +1 -0
  275. package/dist/web/hooks/use-host.test.d.ts +1 -0
  276. package/dist/web/hooks/use-host.test.js +59 -0
  277. package/dist/web/hooks/use-host.test.js.map +1 -0
  278. package/dist/web/hooks/use-open-external.test.js +9 -13
  279. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  280. package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
  281. package/dist/web/hooks/use-register-view-tool.js +50 -0
  282. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  283. package/dist/web/hooks/use-request-close.test.js +6 -5
  284. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  285. package/dist/web/hooks/use-request-modal.test.js +4 -4
  286. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  287. package/dist/web/hooks/use-request-size.d.ts +1 -1
  288. package/dist/web/hooks/use-request-size.js +1 -1
  289. package/dist/web/hooks/use-request-size.js.map +1 -1
  290. package/dist/web/hooks/use-request-size.test.js +4 -4
  291. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  292. package/dist/web/hooks/use-set-open-in-app-url.test.js +4 -10
  293. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  294. package/dist/web/hooks/use-tool-info.d.ts +18 -19
  295. package/dist/web/hooks/use-tool-info.js +4 -8
  296. package/dist/web/hooks/use-tool-info.js.map +1 -1
  297. package/dist/web/hooks/use-tool-info.test-d.js +11 -34
  298. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  299. package/dist/web/hooks/use-tool-info.test.js +9 -14
  300. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  301. package/dist/web/hooks/use-user.d.ts +3 -2
  302. package/dist/web/hooks/use-user.js +4 -3
  303. package/dist/web/hooks/use-user.js.map +1 -1
  304. package/dist/web/hooks/use-user.test.js +10 -8
  305. package/dist/web/hooks/use-user.test.js.map +1 -1
  306. package/dist/web/hooks/use-view-state.js +19 -9
  307. package/dist/web/hooks/use-view-state.js.map +1 -1
  308. package/dist/web/hooks/use-view-state.test.js +36 -5
  309. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  310. package/dist/web/hooks/use-viewport.d.ts +20 -0
  311. package/dist/web/hooks/use-viewport.js +21 -0
  312. package/dist/web/hooks/use-viewport.js.map +1 -0
  313. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  314. package/dist/web/hooks/{use-layout.test.js → use-viewport.test.js} +17 -37
  315. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  316. package/dist/web/mount-view.d.ts +3 -2
  317. package/dist/web/mount-view.js +5 -8
  318. package/dist/web/mount-view.js.map +1 -1
  319. package/package.json +32 -26
  320. package/dist/cli/resolve-views-dir.d.ts +0 -1
  321. package/dist/cli/resolve-views-dir.js.map +0 -1
  322. package/dist/web/bridges/host-context-stores.d.ts +0 -27
  323. package/dist/web/bridges/host-context-stores.js +0 -73
  324. package/dist/web/bridges/host-context-stores.js.map +0 -1
  325. package/dist/web/hooks/use-layout.d.ts +0 -24
  326. package/dist/web/hooks/use-layout.js +0 -25
  327. package/dist/web/hooks/use-layout.js.map +0 -1
  328. package/dist/web/hooks/use-layout.test.js.map +0 -1
  329. package/dist/web/plugin/data-llm.test.js +0 -81
  330. package/dist/web/plugin/data-llm.test.js.map +0 -1
  331. package/dist/web/plugin/plugin.d.ts +0 -33
  332. package/dist/web/plugin/plugin.js +0 -189
  333. package/dist/web/plugin/plugin.js.map +0 -1
  334. package/dist/web/plugin/scan-views.js.map +0 -1
  335. package/dist/web/plugin/scan-views.test.js.map +0 -1
  336. package/dist/web/plugin/transform-data-llm.d.ts +0 -12
  337. package/dist/web/plugin/transform-data-llm.js +0 -96
  338. package/dist/web/plugin/transform-data-llm.js.map +0 -1
  339. package/dist/web/plugin/transform-data-llm.test.js +0 -81
  340. package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
  341. package/dist/web/plugin/validate-view.d.ts +0 -1
  342. package/dist/web/plugin/validate-view.js.map +0 -1
  343. package/dist/web/plugin/validate-view.test.js.map +0 -1
  344. /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  345. /package/dist/{web/plugin/data-llm.test.d.ts → cli/build-steps.test.d.ts} +0 -0
  346. /package/dist/{web/plugin/scan-views.test.d.ts → context-warnings.test.d.ts} +0 -0
  347. /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/app.test.d.ts} +0 -0
  348. /package/dist/{web/plugin/validate-view.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
  349. /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
  350. /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
  351. /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
@@ -1,45 +1,25 @@
1
1
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { VIEW_STATE_WARNING_TOKENS } from "../../context-warnings.js";
2
3
  import { HostAdaptor } from "./adaptor.js";
3
4
  import { AppsSdkBridge } from "./apps-sdk/bridge.js";
4
5
  import { McpAppBridge } from "./mcp-app/bridge.js";
5
6
  import { NotSupportedError } from "./types.js";
6
- describe("HostAdaptor constructor", () => {
7
+ describe("HostAdaptor", () => {
7
8
  beforeEach(() => {
8
9
  McpAppBridge.resetInstance();
9
10
  AppsSdkBridge.resetInstance();
10
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
11
+ vi.stubGlobal("skybridge", {});
11
12
  vi.stubGlobal("parent", { postMessage: vi.fn() });
13
+ localStorage.clear();
12
14
  });
13
15
  afterEach(() => {
14
16
  vi.unstubAllGlobals();
15
17
  McpAppBridge.resetInstance();
16
18
  AppsSdkBridge.resetInstance();
19
+ localStorage.clear();
17
20
  });
18
- it("instantiates without window.openai (oai is null)", () => {
19
- vi.stubGlobal("openai", undefined);
20
- const adaptor = new HostAdaptor();
21
- expect(adaptor.hasAppsSdkOverlay()).toBe(false);
22
- });
23
- it("captures window.openai when present (oai is set)", () => {
24
- vi.stubGlobal("openai", { widgetState: null });
25
- const adaptor = new HostAdaptor();
26
- expect(adaptor.hasAppsSdkOverlay()).toBe(true);
27
- });
28
- });
29
- describe("HostAdaptor MCP-routed methods", () => {
30
- beforeEach(() => {
31
- McpAppBridge.resetInstance();
32
- AppsSdkBridge.resetInstance();
33
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
34
- vi.stubGlobal("parent", { postMessage: vi.fn() });
35
- vi.stubGlobal("openai", undefined);
36
- });
37
- afterEach(() => {
38
- vi.unstubAllGlobals();
39
- McpAppBridge.resetInstance();
40
- AppsSdkBridge.resetInstance();
41
- });
42
- it("callTool delegates to mcp.callServerTool", async () => {
21
+ it("callTool always routes to mcp.callServerTool", async () => {
22
+ vi.stubGlobal("openai", { callTool: vi.fn() });
43
23
  const adaptor = new HostAdaptor();
44
24
  const fakeApp = {
45
25
  callServerTool: vi.fn().mockResolvedValue({
@@ -59,39 +39,8 @@ describe("HostAdaptor MCP-routed methods", () => {
59
39
  expect(result.structuredContent).toEqual({ ok: true });
60
40
  expect(result.meta).toEqual({ x: 1 });
61
41
  });
62
- it("requestDisplayMode delegates to mcp.requestDisplayMode", async () => {
63
- const adaptor = new HostAdaptor();
64
- const fakeApp = {
65
- requestDisplayMode: vi.fn().mockResolvedValue({ mode: "fullscreen" }),
66
- };
67
- // biome-ignore lint/suspicious/noExplicitAny: test seam
68
- adaptor.mcp.getApp = vi.fn().mockResolvedValue(fakeApp);
69
- const r = await adaptor.requestDisplayMode("fullscreen");
70
- expect(r.mode).toBe("fullscreen");
71
- expect(fakeApp.requestDisplayMode).toHaveBeenCalledWith({
72
- mode: "fullscreen",
73
- });
74
- });
75
- it("requestClose delegates to mcp.requestTeardown", async () => {
76
- const adaptor = new HostAdaptor();
77
- const fakeApp = { requestTeardown: vi.fn().mockResolvedValue(undefined) };
78
- // biome-ignore lint/suspicious/noExplicitAny: test seam
79
- adaptor.mcp.getApp = vi.fn().mockResolvedValue(fakeApp);
80
- await adaptor.requestClose();
81
- expect(fakeApp.requestTeardown).toHaveBeenCalled();
82
- });
83
- it("requestSize delegates to mcp.sendSizeChanged", async () => {
84
- const adaptor = new HostAdaptor();
85
- const fakeApp = { sendSizeChanged: vi.fn().mockResolvedValue(undefined) };
86
- // biome-ignore lint/suspicious/noExplicitAny: test seam
87
- adaptor.mcp.getApp = vi.fn().mockResolvedValue(fakeApp);
88
- await adaptor.requestSize({ width: 100, height: 200 });
89
- expect(fakeApp.sendSizeChanged).toHaveBeenCalledWith({
90
- width: 100,
91
- height: 200,
92
- });
93
- });
94
42
  it("download returns isError when host lacks downloadFile capability", async () => {
43
+ vi.stubGlobal("openai", undefined);
95
44
  const adaptor = new HostAdaptor();
96
45
  const fakeApp = {
97
46
  getHostCapabilities: () => ({}),
@@ -103,187 +52,106 @@ describe("HostAdaptor MCP-routed methods", () => {
103
52
  expect(r.isError).toBe(true);
104
53
  expect(fakeApp.downloadFile).not.toHaveBeenCalled();
105
54
  });
106
- });
107
- describe("HostAdaptor conditional routing", () => {
108
- beforeEach(() => {
109
- McpAppBridge.resetInstance();
110
- AppsSdkBridge.resetInstance();
111
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
112
- vi.stubGlobal("parent", { postMessage: vi.fn() });
113
- });
114
- afterEach(() => {
115
- vi.unstubAllGlobals();
116
- McpAppBridge.resetInstance();
117
- AppsSdkBridge.resetInstance();
118
- });
119
- it("sendFollowUpMessage uses oai when scrollToBottom set", async () => {
55
+ it("sendFollowUpMessage routes to window.openai only when scrollToBottom is set", async () => {
120
56
  const sendFollowUpMessage = vi.fn().mockResolvedValue(undefined);
121
57
  vi.stubGlobal("openai", { sendFollowUpMessage });
122
- const adaptor = new HostAdaptor();
58
+ let adaptor = new HostAdaptor();
123
59
  await adaptor.sendFollowUpMessage("hi", { scrollToBottom: false });
124
60
  expect(sendFollowUpMessage).toHaveBeenCalledWith({
125
61
  prompt: "hi",
126
62
  scrollToBottom: false,
127
63
  });
128
- });
129
- it("sendFollowUpMessage uses mcp when no options", async () => {
64
+ // Default case falls through to MCP
65
+ McpAppBridge.resetInstance();
66
+ AppsSdkBridge.resetInstance();
130
67
  vi.stubGlobal("openai", undefined);
131
- const adaptor = new HostAdaptor();
132
- const fakeApp = { sendMessage: vi.fn().mockResolvedValue(undefined) };
68
+ adaptor = new HostAdaptor();
69
+ const sendMessage = vi.fn().mockResolvedValue(undefined);
133
70
  // biome-ignore lint/suspicious/noExplicitAny: test seam
134
- adaptor.mcp.getApp = vi.fn().mockResolvedValue(fakeApp);
71
+ adaptor.mcp.getApp = vi.fn().mockResolvedValue({ sendMessage });
135
72
  await adaptor.sendFollowUpMessage("hi");
136
- expect(fakeApp.sendMessage).toHaveBeenCalledWith({
73
+ expect(sendMessage).toHaveBeenCalledWith({
137
74
  role: "user",
138
75
  content: [{ type: "text", text: "hi" }],
139
76
  });
140
77
  });
141
- it("openExternal uses oai when redirectUrl: false", async () => {
78
+ it("openExternal routes to window.openai only when redirectUrl: false", async () => {
142
79
  const openExternal = vi.fn();
143
80
  vi.stubGlobal("openai", { openExternal });
144
- const adaptor = new HostAdaptor();
81
+ let adaptor = new HostAdaptor();
145
82
  adaptor.openExternal("https://x", { redirectUrl: false });
146
83
  expect(openExternal).toHaveBeenCalledWith({
147
84
  href: "https://x",
148
85
  redirectUrl: false,
149
86
  });
150
- });
151
- it("openExternal uses mcp.openLink for default case", async () => {
87
+ // Default case falls through to MCP openLink
88
+ McpAppBridge.resetInstance();
89
+ AppsSdkBridge.resetInstance();
152
90
  vi.stubGlobal("openai", undefined);
153
- const adaptor = new HostAdaptor();
91
+ adaptor = new HostAdaptor();
154
92
  const openLink = vi.fn();
155
93
  // biome-ignore lint/suspicious/noExplicitAny: test seam
156
94
  adaptor.mcp.getApp = vi.fn().mockResolvedValue({ openLink });
157
95
  adaptor.openExternal("https://x");
158
- // openExternal is sync but mcp.openLink resolves async
159
96
  await new Promise((r) => setTimeout(r, 0));
160
97
  expect(openLink).toHaveBeenCalledWith({ url: "https://x" });
161
98
  });
162
- });
163
- describe("HostAdaptor Apps-SDK-only methods", () => {
164
- beforeEach(() => {
165
- McpAppBridge.resetInstance();
166
- AppsSdkBridge.resetInstance();
167
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
168
- vi.stubGlobal("parent", { postMessage: vi.fn() });
169
- });
170
- afterEach(() => {
171
- vi.unstubAllGlobals();
172
- McpAppBridge.resetInstance();
173
- AppsSdkBridge.resetInstance();
174
- });
175
- it("uploadFile throws NotSupportedError when oai is null", async () => {
99
+ it("Apps-SDK-exclusive methods throw NotSupportedError when window.openai is null", async () => {
176
100
  vi.stubGlobal("openai", undefined);
177
101
  const adaptor = new HostAdaptor();
178
102
  await expect(adaptor.uploadFile(new File([], "x"))).rejects.toThrow(NotSupportedError);
103
+ await expect(adaptor.selectFiles()).rejects.toThrow(NotSupportedError);
104
+ await expect(adaptor.getFileDownloadUrl({ fileId: "x" })).rejects.toThrow(NotSupportedError);
105
+ await expect(adaptor.setOpenInAppUrl("https://x")).rejects.toThrow(NotSupportedError);
179
106
  });
180
- it("uploadFile delegates to oai.uploadFile and tracks fileId", async () => {
107
+ it("uploadFile delegates to window.openai.uploadFile and tracks fileId in widgetState", async () => {
181
108
  const setWidgetState = vi.fn().mockResolvedValue(undefined);
182
- const uploadFile = vi
183
- .fn()
184
- .mockResolvedValue({ fileId: "abc", fileName: "x" });
185
- vi.stubGlobal("openai", {
186
- uploadFile,
187
- setWidgetState,
188
- widgetState: null,
109
+ const uploadFile = vi.fn().mockResolvedValue({
110
+ fileId: "abc",
111
+ fileName: "x",
112
+ mimeType: "image/png",
189
113
  });
114
+ vi.stubGlobal("openai", { uploadFile, setWidgetState, widgetState: null });
190
115
  const adaptor = new HostAdaptor();
191
- const file = new File([], "x");
116
+ const file = new File([], "x", { type: "image/png" });
192
117
  const r = await adaptor.uploadFile(file, { library: true });
193
118
  expect(uploadFile).toHaveBeenCalledWith(file, { library: true });
194
119
  expect(r.fileId).toBe("abc");
195
120
  expect(setWidgetState).toHaveBeenCalledWith(expect.objectContaining({ imageIds: ["abc"] }));
196
121
  });
197
- it("selectFiles throws when oai is null", async () => {
198
- vi.stubGlobal("openai", undefined);
199
- const adaptor = new HostAdaptor();
200
- await expect(adaptor.selectFiles()).rejects.toThrow(NotSupportedError);
201
- });
202
- it("selectFiles throws when host version lacks support", async () => {
203
- vi.stubGlobal("openai", { selectFiles: undefined });
204
- const adaptor = new HostAdaptor();
205
- await expect(adaptor.selectFiles()).rejects.toThrow(/selectFiles/);
206
- });
207
- it("getFileDownloadUrl throws when oai is null", async () => {
208
- vi.stubGlobal("openai", undefined);
209
- const adaptor = new HostAdaptor();
210
- await expect(adaptor.getFileDownloadUrl({ fileId: "x" })).rejects.toThrow(NotSupportedError);
211
- });
212
- it("setOpenInAppUrl throws when oai is null", async () => {
213
- vi.stubGlobal("openai", undefined);
214
- const adaptor = new HostAdaptor();
215
- await expect(adaptor.setOpenInAppUrl("https://x")).rejects.toThrow(NotSupportedError);
216
- });
217
- });
218
- describe("HostAdaptor modal", () => {
219
- beforeEach(() => {
220
- McpAppBridge.resetInstance();
221
- AppsSdkBridge.resetInstance();
222
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
223
- vi.stubGlobal("parent", { postMessage: vi.fn() });
224
- });
225
- afterEach(() => {
226
- vi.unstubAllGlobals();
227
- McpAppBridge.resetInstance();
228
- AppsSdkBridge.resetInstance();
229
- });
230
- it("openModal delegates to oai.requestModal when present", () => {
231
- const requestModal = vi.fn();
232
- vi.stubGlobal("openai", { requestModal });
233
- const adaptor = new HostAdaptor();
234
- adaptor.openModal({ title: "Hi" });
235
- expect(requestModal).toHaveBeenCalledWith({ title: "Hi" });
236
- });
237
- it("closeModal is a no-op when oai is present", () => {
238
- vi.stubGlobal("openai", { requestModal: vi.fn() });
239
- const adaptor = new HostAdaptor();
240
- expect(() => adaptor.closeModal()).not.toThrow();
241
- });
242
- it("openModal sets polyfill display state when oai is null", () => {
243
- vi.stubGlobal("openai", undefined);
244
- const adaptor = new HostAdaptor();
245
- const listener = vi.fn();
246
- // biome-ignore lint/suspicious/noExplicitAny: test seam
247
- adaptor.polyfillDisplayListeners.add(listener);
248
- adaptor.openModal({ params: { x: 1 } });
249
- // biome-ignore lint/suspicious/noExplicitAny: test seam
250
- expect(adaptor._polyfillDisplay).toEqual({
251
- mode: "modal",
252
- params: { x: 1 },
122
+ it("uploadFile does not track a non-image fileId in widgetState.imageIds", async () => {
123
+ const setWidgetState = vi.fn().mockResolvedValue(undefined);
124
+ const uploadFile = vi.fn().mockResolvedValue({
125
+ fileId: "sediment://file_txt",
126
+ fileName: "notes.txt",
127
+ mimeType: "text/plain",
253
128
  });
254
- expect(listener).toHaveBeenCalled();
255
- });
256
- it("closeModal resets polyfill display state when oai is null", () => {
257
- vi.stubGlobal("openai", undefined);
129
+ vi.stubGlobal("openai", { uploadFile, setWidgetState, widgetState: null });
258
130
  const adaptor = new HostAdaptor();
259
- adaptor.openModal({});
260
- adaptor.closeModal();
261
- // biome-ignore lint/suspicious/noExplicitAny: test seam
262
- expect(adaptor._polyfillDisplay).toEqual({ mode: "inline" });
263
- });
264
- });
265
- describe("HostAdaptor setViewState", () => {
266
- beforeEach(() => {
267
- McpAppBridge.resetInstance();
268
- AppsSdkBridge.resetInstance();
269
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
270
- vi.stubGlobal("parent", { postMessage: vi.fn() });
271
- localStorage.clear();
272
- });
273
- afterEach(() => {
274
- vi.unstubAllGlobals();
275
- McpAppBridge.resetInstance();
276
- AppsSdkBridge.resetInstance();
277
- localStorage.clear();
131
+ await adaptor.uploadFile(new File([], "notes.txt", { type: "text/plain" }));
132
+ for (const call of setWidgetState.mock.calls) {
133
+ expect(call[0].imageIds ?? []).not.toContain("sediment://file_txt");
134
+ }
278
135
  });
279
- it("uses window.openai.setWidgetState when oai is present", async () => {
136
+ it("setViewState uses window.openai.setWidgetState when present", async () => {
280
137
  const setWidgetState = vi.fn().mockResolvedValue(undefined);
281
138
  vi.stubGlobal("openai", { setWidgetState, widgetState: null });
282
139
  const adaptor = new HostAdaptor();
283
140
  await adaptor.setViewState({ count: 1 });
284
141
  expect(setWidgetState).toHaveBeenCalledWith(expect.objectContaining({ modelContent: { count: 1 } }));
285
142
  });
286
- it("calls mcp.updateModelContext and writes localStorage when oai is null", async () => {
143
+ it("warns when setViewState reaches 20K tokens", async () => {
144
+ const setWidgetState = vi.fn().mockResolvedValue(undefined);
145
+ vi.stubGlobal("openai", { setWidgetState, widgetState: null });
146
+ const adaptor = new HostAdaptor();
147
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
148
+ await adaptor.setViewState({
149
+ longText: "x".repeat(VIEW_STATE_WARNING_TOKENS * 4),
150
+ });
151
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("setWidgetState is persisting"));
152
+ warnSpy.mockRestore();
153
+ });
154
+ it("setViewState falls back to MCP updateModelContext + localStorage when window.openai is absent", async () => {
287
155
  vi.stubGlobal("openai", undefined);
288
156
  const adaptor = new HostAdaptor();
289
157
  const updateModelContext = vi.fn().mockResolvedValue(undefined);
@@ -307,69 +175,51 @@ describe("HostAdaptor setViewState", () => {
307
175
  }
308
176
  expect(keys.some((k) => k.endsWith(":view-1"))).toBe(true);
309
177
  });
310
- it("accepts an updater function form", async () => {
178
+ it("openModal/closeModal: delegates to window.openai.requestModal when present, polyfill state otherwise", () => {
179
+ const requestModal = vi.fn();
180
+ vi.stubGlobal("openai", { requestModal });
181
+ let adaptor = new HostAdaptor();
182
+ adaptor.openModal({ title: "Hi" });
183
+ expect(requestModal).toHaveBeenCalledWith({ title: "Hi" });
184
+ expect(() => adaptor.closeModal()).not.toThrow();
185
+ // Polyfill path
186
+ McpAppBridge.resetInstance();
187
+ AppsSdkBridge.resetInstance();
311
188
  vi.stubGlobal("openai", undefined);
312
- const adaptor = new HostAdaptor();
189
+ adaptor = new HostAdaptor();
190
+ adaptor.openModal({ params: { x: 1 } });
313
191
  // biome-ignore lint/suspicious/noExplicitAny: test seam
314
- adaptor.mcp.getApp = vi.fn().mockResolvedValue({
315
- updateModelContext: vi.fn().mockResolvedValue(undefined),
192
+ expect(adaptor._polyfillDisplay).toEqual({
193
+ mode: "modal",
194
+ params: { x: 1 },
316
195
  });
196
+ adaptor.closeModal();
317
197
  // biome-ignore lint/suspicious/noExplicitAny: test seam
318
- adaptor._viewState = { count: 1 };
319
- await adaptor.setViewState((prev) => ({
320
- // biome-ignore lint/suspicious/noExplicitAny: test
321
- count: prev.count + 1,
322
- }));
323
- // biome-ignore lint/suspicious/noExplicitAny: test seam
324
- expect(adaptor._viewState).toEqual({ count: 2 });
325
- });
326
- });
327
- describe("HostAdaptor getHostContextStore", () => {
328
- beforeEach(() => {
329
- McpAppBridge.resetInstance();
330
- AppsSdkBridge.resetInstance();
331
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
332
- vi.stubGlobal("parent", { postMessage: vi.fn() });
333
- });
334
- afterEach(() => {
335
- vi.unstubAllGlobals();
336
- McpAppBridge.resetInstance();
337
- AppsSdkBridge.resetInstance();
338
- });
339
- it("routes `display` to oai when overlay is present", () => {
340
- vi.stubGlobal("openai", { view: { mode: "fullscreen" } });
341
- const adaptor = new HostAdaptor();
342
- const store = adaptor.getHostContextStore("display");
343
- expect(store.getSnapshot()).toEqual({ mode: "fullscreen" });
198
+ expect(adaptor._polyfillDisplay).toEqual({ mode: "inline" });
344
199
  });
345
- it("routes `viewState` to oai.widgetState.modelContent when overlay present", () => {
200
+ it("getHostContextStore: display/viewState route to Apps SDK overlay when present, MCP otherwise", () => {
346
201
  vi.stubGlobal("openai", {
202
+ view: { mode: "fullscreen" },
347
203
  widgetState: { modelContent: { count: 5 }, privateContent: {} },
348
204
  });
349
- const adaptor = new HostAdaptor();
350
- const store = adaptor.getHostContextStore("viewState");
351
- expect(store.getSnapshot()).toEqual({ count: 5 });
352
- });
353
- it("routes `display` to polyfill when oai is null", () => {
354
- vi.stubGlobal("openai", undefined);
355
- const adaptor = new HostAdaptor();
356
- const store = adaptor.getHostContextStore("display");
357
- expect(store.getSnapshot()).toEqual({ mode: "inline" });
358
- adaptor.openModal({});
359
- expect(store.getSnapshot()).toEqual({ mode: "modal", params: undefined });
360
- });
361
- it("routes `viewState` to local LRU state when oai is null", () => {
205
+ let adaptor = new HostAdaptor();
206
+ expect(adaptor.getHostContextStore("display").getSnapshot()).toEqual({
207
+ mode: "fullscreen",
208
+ });
209
+ expect(adaptor.getHostContextStore("viewState").getSnapshot()).toEqual({
210
+ count: 5,
211
+ });
212
+ // Other keys (theme) always flow through MCP; default fallback when no notification
213
+ expect(adaptor.getHostContextStore("theme").getSnapshot()).toBe("light");
214
+ // Polyfill / local-state path
215
+ McpAppBridge.resetInstance();
216
+ AppsSdkBridge.resetInstance();
362
217
  vi.stubGlobal("openai", undefined);
363
- const adaptor = new HostAdaptor();
364
- const store = adaptor.getHostContextStore("viewState");
365
- expect(store.getSnapshot()).toBe(null);
366
- });
367
- it("routes other keys (theme, locale, etc.) to mcp regardless of overlay", () => {
368
- vi.stubGlobal("openai", { view: { mode: "inline" } });
369
- const adaptor = new HostAdaptor();
370
- const theme = adaptor.getHostContextStore("theme");
371
- // default fallback when no notification yet
372
- expect(theme.getSnapshot()).toBe("light");
218
+ adaptor = new HostAdaptor();
219
+ expect(adaptor.getHostContextStore("display").getSnapshot()).toEqual({
220
+ mode: "inline",
221
+ });
222
+ expect(adaptor.getHostContextStore("viewState").getSnapshot()).toBe(null);
373
223
  });
374
224
  });
375
225
  //# sourceMappingURL=adaptor.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adaptor.test.js","sourceRoot":"","sources":["../../../src/web/bridges/adaptor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"./adaptor.js\";\nimport { AppsSdkBridge } from \"./apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"./mcp-app/bridge.js\";\nimport { NotSupportedError } from \"./types.js\";\n\ndescribe(\"HostAdaptor constructor\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"instantiates without window.openai (oai is null)\", () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n expect(adaptor.hasAppsSdkOverlay()).toBe(false);\n });\n\n it(\"captures window.openai when present (oai is set)\", () => {\n vi.stubGlobal(\"openai\", { widgetState: null });\n const adaptor = new HostAdaptor();\n expect(adaptor.hasAppsSdkOverlay()).toBe(true);\n });\n});\n\ndescribe(\"HostAdaptor MCP-routed methods\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n vi.stubGlobal(\"openai\", undefined);\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"callTool delegates to mcp.callServerTool\", async () => {\n const adaptor = new HostAdaptor();\n const fakeApp = {\n callServerTool: vi.fn().mockResolvedValue({\n content: [],\n structuredContent: { ok: true },\n isError: false,\n _meta: { x: 1 },\n }),\n };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n\n const result = await adaptor.callTool(\"greet\", { name: \"alice\" });\n expect(fakeApp.callServerTool).toHaveBeenCalledWith({\n name: \"greet\",\n arguments: { name: \"alice\" },\n });\n expect(result.structuredContent).toEqual({ ok: true });\n expect(result.meta).toEqual({ x: 1 });\n });\n\n it(\"requestDisplayMode delegates to mcp.requestDisplayMode\", async () => {\n const adaptor = new HostAdaptor();\n const fakeApp = {\n requestDisplayMode: vi.fn().mockResolvedValue({ mode: \"fullscreen\" }),\n };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n const r = await adaptor.requestDisplayMode(\"fullscreen\");\n expect(r.mode).toBe(\"fullscreen\");\n expect(fakeApp.requestDisplayMode).toHaveBeenCalledWith({\n mode: \"fullscreen\",\n });\n });\n\n it(\"requestClose delegates to mcp.requestTeardown\", async () => {\n const adaptor = new HostAdaptor();\n const fakeApp = { requestTeardown: vi.fn().mockResolvedValue(undefined) };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n await adaptor.requestClose();\n expect(fakeApp.requestTeardown).toHaveBeenCalled();\n });\n\n it(\"requestSize delegates to mcp.sendSizeChanged\", async () => {\n const adaptor = new HostAdaptor();\n const fakeApp = { sendSizeChanged: vi.fn().mockResolvedValue(undefined) };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n await adaptor.requestSize({ width: 100, height: 200 });\n expect(fakeApp.sendSizeChanged).toHaveBeenCalledWith({\n width: 100,\n height: 200,\n });\n });\n\n it(\"download returns isError when host lacks downloadFile capability\", async () => {\n const adaptor = new HostAdaptor();\n const fakeApp = {\n getHostCapabilities: () => ({}),\n downloadFile: vi.fn(),\n };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n const r = await adaptor.download({ contents: [] });\n expect(r.isError).toBe(true);\n expect(fakeApp.downloadFile).not.toHaveBeenCalled();\n });\n});\n\ndescribe(\"HostAdaptor conditional routing\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"sendFollowUpMessage uses oai when scrollToBottom set\", async () => {\n const sendFollowUpMessage = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", { sendFollowUpMessage });\n const adaptor = new HostAdaptor();\n await adaptor.sendFollowUpMessage(\"hi\", { scrollToBottom: false });\n expect(sendFollowUpMessage).toHaveBeenCalledWith({\n prompt: \"hi\",\n scrollToBottom: false,\n });\n });\n\n it(\"sendFollowUpMessage uses mcp when no options\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const fakeApp = { sendMessage: vi.fn().mockResolvedValue(undefined) };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n await adaptor.sendFollowUpMessage(\"hi\");\n expect(fakeApp.sendMessage).toHaveBeenCalledWith({\n role: \"user\",\n content: [{ type: \"text\", text: \"hi\" }],\n });\n });\n\n it(\"openExternal uses oai when redirectUrl: false\", async () => {\n const openExternal = vi.fn();\n vi.stubGlobal(\"openai\", { openExternal });\n const adaptor = new HostAdaptor();\n adaptor.openExternal(\"https://x\", { redirectUrl: false });\n expect(openExternal).toHaveBeenCalledWith({\n href: \"https://x\",\n redirectUrl: false,\n });\n });\n\n it(\"openExternal uses mcp.openLink for default case\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const openLink = vi.fn();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue({ openLink });\n adaptor.openExternal(\"https://x\");\n // openExternal is sync but mcp.openLink resolves async\n await new Promise((r) => setTimeout(r, 0));\n expect(openLink).toHaveBeenCalledWith({ url: \"https://x\" });\n });\n});\n\ndescribe(\"HostAdaptor Apps-SDK-only methods\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"uploadFile throws NotSupportedError when oai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n await expect(adaptor.uploadFile(new File([], \"x\"))).rejects.toThrow(\n NotSupportedError,\n );\n });\n\n it(\"uploadFile delegates to oai.uploadFile and tracks fileId\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n const uploadFile = vi\n .fn()\n .mockResolvedValue({ fileId: \"abc\", fileName: \"x\" });\n vi.stubGlobal(\"openai\", {\n uploadFile,\n setWidgetState,\n widgetState: null,\n });\n const adaptor = new HostAdaptor();\n const file = new File([], \"x\");\n const r = await adaptor.uploadFile(file, { library: true });\n expect(uploadFile).toHaveBeenCalledWith(file, { library: true });\n expect(r.fileId).toBe(\"abc\");\n expect(setWidgetState).toHaveBeenCalledWith(\n expect.objectContaining({ imageIds: [\"abc\"] }),\n );\n });\n\n it(\"selectFiles throws when oai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n await expect(adaptor.selectFiles()).rejects.toThrow(NotSupportedError);\n });\n\n it(\"selectFiles throws when host version lacks support\", async () => {\n vi.stubGlobal(\"openai\", { selectFiles: undefined });\n const adaptor = new HostAdaptor();\n await expect(adaptor.selectFiles()).rejects.toThrow(/selectFiles/);\n });\n\n it(\"getFileDownloadUrl throws when oai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n await expect(adaptor.getFileDownloadUrl({ fileId: \"x\" })).rejects.toThrow(\n NotSupportedError,\n );\n });\n\n it(\"setOpenInAppUrl throws when oai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n await expect(adaptor.setOpenInAppUrl(\"https://x\")).rejects.toThrow(\n NotSupportedError,\n );\n });\n});\n\ndescribe(\"HostAdaptor modal\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"openModal delegates to oai.requestModal when present\", () => {\n const requestModal = vi.fn();\n vi.stubGlobal(\"openai\", { requestModal });\n const adaptor = new HostAdaptor();\n adaptor.openModal({ title: \"Hi\" });\n expect(requestModal).toHaveBeenCalledWith({ title: \"Hi\" });\n });\n\n it(\"closeModal is a no-op when oai is present\", () => {\n vi.stubGlobal(\"openai\", { requestModal: vi.fn() });\n const adaptor = new HostAdaptor();\n expect(() => adaptor.closeModal()).not.toThrow();\n });\n\n it(\"openModal sets polyfill display state when oai is null\", () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const listener = vi.fn();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).polyfillDisplayListeners.add(listener);\n adaptor.openModal({ params: { x: 1 } });\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n expect((adaptor as any)._polyfillDisplay).toEqual({\n mode: \"modal\",\n params: { x: 1 },\n });\n expect(listener).toHaveBeenCalled();\n });\n\n it(\"closeModal resets polyfill display state when oai is null\", () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n adaptor.openModal({});\n adaptor.closeModal();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n expect((adaptor as any)._polyfillDisplay).toEqual({ mode: \"inline\" });\n });\n});\n\ndescribe(\"HostAdaptor setViewState\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n localStorage.clear();\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n localStorage.clear();\n });\n\n it(\"uses window.openai.setWidgetState when oai is present\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", { setWidgetState, widgetState: null });\n const adaptor = new HostAdaptor();\n await adaptor.setViewState({ count: 1 });\n expect(setWidgetState).toHaveBeenCalledWith(\n expect.objectContaining({ modelContent: { count: 1 } }),\n );\n });\n\n it(\"calls mcp.updateModelContext and writes localStorage when oai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const updateModelContext = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi\n .fn()\n .mockResolvedValue({ updateModelContext });\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any)._viewUUID = \"view-1\";\n await adaptor.setViewState({ count: 2 });\n expect(updateModelContext).toHaveBeenCalledWith({\n structuredContent: { count: 2 },\n content: [{ type: \"text\", text: JSON.stringify({ count: 2 }) }],\n });\n const keys: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key !== null) {\n keys.push(key);\n }\n }\n expect(keys.some((k) => k.endsWith(\":view-1\"))).toBe(true);\n });\n\n it(\"accepts an updater function form\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue({\n updateModelContext: vi.fn().mockResolvedValue(undefined),\n });\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any)._viewState = { count: 1 };\n await adaptor.setViewState((prev) => ({\n // biome-ignore lint/suspicious/noExplicitAny: test\n count: (prev as any).count + 1,\n }));\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n expect((adaptor as any)._viewState).toEqual({ count: 2 });\n });\n});\n\ndescribe(\"HostAdaptor getHostContextStore\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"routes `display` to oai when overlay is present\", () => {\n vi.stubGlobal(\"openai\", { view: { mode: \"fullscreen\" } });\n const adaptor = new HostAdaptor();\n const store = adaptor.getHostContextStore(\"display\");\n expect(store.getSnapshot()).toEqual({ mode: \"fullscreen\" });\n });\n\n it(\"routes `viewState` to oai.widgetState.modelContent when overlay present\", () => {\n vi.stubGlobal(\"openai\", {\n widgetState: { modelContent: { count: 5 }, privateContent: {} },\n });\n const adaptor = new HostAdaptor();\n const store = adaptor.getHostContextStore(\"viewState\");\n expect(store.getSnapshot()).toEqual({ count: 5 });\n });\n\n it(\"routes `display` to polyfill when oai is null\", () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const store = adaptor.getHostContextStore(\"display\");\n expect(store.getSnapshot()).toEqual({ mode: \"inline\" });\n adaptor.openModal({});\n expect(store.getSnapshot()).toEqual({ mode: \"modal\", params: undefined });\n });\n\n it(\"routes `viewState` to local LRU state when oai is null\", () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const store = adaptor.getHostContextStore(\"viewState\");\n expect(store.getSnapshot()).toBe(null);\n });\n\n it(\"routes other keys (theme, locale, etc.) to mcp regardless of overlay\", () => {\n vi.stubGlobal(\"openai\", { view: { mode: \"inline\" } });\n const adaptor = new HostAdaptor();\n const theme = adaptor.getHostContextStore(\"theme\");\n // default fallback when no notification yet\n expect(theme.getSnapshot()).toBe(\"light\");\n });\n});\n"]}
1
+ {"version":3,"file":"adaptor.test.js","sourceRoot":"","sources":["../../../src/web/bridges/adaptor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { VIEW_STATE_WARNING_TOKENS } from \"../../context-warnings.js\";\nimport { HostAdaptor } from \"./adaptor.js\";\nimport { AppsSdkBridge } from \"./apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"./mcp-app/bridge.js\";\nimport { NotSupportedError } from \"./types.js\";\n\ndescribe(\"HostAdaptor\", () => {\n beforeEach(() => {\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n localStorage.clear();\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n localStorage.clear();\n });\n\n it(\"callTool always routes to mcp.callServerTool\", async () => {\n vi.stubGlobal(\"openai\", { callTool: vi.fn() });\n const adaptor = new HostAdaptor();\n const fakeApp = {\n callServerTool: vi.fn().mockResolvedValue({\n content: [],\n structuredContent: { ok: true },\n isError: false,\n _meta: { x: 1 },\n }),\n };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n\n const result = await adaptor.callTool(\"greet\", { name: \"alice\" });\n expect(fakeApp.callServerTool).toHaveBeenCalledWith({\n name: \"greet\",\n arguments: { name: \"alice\" },\n });\n expect(result.structuredContent).toEqual({ ok: true });\n expect(result.meta).toEqual({ x: 1 });\n });\n\n it(\"download returns isError when host lacks downloadFile capability\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const fakeApp = {\n getHostCapabilities: () => ({}),\n downloadFile: vi.fn(),\n };\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue(fakeApp);\n const r = await adaptor.download({ contents: [] });\n expect(r.isError).toBe(true);\n expect(fakeApp.downloadFile).not.toHaveBeenCalled();\n });\n\n it(\"sendFollowUpMessage routes to window.openai only when scrollToBottom is set\", async () => {\n const sendFollowUpMessage = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", { sendFollowUpMessage });\n let adaptor = new HostAdaptor();\n await adaptor.sendFollowUpMessage(\"hi\", { scrollToBottom: false });\n expect(sendFollowUpMessage).toHaveBeenCalledWith({\n prompt: \"hi\",\n scrollToBottom: false,\n });\n\n // Default case falls through to MCP\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n adaptor = new HostAdaptor();\n const sendMessage = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue({ sendMessage });\n await adaptor.sendFollowUpMessage(\"hi\");\n expect(sendMessage).toHaveBeenCalledWith({\n role: \"user\",\n content: [{ type: \"text\", text: \"hi\" }],\n });\n });\n\n it(\"openExternal routes to window.openai only when redirectUrl: false\", async () => {\n const openExternal = vi.fn();\n vi.stubGlobal(\"openai\", { openExternal });\n let adaptor = new HostAdaptor();\n adaptor.openExternal(\"https://x\", { redirectUrl: false });\n expect(openExternal).toHaveBeenCalledWith({\n href: \"https://x\",\n redirectUrl: false,\n });\n\n // Default case falls through to MCP openLink\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n adaptor = new HostAdaptor();\n const openLink = vi.fn();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi.fn().mockResolvedValue({ openLink });\n adaptor.openExternal(\"https://x\");\n await new Promise((r) => setTimeout(r, 0));\n expect(openLink).toHaveBeenCalledWith({ url: \"https://x\" });\n });\n\n it(\"Apps-SDK-exclusive methods throw NotSupportedError when window.openai is null\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n await expect(adaptor.uploadFile(new File([], \"x\"))).rejects.toThrow(\n NotSupportedError,\n );\n await expect(adaptor.selectFiles()).rejects.toThrow(NotSupportedError);\n await expect(adaptor.getFileDownloadUrl({ fileId: \"x\" })).rejects.toThrow(\n NotSupportedError,\n );\n await expect(adaptor.setOpenInAppUrl(\"https://x\")).rejects.toThrow(\n NotSupportedError,\n );\n });\n\n it(\"uploadFile delegates to window.openai.uploadFile and tracks fileId in widgetState\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n const uploadFile = vi.fn().mockResolvedValue({\n fileId: \"abc\",\n fileName: \"x\",\n mimeType: \"image/png\",\n });\n vi.stubGlobal(\"openai\", { uploadFile, setWidgetState, widgetState: null });\n const adaptor = new HostAdaptor();\n const file = new File([], \"x\", { type: \"image/png\" });\n const r = await adaptor.uploadFile(file, { library: true });\n expect(uploadFile).toHaveBeenCalledWith(file, { library: true });\n expect(r.fileId).toBe(\"abc\");\n expect(setWidgetState).toHaveBeenCalledWith(\n expect.objectContaining({ imageIds: [\"abc\"] }),\n );\n });\n\n it(\"uploadFile does not track a non-image fileId in widgetState.imageIds\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n const uploadFile = vi.fn().mockResolvedValue({\n fileId: \"sediment://file_txt\",\n fileName: \"notes.txt\",\n mimeType: \"text/plain\",\n });\n vi.stubGlobal(\"openai\", { uploadFile, setWidgetState, widgetState: null });\n const adaptor = new HostAdaptor();\n\n await adaptor.uploadFile(new File([], \"notes.txt\", { type: \"text/plain\" }));\n\n for (const call of setWidgetState.mock.calls) {\n expect(call[0].imageIds ?? []).not.toContain(\"sediment://file_txt\");\n }\n });\n\n it(\"setViewState uses window.openai.setWidgetState when present\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", { setWidgetState, widgetState: null });\n const adaptor = new HostAdaptor();\n await adaptor.setViewState({ count: 1 });\n expect(setWidgetState).toHaveBeenCalledWith(\n expect.objectContaining({ modelContent: { count: 1 } }),\n );\n });\n\n it(\"warns when setViewState reaches 20K tokens\", async () => {\n const setWidgetState = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", { setWidgetState, widgetState: null });\n const adaptor = new HostAdaptor();\n const warnSpy = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n\n await adaptor.setViewState({\n longText: \"x\".repeat(VIEW_STATE_WARNING_TOKENS * 4),\n });\n\n expect(warnSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"setWidgetState is persisting\"),\n );\n\n warnSpy.mockRestore();\n });\n\n it(\"setViewState falls back to MCP updateModelContext + localStorage when window.openai is absent\", async () => {\n vi.stubGlobal(\"openai\", undefined);\n const adaptor = new HostAdaptor();\n const updateModelContext = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any).mcp.getApp = vi\n .fn()\n .mockResolvedValue({ updateModelContext });\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n (adaptor as any)._viewUUID = \"view-1\";\n await adaptor.setViewState({ count: 2 });\n expect(updateModelContext).toHaveBeenCalledWith({\n structuredContent: { count: 2 },\n content: [{ type: \"text\", text: JSON.stringify({ count: 2 }) }],\n });\n const keys: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key !== null) {\n keys.push(key);\n }\n }\n expect(keys.some((k) => k.endsWith(\":view-1\"))).toBe(true);\n });\n\n it(\"openModal/closeModal: delegates to window.openai.requestModal when present, polyfill state otherwise\", () => {\n const requestModal = vi.fn();\n vi.stubGlobal(\"openai\", { requestModal });\n let adaptor = new HostAdaptor();\n adaptor.openModal({ title: \"Hi\" });\n expect(requestModal).toHaveBeenCalledWith({ title: \"Hi\" });\n expect(() => adaptor.closeModal()).not.toThrow();\n\n // Polyfill path\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n adaptor = new HostAdaptor();\n adaptor.openModal({ params: { x: 1 } });\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n expect((adaptor as any)._polyfillDisplay).toEqual({\n mode: \"modal\",\n params: { x: 1 },\n });\n adaptor.closeModal();\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n expect((adaptor as any)._polyfillDisplay).toEqual({ mode: \"inline\" });\n });\n\n it(\"getHostContextStore: display/viewState route to Apps SDK overlay when present, MCP otherwise\", () => {\n vi.stubGlobal(\"openai\", {\n view: { mode: \"fullscreen\" },\n widgetState: { modelContent: { count: 5 }, privateContent: {} },\n });\n let adaptor = new HostAdaptor();\n expect(adaptor.getHostContextStore(\"display\").getSnapshot()).toEqual({\n mode: \"fullscreen\",\n });\n expect(adaptor.getHostContextStore(\"viewState\").getSnapshot()).toEqual({\n count: 5,\n });\n // Other keys (theme) always flow through MCP; default fallback when no notification\n expect(adaptor.getHostContextStore(\"theme\").getSnapshot()).toBe(\"light\");\n\n // Polyfill / local-state path\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n adaptor = new HostAdaptor();\n expect(adaptor.getHostContextStore(\"display\").getSnapshot()).toEqual({\n mode: \"inline\",\n });\n expect(adaptor.getHostContextStore(\"viewState\").getSnapshot()).toBe(null);\n });\n});\n"]}
@@ -1,4 +1,4 @@
1
- import type { Bridge, Subscribe } from "../types.js";
1
+ import type { Bridge, HostContextStore, Subscribe } from "../types.js";
2
2
  import { type AppsSdkContext } from "./types.js";
3
3
  /** @internal Singleton bridge over `window.openai` events. Used by `HostAdaptor`. */
4
4
  export declare class AppsSdkBridge implements Bridge<AppsSdkContext> {
@@ -8,4 +8,8 @@ export declare class AppsSdkBridge implements Bridge<AppsSdkContext> {
8
8
  subscribe(key: keyof AppsSdkContext): Subscribe;
9
9
  subscribe(keys: readonly (keyof AppsSdkContext)[]): Subscribe;
10
10
  getSnapshot: <K extends keyof AppsSdkContext>(key: K) => (import("./types.js").AppsSdkMethods<import("./types.js").AppsSdkWidgetState> & AppsSdkContext<Record<never, unknown>, import("../../types.js").UnknownObject, import("../../types.js").UnknownObject, import("./types.js").AppsSdkWidgetState>)[K];
11
+ createOverlayStores(): {
12
+ display: HostContextStore<"display">;
13
+ viewState: HostContextStore<"viewState">;
14
+ };
11
15
  }
@@ -42,5 +42,17 @@ export class AppsSdkBridge {
42
42
  }
43
43
  return window.openai[key];
44
44
  };
45
+ createOverlayStores() {
46
+ return {
47
+ display: {
48
+ subscribe: this.subscribe("view"),
49
+ getSnapshot: () => this.getSnapshot("view"),
50
+ },
51
+ viewState: {
52
+ subscribe: this.subscribe("widgetState"),
53
+ getSnapshot: () => this.getSnapshot("widgetState")?.modelContent ?? null,
54
+ },
55
+ };
56
+ }
45
57
  }
46
58
  //# sourceMappingURL=bridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk/bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,sBAAsB,GAEvB,MAAM,YAAY,CAAC;AAEpB,qFAAqF;AACrF,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,QAAQ,GAAyB,IAAI,CAAC;IAE9C,MAAM,CAAC,WAAW;QACvB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACpC,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAIM,SAAS,CACd,SAAmE;QAEnE,MAAM,IAAI,GAAsC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACtE,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAChB,OAAO,CAAC,QAAoB,EAAE,EAAE;YAC9B,MAAM,eAAe,GAAG,CAAC,KAAsB,EAAE,EAAE;gBACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CACjC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CACjD,CAAC;gBACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACvB,OAAO;gBACT,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC;YAEF,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,eAAe,EAAE;gBAC/D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YAEH,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAC;YACtE,CAAC,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;IAEM,WAAW,GAAG,CAAiC,GAAM,EAAE,EAAE;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,+EAA+E,GAAG,8CAA8C,CACjI,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC","sourcesContent":["import type { Bridge, Subscribe } from \"../types.js\";\nimport {\n type AppsSdkContext,\n SET_GLOBALS_EVENT_TYPE,\n type SetGlobalsEvent,\n} from \"./types.js\";\n\n/** @internal Singleton bridge over `window.openai` events. Used by `HostAdaptor`. */\nexport class AppsSdkBridge implements Bridge<AppsSdkContext> {\n private static instance: AppsSdkBridge | null = null;\n\n public static getInstance(): AppsSdkBridge {\n if (window.openai === undefined) {\n throw new Error(\n \"Apps SDK Bridge requires window.openai (Apps SDK runtime).\",\n );\n }\n if (AppsSdkBridge.instance === null) {\n AppsSdkBridge.instance = new AppsSdkBridge();\n }\n return AppsSdkBridge.instance;\n }\n\n public static resetInstance(): void {\n if (AppsSdkBridge.instance) {\n AppsSdkBridge.instance = null;\n }\n }\n\n public subscribe(key: keyof AppsSdkContext): Subscribe;\n public subscribe(keys: readonly (keyof AppsSdkContext)[]): Subscribe;\n public subscribe(\n keyOrKeys: keyof AppsSdkContext | readonly (keyof AppsSdkContext)[],\n ): Subscribe {\n const keys: readonly (keyof AppsSdkContext)[] = Array.isArray(keyOrKeys)\n ? keyOrKeys\n : [keyOrKeys];\n return (onChange: () => void) => {\n const handleSetGlobal = (event: SetGlobalsEvent) => {\n const hasRelevantChange = keys.some(\n (key) => event.detail.globals[key] !== undefined,\n );\n if (!hasRelevantChange) {\n return;\n }\n onChange();\n };\n\n window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {\n passive: true,\n });\n\n return () => {\n window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);\n };\n };\n }\n\n public getSnapshot = <K extends keyof AppsSdkContext>(key: K) => {\n if (window.openai === undefined) {\n throw new Error(\n `window.openai is not available. Make sure you're calling the hook requiring ${key} within the OpenAI iFrame skybridge runtime.`,\n );\n }\n\n return window.openai[key];\n };\n}\n"]}
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk/bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,sBAAsB,GAEvB,MAAM,YAAY,CAAC;AAEpB,qFAAqF;AACrF,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,QAAQ,GAAyB,IAAI,CAAC;IAE9C,MAAM,CAAC,WAAW;QACvB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACpC,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAIM,SAAS,CACd,SAAmE;QAEnE,MAAM,IAAI,GAAsC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACtE,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAChB,OAAO,CAAC,QAAoB,EAAE,EAAE;YAC9B,MAAM,eAAe,GAAG,CAAC,KAAsB,EAAE,EAAE;gBACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CACjC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CACjD,CAAC;gBACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACvB,OAAO;gBACT,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC;YAEF,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,eAAe,EAAE;gBAC/D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YAEH,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAC;YACtE,CAAC,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;IAEM,WAAW,GAAG,CAAiC,GAAM,EAAE,EAAE;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,+EAA+E,GAAG,8CAA8C,CACjI,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEK,mBAAmB;QAIxB,OAAO;YACL,OAAO,EAAE;gBACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;gBACjC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;aAC5C;YACD,SAAS,EAAE;gBACT,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;gBACxC,WAAW,EAAE,GAAG,EAAE,CAChB,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,YAAY,IAAI,IAAI;aACxD;SACF,CAAC;IACJ,CAAC","sourcesContent":["import type { Bridge, HostContextStore, Subscribe } from \"../types.js\";\nimport {\n type AppsSdkContext,\n SET_GLOBALS_EVENT_TYPE,\n type SetGlobalsEvent,\n} from \"./types.js\";\n\n/** @internal Singleton bridge over `window.openai` events. Used by `HostAdaptor`. */\nexport class AppsSdkBridge implements Bridge<AppsSdkContext> {\n private static instance: AppsSdkBridge | null = null;\n\n public static getInstance(): AppsSdkBridge {\n if (window.openai === undefined) {\n throw new Error(\n \"Apps SDK Bridge requires window.openai (Apps SDK runtime).\",\n );\n }\n if (AppsSdkBridge.instance === null) {\n AppsSdkBridge.instance = new AppsSdkBridge();\n }\n return AppsSdkBridge.instance;\n }\n\n public static resetInstance(): void {\n if (AppsSdkBridge.instance) {\n AppsSdkBridge.instance = null;\n }\n }\n\n public subscribe(key: keyof AppsSdkContext): Subscribe;\n public subscribe(keys: readonly (keyof AppsSdkContext)[]): Subscribe;\n public subscribe(\n keyOrKeys: keyof AppsSdkContext | readonly (keyof AppsSdkContext)[],\n ): Subscribe {\n const keys: readonly (keyof AppsSdkContext)[] = Array.isArray(keyOrKeys)\n ? keyOrKeys\n : [keyOrKeys];\n return (onChange: () => void) => {\n const handleSetGlobal = (event: SetGlobalsEvent) => {\n const hasRelevantChange = keys.some(\n (key) => event.detail.globals[key] !== undefined,\n );\n if (!hasRelevantChange) {\n return;\n }\n onChange();\n };\n\n window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {\n passive: true,\n });\n\n return () => {\n window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);\n };\n };\n }\n\n public getSnapshot = <K extends keyof AppsSdkContext>(key: K) => {\n if (window.openai === undefined) {\n throw new Error(\n `window.openai is not available. Make sure you're calling the hook requiring ${key} within the OpenAI iFrame skybridge runtime.`,\n );\n }\n\n return window.openai[key];\n };\n\n public createOverlayStores(): {\n display: HostContextStore<\"display\">;\n viewState: HostContextStore<\"viewState\">;\n } {\n return {\n display: {\n subscribe: this.subscribe(\"view\"),\n getSnapshot: () => this.getSnapshot(\"view\"),\n },\n viewState: {\n subscribe: this.subscribe(\"widgetState\"),\n getSnapshot: () =>\n this.getSnapshot(\"widgetState\")?.modelContent ?? null,\n },\n };\n }\n}\n"]}
@@ -2,7 +2,7 @@ import type { AppsSdkContext } from "./types.js";
2
2
  /**
3
3
  * Read a single key from the raw Apps SDK (`window.openai`) context.
4
4
  *
5
- * Advanced escape hatch — prefer the cross-host hooks (`useLayout`, `useUser`,
5
+ * Advanced escape hatch — prefer the cross-host hooks (`useViewport`, `useUser`,
6
6
  * `useToolInfo`, etc.) which work in both Apps SDK and MCP Apps. Reach for
7
7
  * this when you need ChatGPT-only fields not surfaced by the public hooks.
8
8
  *