skybridge 0.0.0-dev.f3fc72c → 0.0.0-dev.f40327b

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 (475) hide show
  1. package/README.md +152 -0
  2. package/bin/run.js +5 -0
  3. package/dist/cli/detect-port.d.ts +18 -0
  4. package/dist/cli/detect-port.js +61 -0
  5. package/dist/cli/detect-port.js.map +1 -0
  6. package/dist/cli/header.d.ts +4 -0
  7. package/dist/cli/header.js +6 -0
  8. package/dist/cli/header.js.map +1 -0
  9. package/dist/cli/run-command.d.ts +2 -0
  10. package/dist/cli/run-command.js +43 -0
  11. package/dist/cli/run-command.js.map +1 -0
  12. package/dist/cli/telemetry.d.ts +7 -0
  13. package/dist/cli/telemetry.js +123 -0
  14. package/dist/cli/telemetry.js.map +1 -0
  15. package/dist/cli/tunnel-control-server.d.ts +9 -0
  16. package/dist/cli/tunnel-control-server.js +31 -0
  17. package/dist/cli/tunnel-control-server.js.map +1 -0
  18. package/dist/cli/tunnel-control-server.test.js +39 -0
  19. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  20. package/dist/cli/tunnel-handler.d.ts +3 -0
  21. package/dist/cli/tunnel-handler.js +48 -0
  22. package/dist/cli/tunnel-handler.js.map +1 -0
  23. package/dist/cli/tunnel-handler.test.js +105 -0
  24. package/dist/cli/tunnel-handler.test.js.map +1 -0
  25. package/dist/cli/tunnel.d.ts +57 -0
  26. package/dist/cli/tunnel.js +154 -0
  27. package/dist/cli/tunnel.js.map +1 -0
  28. package/dist/cli/tunnel.test.js +190 -0
  29. package/dist/cli/tunnel.test.js.map +1 -0
  30. package/dist/cli/types.d.ts +5 -0
  31. package/dist/cli/types.js.map +1 -0
  32. package/dist/cli/use-execute-steps.d.ts +11 -0
  33. package/dist/cli/use-execute-steps.js +36 -0
  34. package/dist/cli/use-execute-steps.js.map +1 -0
  35. package/dist/cli/use-messages.d.ts +3 -0
  36. package/dist/cli/use-messages.js +11 -0
  37. package/dist/cli/use-messages.js.map +1 -0
  38. package/dist/cli/use-nodemon.d.ts +2 -0
  39. package/dist/cli/use-nodemon.js +73 -0
  40. package/dist/cli/use-nodemon.js.map +1 -0
  41. package/dist/cli/use-open-browser.d.ts +1 -0
  42. package/dist/cli/use-open-browser.js +44 -0
  43. package/dist/cli/use-open-browser.js.map +1 -0
  44. package/dist/cli/use-tunnel.d.ts +14 -0
  45. package/dist/cli/use-tunnel.js +131 -0
  46. package/dist/cli/use-tunnel.js.map +1 -0
  47. package/dist/cli/use-typescript-check.d.ts +9 -0
  48. package/dist/cli/use-typescript-check.js +94 -0
  49. package/dist/cli/use-typescript-check.js.map +1 -0
  50. package/dist/commands/build.d.ts +9 -0
  51. package/dist/commands/build.js +102 -0
  52. package/dist/commands/build.js.map +1 -0
  53. package/dist/commands/create.d.ts +9 -0
  54. package/dist/commands/create.js +30 -0
  55. package/dist/commands/create.js.map +1 -0
  56. package/dist/commands/dev.d.ts +12 -0
  57. package/dist/commands/dev.js +80 -0
  58. package/dist/commands/dev.js.map +1 -0
  59. package/dist/commands/start.d.ts +9 -0
  60. package/dist/commands/start.js +49 -0
  61. package/dist/commands/start.js.map +1 -0
  62. package/dist/commands/telemetry/disable.d.ts +5 -0
  63. package/dist/commands/telemetry/disable.js +14 -0
  64. package/dist/commands/telemetry/disable.js.map +1 -0
  65. package/dist/commands/telemetry/enable.d.ts +5 -0
  66. package/dist/commands/telemetry/enable.js +14 -0
  67. package/dist/commands/telemetry/enable.js.map +1 -0
  68. package/dist/commands/telemetry/status.d.ts +5 -0
  69. package/dist/commands/telemetry/status.js +14 -0
  70. package/dist/commands/telemetry/status.js.map +1 -0
  71. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  72. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  73. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  74. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  75. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  76. package/dist/server/auth.d.ts +20 -0
  77. package/dist/server/auth.js +28 -0
  78. package/dist/server/auth.js.map +1 -0
  79. package/dist/server/content-helpers.d.ts +67 -0
  80. package/dist/server/content-helpers.js +79 -0
  81. package/dist/server/content-helpers.js.map +1 -0
  82. package/dist/server/content-helpers.test.js +70 -0
  83. package/dist/server/content-helpers.test.js.map +1 -0
  84. package/dist/server/express.d.ts +11 -0
  85. package/dist/server/express.js +101 -0
  86. package/dist/server/express.js.map +1 -0
  87. package/dist/server/express.test.js +430 -0
  88. package/dist/server/express.test.js.map +1 -0
  89. package/dist/server/file-ref.d.ts +28 -0
  90. package/dist/server/file-ref.js +27 -0
  91. package/dist/server/file-ref.js.map +1 -0
  92. package/dist/server/index.d.ts +8 -0
  93. package/dist/server/index.js +6 -0
  94. package/dist/server/index.js.map +1 -0
  95. package/dist/{src/server → server}/inferUtilityTypes.d.ts +6 -6
  96. package/dist/server/inferUtilityTypes.js.map +1 -0
  97. package/dist/server/metric.d.ts +14 -0
  98. package/dist/server/metric.js +62 -0
  99. package/dist/server/metric.js.map +1 -0
  100. package/dist/server/middleware.d.ts +137 -0
  101. package/dist/server/middleware.js +93 -0
  102. package/dist/server/middleware.js.map +1 -0
  103. package/dist/server/middleware.test-d.js +75 -0
  104. package/dist/server/middleware.test-d.js.map +1 -0
  105. package/dist/server/middleware.test.js +493 -0
  106. package/dist/server/middleware.test.js.map +1 -0
  107. package/dist/server/server.d.ts +398 -0
  108. package/dist/server/server.js +561 -0
  109. package/dist/server/server.js.map +1 -0
  110. package/dist/{src/server → server}/templateHelper.d.ts +5 -7
  111. package/dist/server/templateHelper.js +11 -0
  112. package/dist/server/templateHelper.js.map +1 -0
  113. package/dist/server/templates.generated.d.ts +4 -0
  114. package/dist/server/templates.generated.js +47 -0
  115. package/dist/server/templates.generated.js.map +1 -0
  116. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  117. package/dist/server/tunnel-proxy-router.js +110 -0
  118. package/dist/server/tunnel-proxy-router.js.map +1 -0
  119. package/dist/server/tunnel-proxy-router.test.js +229 -0
  120. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  121. package/dist/server/viewsDevServer.d.ts +14 -0
  122. package/dist/server/viewsDevServer.js +45 -0
  123. package/dist/server/viewsDevServer.js.map +1 -0
  124. package/dist/{src/test → test}/utils.d.ts +13 -21
  125. package/dist/{src/test → test}/utils.js +42 -37
  126. package/dist/test/utils.js.map +1 -0
  127. package/dist/test/view.test.js +568 -0
  128. package/dist/test/view.test.js.map +1 -0
  129. package/dist/version.d.ts +1 -0
  130. package/dist/version.js +3 -0
  131. package/dist/version.js.map +1 -0
  132. package/dist/web/bridges/apps-sdk/adaptor.d.ts +28 -0
  133. package/dist/web/bridges/apps-sdk/adaptor.js +113 -0
  134. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  135. package/dist/web/bridges/apps-sdk/bridge.d.ts +11 -0
  136. package/dist/{src/web/bridges/apps-sdk-bridge.js → web/bridges/apps-sdk/bridge.js} +3 -2
  137. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  138. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  139. package/dist/web/bridges/apps-sdk/index.js +5 -0
  140. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  141. package/dist/web/bridges/apps-sdk/types.d.ts +133 -0
  142. package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -1
  143. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  144. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +13 -0
  145. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +18 -0
  146. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  147. package/dist/web/bridges/get-adaptor.d.ts +9 -0
  148. package/dist/web/bridges/get-adaptor.js +15 -0
  149. package/dist/web/bridges/get-adaptor.js.map +1 -0
  150. package/dist/web/bridges/index.d.ts +5 -0
  151. package/dist/web/bridges/index.js +6 -0
  152. package/dist/web/bridges/index.js.map +1 -0
  153. package/dist/web/bridges/mcp-app/adaptor.d.ts +52 -0
  154. package/dist/web/bridges/mcp-app/adaptor.js +280 -0
  155. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  156. package/dist/web/bridges/mcp-app/bridge.d.ts +27 -0
  157. package/dist/web/bridges/mcp-app/bridge.js +103 -0
  158. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  159. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  160. package/dist/web/bridges/mcp-app/index.js +4 -0
  161. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  162. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  163. package/dist/web/bridges/mcp-app/types.js +2 -0
  164. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  165. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +19 -0
  166. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +19 -0
  167. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  168. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
  169. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  170. package/dist/web/bridges/types.d.ts +171 -0
  171. package/dist/web/bridges/types.js +2 -0
  172. package/dist/web/bridges/types.js.map +1 -0
  173. package/dist/web/bridges/use-host-context.d.ts +7 -0
  174. package/dist/web/bridges/use-host-context.js +13 -0
  175. package/dist/web/bridges/use-host-context.js.map +1 -0
  176. package/dist/web/components/modal-provider.d.ts +4 -0
  177. package/dist/web/components/modal-provider.js +45 -0
  178. package/dist/web/components/modal-provider.js.map +1 -0
  179. package/dist/web/create-store.d.ts +29 -0
  180. package/dist/web/create-store.js +64 -0
  181. package/dist/web/create-store.js.map +1 -0
  182. package/dist/web/create-store.test.js +129 -0
  183. package/dist/web/create-store.test.js.map +1 -0
  184. package/dist/web/data-llm.d.ts +47 -0
  185. package/dist/{src/web → web}/data-llm.js +35 -5
  186. package/dist/web/data-llm.js.map +1 -0
  187. package/dist/web/data-llm.test.js +142 -0
  188. package/dist/web/data-llm.test.js.map +1 -0
  189. package/dist/{src/web → web}/generate-helpers.d.ts +24 -19
  190. package/dist/{src/web → web}/generate-helpers.js +22 -18
  191. package/dist/web/generate-helpers.js.map +1 -0
  192. package/dist/{src/web → web}/generate-helpers.test-d.js +26 -26
  193. package/dist/web/generate-helpers.test-d.js.map +1 -0
  194. package/dist/web/generate-helpers.test.js.map +1 -0
  195. package/dist/{src/web → web}/helpers/state.d.ts +2 -2
  196. package/dist/web/helpers/state.js +45 -0
  197. package/dist/web/helpers/state.js.map +1 -0
  198. package/dist/{src/web → web}/helpers/state.test.js +9 -9
  199. package/dist/web/helpers/state.test.js.map +1 -0
  200. package/dist/{src/web → web}/hooks/index.d.ts +6 -3
  201. package/dist/{src/web → web}/hooks/index.js +5 -2
  202. package/dist/web/hooks/index.js.map +1 -0
  203. package/dist/web/hooks/test/utils.d.ts +20 -0
  204. package/dist/web/hooks/test/utils.js +75 -0
  205. package/dist/web/hooks/test/utils.js.map +1 -0
  206. package/dist/{src/web → web}/hooks/use-call-tool.d.ts +48 -2
  207. package/dist/{src/web → web}/hooks/use-call-tool.js +30 -2
  208. package/dist/web/hooks/use-call-tool.js.map +1 -0
  209. package/dist/{src/web → web}/hooks/use-call-tool.test-d.js +1 -1
  210. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  211. package/dist/{src/web → web}/hooks/use-call-tool.test.js +30 -9
  212. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  213. package/dist/web/hooks/use-display-mode.d.ts +24 -0
  214. package/dist/web/hooks/use-display-mode.js +29 -0
  215. package/dist/web/hooks/use-display-mode.js.map +1 -0
  216. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  217. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  218. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  219. package/dist/web/hooks/use-download.d.ts +5 -0
  220. package/dist/web/hooks/use-download.js +8 -0
  221. package/dist/web/hooks/use-download.js.map +1 -0
  222. package/dist/web/hooks/use-download.test.d.ts +1 -0
  223. package/dist/web/hooks/use-download.test.js +95 -0
  224. package/dist/web/hooks/use-download.test.js.map +1 -0
  225. package/dist/web/hooks/use-files.d.ts +39 -0
  226. package/dist/web/hooks/use-files.js +42 -0
  227. package/dist/web/hooks/use-files.js.map +1 -0
  228. package/dist/web/hooks/use-files.test.d.ts +1 -0
  229. package/dist/web/hooks/use-files.test.js +54 -0
  230. package/dist/web/hooks/use-files.test.js.map +1 -0
  231. package/dist/{src/web → web}/hooks/use-layout.d.ts +4 -2
  232. package/dist/{src/web → web}/hooks/use-layout.js +6 -4
  233. package/dist/web/hooks/use-layout.js.map +1 -0
  234. package/dist/web/hooks/use-layout.test.d.ts +1 -0
  235. package/dist/{src/web → web}/hooks/use-layout.test.js +7 -6
  236. package/dist/web/hooks/use-layout.test.js.map +1 -0
  237. package/dist/web/hooks/use-open-external.d.ts +20 -0
  238. package/dist/web/hooks/use-open-external.js +24 -0
  239. package/dist/web/hooks/use-open-external.js.map +1 -0
  240. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  241. package/dist/{src/web → web}/hooks/use-open-external.test.js +27 -12
  242. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  243. package/dist/web/hooks/use-request-close.d.ts +16 -0
  244. package/dist/web/hooks/use-request-close.js +21 -0
  245. package/dist/web/hooks/use-request-close.js.map +1 -0
  246. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  247. package/dist/web/hooks/use-request-close.test.js +52 -0
  248. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  249. package/dist/web/hooks/use-request-modal.d.ts +24 -0
  250. package/dist/web/hooks/use-request-modal.js +31 -0
  251. package/dist/web/hooks/use-request-modal.js.map +1 -0
  252. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  253. package/dist/{src/web → web}/hooks/use-request-modal.test.js +5 -1
  254. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  255. package/dist/web/hooks/use-request-size.d.ts +20 -0
  256. package/dist/web/hooks/use-request-size.js +24 -0
  257. package/dist/web/hooks/use-request-size.js.map +1 -0
  258. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  259. package/dist/web/hooks/use-request-size.test.js +65 -0
  260. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  261. package/dist/web/hooks/use-send-follow-up-message.d.ts +19 -0
  262. package/dist/web/hooks/use-send-follow-up-message.js +25 -0
  263. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  264. package/dist/web/hooks/use-set-open-in-app-url.d.ts +18 -0
  265. package/dist/web/hooks/use-set-open-in-app-url.js +25 -0
  266. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  267. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  268. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  269. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  270. package/dist/web/hooks/use-tool-info.d.ts +69 -0
  271. package/dist/web/hooks/use-tool-info.js +52 -0
  272. package/dist/web/hooks/use-tool-info.js.map +1 -0
  273. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  274. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  275. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  276. package/dist/{src/web → web}/hooks/use-tool-info.test.js +5 -5
  277. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  278. package/dist/{src/web → web}/hooks/use-user.d.ts +3 -1
  279. package/dist/web/hooks/use-user.js +37 -0
  280. package/dist/web/hooks/use-user.js.map +1 -0
  281. package/dist/web/hooks/use-user.test.d.ts +1 -0
  282. package/dist/{src/web → web}/hooks/use-user.test.js +33 -4
  283. package/dist/web/hooks/use-user.test.js.map +1 -0
  284. package/dist/web/hooks/use-view-state.d.ts +25 -0
  285. package/dist/web/hooks/use-view-state.js +32 -0
  286. package/dist/web/hooks/use-view-state.js.map +1 -0
  287. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  288. package/dist/web/hooks/use-view-state.test.js +177 -0
  289. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  290. package/dist/{src/web → web}/index.d.ts +1 -2
  291. package/dist/{src/web → web}/index.js +1 -2
  292. package/dist/web/index.js.map +1 -0
  293. package/dist/web/mount-view.d.ts +20 -0
  294. package/dist/web/mount-view.js +46 -0
  295. package/dist/web/mount-view.js.map +1 -0
  296. package/dist/web/plugin/data-llm.test.d.ts +1 -0
  297. package/dist/web/plugin/data-llm.test.js.map +1 -0
  298. package/dist/web/plugin/plugin.d.ts +33 -0
  299. package/dist/web/plugin/plugin.js +189 -0
  300. package/dist/web/plugin/plugin.js.map +1 -0
  301. package/dist/web/plugin/scan-views.d.ts +16 -0
  302. package/dist/web/plugin/scan-views.js +88 -0
  303. package/dist/web/plugin/scan-views.js.map +1 -0
  304. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  305. package/dist/web/plugin/scan-views.test.js +99 -0
  306. package/dist/web/plugin/scan-views.test.js.map +1 -0
  307. package/dist/{src/web → web}/plugin/transform-data-llm.js +1 -1
  308. package/dist/web/plugin/transform-data-llm.js.map +1 -0
  309. package/dist/web/plugin/transform-data-llm.test.d.ts +1 -0
  310. package/dist/web/plugin/transform-data-llm.test.js.map +1 -0
  311. package/dist/web/plugin/validate-view.d.ts +1 -0
  312. package/dist/web/plugin/validate-view.js +9 -0
  313. package/dist/web/plugin/validate-view.js.map +1 -0
  314. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  315. package/dist/web/plugin/validate-view.test.js +24 -0
  316. package/dist/web/plugin/validate-view.test.js.map +1 -0
  317. package/dist/{src/web → web}/proxy.js +0 -1
  318. package/dist/web/proxy.js.map +1 -0
  319. package/dist/web/types.d.ts +20 -0
  320. package/dist/web/types.js +2 -0
  321. package/dist/web/types.js.map +1 -0
  322. package/package.json +70 -30
  323. package/tsconfig.base.json +33 -0
  324. package/dist/src/server/index.d.ts +0 -4
  325. package/dist/src/server/index.js +0 -3
  326. package/dist/src/server/index.js.map +0 -1
  327. package/dist/src/server/inferUtilityTypes.js.map +0 -1
  328. package/dist/src/server/server.d.ts +0 -101
  329. package/dist/src/server/server.js +0 -120
  330. package/dist/src/server/server.js.map +0 -1
  331. package/dist/src/server/templateHelper.js +0 -30
  332. package/dist/src/server/templateHelper.js.map +0 -1
  333. package/dist/src/server/templates/development.hbs +0 -66
  334. package/dist/src/server/templates/production.hbs +0 -7
  335. package/dist/src/server/widgetsDevServer.d.ts +0 -12
  336. package/dist/src/server/widgetsDevServer.js +0 -47
  337. package/dist/src/server/widgetsDevServer.js.map +0 -1
  338. package/dist/src/test/utils.js.map +0 -1
  339. package/dist/src/test/widget.test.js +0 -237
  340. package/dist/src/test/widget.test.js.map +0 -1
  341. package/dist/src/web/bridges/adaptors/apps-sdk-adaptor.d.ts +0 -13
  342. package/dist/src/web/bridges/adaptors/apps-sdk-adaptor.js +0 -33
  343. package/dist/src/web/bridges/adaptors/apps-sdk-adaptor.js.map +0 -1
  344. package/dist/src/web/bridges/adaptors/mcp-app-adaptor.d.ts +0 -16
  345. package/dist/src/web/bridges/adaptors/mcp-app-adaptor.js +0 -115
  346. package/dist/src/web/bridges/adaptors/mcp-app-adaptor.js.map +0 -1
  347. package/dist/src/web/bridges/apps-sdk-bridge.d.ts +0 -10
  348. package/dist/src/web/bridges/apps-sdk-bridge.js.map +0 -1
  349. package/dist/src/web/bridges/hooks/use-adaptor.d.ts +0 -2
  350. package/dist/src/web/bridges/hooks/use-adaptor.js +0 -8
  351. package/dist/src/web/bridges/hooks/use-adaptor.js.map +0 -1
  352. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.d.ts +0 -2
  353. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js +0 -7
  354. package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js.map +0 -1
  355. package/dist/src/web/bridges/hooks/use-bridge.d.ts +0 -2
  356. package/dist/src/web/bridges/hooks/use-bridge.js +0 -8
  357. package/dist/src/web/bridges/hooks/use-bridge.js.map +0 -1
  358. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.d.ts +0 -5
  359. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js +0 -7
  360. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js.map +0 -1
  361. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js +0 -41
  362. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js.map +0 -1
  363. package/dist/src/web/bridges/index.d.ts +0 -4
  364. package/dist/src/web/bridges/index.js +0 -5
  365. package/dist/src/web/bridges/index.js.map +0 -1
  366. package/dist/src/web/bridges/mcp-app-bridge.d.ts +0 -38
  367. package/dist/src/web/bridges/mcp-app-bridge.js +0 -162
  368. package/dist/src/web/bridges/mcp-app-bridge.js.map +0 -1
  369. package/dist/src/web/bridges/types.d.ts +0 -57
  370. package/dist/src/web/bridges/types.js.map +0 -1
  371. package/dist/src/web/create-store.d.ts +0 -3
  372. package/dist/src/web/create-store.js +0 -25
  373. package/dist/src/web/create-store.js.map +0 -1
  374. package/dist/src/web/create-store.test.js +0 -70
  375. package/dist/src/web/create-store.test.js.map +0 -1
  376. package/dist/src/web/data-llm.d.ts +0 -14
  377. package/dist/src/web/data-llm.js.map +0 -1
  378. package/dist/src/web/data-llm.test.js +0 -76
  379. package/dist/src/web/data-llm.test.js.map +0 -1
  380. package/dist/src/web/generate-helpers.js.map +0 -1
  381. package/dist/src/web/generate-helpers.test-d.js.map +0 -1
  382. package/dist/src/web/generate-helpers.test.js.map +0 -1
  383. package/dist/src/web/helpers/state.js +0 -40
  384. package/dist/src/web/helpers/state.js.map +0 -1
  385. package/dist/src/web/helpers/state.test.js.map +0 -1
  386. package/dist/src/web/hooks/index.js.map +0 -1
  387. package/dist/src/web/hooks/test/utils.d.ts +0 -10
  388. package/dist/src/web/hooks/test/utils.js +0 -40
  389. package/dist/src/web/hooks/test/utils.js.map +0 -1
  390. package/dist/src/web/hooks/use-call-tool.js.map +0 -1
  391. package/dist/src/web/hooks/use-call-tool.test-d.js.map +0 -1
  392. package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
  393. package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
  394. package/dist/src/web/hooks/use-display-mode.js +0 -10
  395. package/dist/src/web/hooks/use-display-mode.js.map +0 -1
  396. package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
  397. package/dist/src/web/hooks/use-files.d.ts +0 -10
  398. package/dist/src/web/hooks/use-files.js +0 -7
  399. package/dist/src/web/hooks/use-files.js.map +0 -1
  400. package/dist/src/web/hooks/use-files.test.js +0 -29
  401. package/dist/src/web/hooks/use-files.test.js.map +0 -1
  402. package/dist/src/web/hooks/use-layout.js.map +0 -1
  403. package/dist/src/web/hooks/use-layout.test.js.map +0 -1
  404. package/dist/src/web/hooks/use-open-external.d.ts +0 -1
  405. package/dist/src/web/hooks/use-open-external.js +0 -8
  406. package/dist/src/web/hooks/use-open-external.js.map +0 -1
  407. package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
  408. package/dist/src/web/hooks/use-openai-global.d.ts +0 -3
  409. package/dist/src/web/hooks/use-openai-global.js +0 -6
  410. package/dist/src/web/hooks/use-openai-global.js.map +0 -1
  411. package/dist/src/web/hooks/use-request-modal.d.ts +0 -9
  412. package/dist/src/web/hooks/use-request-modal.js +0 -14
  413. package/dist/src/web/hooks/use-request-modal.js.map +0 -1
  414. package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
  415. package/dist/src/web/hooks/use-send-follow-up-message.d.ts +0 -1
  416. package/dist/src/web/hooks/use-send-follow-up-message.js +0 -8
  417. package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
  418. package/dist/src/web/hooks/use-tool-info.d.ts +0 -36
  419. package/dist/src/web/hooks/use-tool-info.js +0 -26
  420. package/dist/src/web/hooks/use-tool-info.js.map +0 -1
  421. package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
  422. package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
  423. package/dist/src/web/hooks/use-user.js +0 -19
  424. package/dist/src/web/hooks/use-user.js.map +0 -1
  425. package/dist/src/web/hooks/use-user.test.js.map +0 -1
  426. package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
  427. package/dist/src/web/hooks/use-widget-state.js +0 -32
  428. package/dist/src/web/hooks/use-widget-state.js.map +0 -1
  429. package/dist/src/web/hooks/use-widget-state.test.js +0 -61
  430. package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
  431. package/dist/src/web/index.js.map +0 -1
  432. package/dist/src/web/mount-widget.d.ts +0 -1
  433. package/dist/src/web/mount-widget.js +0 -19
  434. package/dist/src/web/mount-widget.js.map +0 -1
  435. package/dist/src/web/plugin/data-llm.test.js.map +0 -1
  436. package/dist/src/web/plugin/plugin.d.ts +0 -2
  437. package/dist/src/web/plugin/plugin.js +0 -39
  438. package/dist/src/web/plugin/plugin.js.map +0 -1
  439. package/dist/src/web/plugin/transform-data-llm.js.map +0 -1
  440. package/dist/src/web/plugin/transform-data-llm.test.js.map +0 -1
  441. package/dist/src/web/proxy.js.map +0 -1
  442. package/dist/src/web/types.d.ts +0 -149
  443. package/dist/src/web/types.js.map +0 -1
  444. package/dist/vitest.config.d.ts +0 -2
  445. package/dist/vitest.config.js +0 -8
  446. package/dist/vitest.config.js.map +0 -1
  447. /package/dist/{src/test/widget.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  448. /package/dist/{src/web/bridges/hooks/use-mcp-app-bridge.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  449. /package/dist/{src/web/create-store.test.d.ts → cli/tunnel.test.d.ts} +0 -0
  450. /package/dist/{src/web/bridges → cli}/types.js +0 -0
  451. /package/dist/{src/web/data-llm.test.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
  452. /package/dist/{src/web/generate-helpers.test-d.d.ts → server/content-helpers.test.d.ts} +0 -0
  453. /package/dist/{src/web/generate-helpers.test.d.ts → server/express.test.d.ts} +0 -0
  454. /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
  455. /package/dist/{src/web/helpers/state.test.d.ts → server/middleware.test-d.d.ts} +0 -0
  456. /package/dist/{src/web/hooks/use-call-tool.test-d.d.ts → server/middleware.test.d.ts} +0 -0
  457. /package/dist/{src/web/hooks/use-call-tool.test.d.ts → server/tunnel-proxy-router.test.d.ts} +0 -0
  458. /package/dist/{src/web/hooks/use-display-mode.test.d.ts → test/view.test.d.ts} +0 -0
  459. /package/dist/{src/web/hooks/use-files.test.d.ts → web/bridges/mcp-app/use-mcp-app-context.test.d.ts} +0 -0
  460. /package/dist/{src/web/hooks/use-layout.test.d.ts → web/create-store.test.d.ts} +0 -0
  461. /package/dist/{src/web/plugin → web}/data-llm.test.d.ts +0 -0
  462. /package/dist/{src/web/hooks/use-open-external.test.d.ts → web/generate-helpers.test-d.d.ts} +0 -0
  463. /package/dist/{src/web/hooks/use-request-modal.test.d.ts → web/generate-helpers.test.d.ts} +0 -0
  464. /package/dist/{src/web → web}/generate-helpers.test.js +0 -0
  465. /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → web/helpers/state.test.d.ts} +0 -0
  466. /package/dist/{src/web/hooks/use-tool-info.test.d.ts → web/hooks/use-call-tool.test-d.d.ts} +0 -0
  467. /package/dist/{src/web/hooks/use-user.test.d.ts → web/hooks/use-call-tool.test.d.ts} +0 -0
  468. /package/dist/{src/web/hooks/use-widget-state.test.d.ts → web/hooks/use-display-mode.test-d.d.ts} +0 -0
  469. /package/dist/{src/web/plugin/transform-data-llm.test.d.ts → web/hooks/use-display-mode.test.d.ts} +0 -0
  470. /package/dist/{src/web → web}/hooks/use-display-mode.test.js +0 -0
  471. /package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +0 -0
  472. /package/dist/{src/web → web}/plugin/data-llm.test.js +0 -0
  473. /package/dist/{src/web → web}/plugin/transform-data-llm.d.ts +0 -0
  474. /package/dist/{src/web → web}/plugin/transform-data-llm.test.js +0 -0
  475. /package/dist/{src/web → web}/proxy.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-llm.js","sourceRoot":"","sources":["../../src/web/data-llm.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useId,\n} from \"react\";\nimport { getAdaptor } from \"./bridges/index.js\";\n\n/** Text content surfaced to the model by a {@link DataLLM} component. */\nexport type DataLLMContent = string;\n\n/**\n * A node in the {@link DataLLM} tree. Nested `<DataLLM>` elements form a\n * hierarchy that is serialized as an indented bullet list for the model.\n */\nexport interface DataLLMNode {\n id: string;\n parentId: string | null;\n content: string | null;\n}\n\n/**\n * Key under which the serialized {@link DataLLM} tree is persisted on the\n * host's `viewState`. The host exposes the value to the model on subsequent\n * turns.\n */\nexport const VIEW_CONTEXT_KEY = \"__view_context\" as const;\n\nconst nodes = new Map<string, DataLLMNode>();\n\nfunction setNode(node: DataLLMNode) {\n nodes.set(node.id, node);\n onChange();\n}\n\nfunction removeNode(id: string) {\n nodes.delete(id);\n onChange();\n}\n\nfunction onChange() {\n const description = getLLMDescriptionString();\n const adaptor = getAdaptor();\n adaptor.setViewState((prevState) => ({\n ...prevState,\n [VIEW_CONTEXT_KEY]: description,\n }));\n}\n\nconst ParentIdContext = createContext<string | null>(null);\n\ninterface DataLLMProps {\n content: DataLLMContent | null | undefined;\n children?: ReactNode;\n}\n\n/**\n * Surface in-view content to the LLM so it can reason about what the user is\n * seeing without an extra tool call.\n *\n * Each `<DataLLM>` registers `content` as a node in a tree (parented by any\n * enclosing `<DataLLM>`). The flattened tree is serialized as an indented\n * bullet list and persisted on the host's `viewState` under\n * {@link VIEW_CONTEXT_KEY}; the host then surfaces it to the model as part of\n * the next turn's context.\n *\n * Pass `null`/`undefined` for `content` to register only as a structural\n * parent (useful for grouping).\n *\n * @example\n * ```tsx\n * <DataLLM content=\"Active filters\">\n * <DataLLM content={`Sort: ${sort}`} />\n * <DataLLM content={`Page: ${page}`} />\n * </DataLLM>\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/data-llm\n */\nexport function DataLLM({ content, children }: DataLLMProps) {\n const parentId = useContext(ParentIdContext);\n const id = useId();\n\n useEffect(() => {\n if (content) {\n setNode({\n id,\n parentId,\n content,\n });\n } else {\n removeNode(id);\n }\n\n return () => {\n removeNode(id);\n };\n }, [id, parentId, content]);\n\n return (\n <ParentIdContext.Provider value={id}>{children}</ParentIdContext.Provider>\n );\n}\n\nfunction getLLMDescriptionString(): string {\n const byParent = new Map<string | null, DataLLMNode[]>();\n for (const node of Array.from(nodes.values())) {\n const key = node.parentId ?? null;\n if (!byParent.has(key)) {\n byParent.set(key, []);\n }\n byParent.get(key)?.push(node);\n }\n\n for (const list of byParent.values()) {\n list.sort((a, b) => a.id.localeCompare(b.id));\n }\n\n const lines: string[] = [];\n\n function traverseTree(parentId: string | null, depth: number) {\n const children = byParent.get(parentId);\n if (!children) {\n return;\n }\n\n for (const child of children) {\n if (child.content?.trim()) {\n const indent = \" \".repeat(depth);\n lines.push(`${indent}- ${child.content.trim()}`);\n }\n traverseTree(child.id, depth + 1);\n }\n }\n\n traverseTree(null, 0);\n\n return lines.join(\"\\n\");\n}\n"]}
@@ -0,0 +1,142 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { cleanup, render } from "@testing-library/react";
3
+ import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
4
+ import { McpAppAdaptor, McpAppBridge } from "./bridges/mcp-app/index.js";
5
+ import { DataLLM } from "./data-llm.js";
6
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./hooks/test/utils.js";
7
+ describe("DataLLM", () => {
8
+ afterEach(() => {
9
+ // Clean up React components BEFORE unstubbing globals
10
+ cleanup();
11
+ vi.unstubAllGlobals();
12
+ vi.resetAllMocks();
13
+ });
14
+ describe("apps-sdk mode", () => {
15
+ let OpenaiMock;
16
+ beforeEach(() => {
17
+ OpenaiMock = {
18
+ widgetState: { modelContent: {} },
19
+ setWidgetState: vi.fn(),
20
+ };
21
+ // Use Object.defineProperty to ensure it persists
22
+ Object.defineProperty(globalThis, "openai", {
23
+ value: OpenaiMock,
24
+ writable: true,
25
+ configurable: true,
26
+ });
27
+ // Also set on window for browser-like environment
28
+ if (typeof window !== "undefined") {
29
+ Object.defineProperty(window, "openai", {
30
+ value: OpenaiMock,
31
+ writable: true,
32
+ configurable: true,
33
+ });
34
+ }
35
+ vi.stubGlobal("openai", OpenaiMock);
36
+ vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
37
+ });
38
+ afterEach(() => {
39
+ // Keep the mock available for React cleanup, but reset it
40
+ if (typeof window !== "undefined" && window.openai) {
41
+ window.openai.setWidgetState = vi.fn();
42
+ window.openai.widgetState = { modelContent: {}, privateContent: {} };
43
+ }
44
+ });
45
+ it("should register a node with content and call setViewState", () => {
46
+ render(_jsx(DataLLM, { content: "Test content", children: _jsx("div", { children: "Child" }) }));
47
+ expect(OpenaiMock.setWidgetState).toHaveBeenCalled();
48
+ const callArgs = OpenaiMock.setWidgetState.mock.calls[0]?.[0]?.modelContent;
49
+ expect(callArgs).toHaveProperty("__view_context");
50
+ expect(callArgs?.__view_context).toContain("- Test content");
51
+ });
52
+ it("should preserve existing viewState when updating context", () => {
53
+ OpenaiMock.widgetState = {
54
+ modelContent: { existingKey: "existingValue" },
55
+ };
56
+ render(_jsx(DataLLM, { content: "Test content", children: _jsx("div", { children: "Child" }) }));
57
+ const callArgs = OpenaiMock.setWidgetState.mock.calls[0]?.[0]?.modelContent;
58
+ expect(callArgs).toHaveProperty("existingKey", "existingValue");
59
+ expect(callArgs).toHaveProperty("__view_context");
60
+ });
61
+ it("should handle deeply nested DataLLM components", () => {
62
+ render(_jsxs(DataLLM, { content: "Level 1", children: [_jsx(DataLLM, { content: "Level 2A" }), _jsx(DataLLM, { content: "Level 2B", children: _jsx(DataLLM, { content: "Level 3", children: _jsx("div", { children: "Content" }) }) })] }));
63
+ const callArgs = OpenaiMock.setWidgetState.mock.calls[OpenaiMock.setWidgetState.mock.calls.length - 1]?.[0]?.modelContent;
64
+ const context = callArgs?.__view_context;
65
+ expect(context).toContain("- Level 1");
66
+ expect(context).toContain(" - Level 2A");
67
+ expect(context).toContain(" - Level 2B");
68
+ expect(context).toContain(" - Level 3");
69
+ });
70
+ it("should update context when content changes", () => {
71
+ const { rerender } = render(_jsx(DataLLM, { content: "Initial content", children: _jsx("div", { children: "Child" }) }));
72
+ const initialCalls = OpenaiMock.setWidgetState.mock.calls.length;
73
+ rerender(_jsx(DataLLM, { content: "Updated content", children: _jsx("div", { children: "Child" }) }));
74
+ expect(OpenaiMock.setWidgetState.mock.calls.length).toBeGreaterThan(initialCalls);
75
+ const lastCallArgs = OpenaiMock.setWidgetState.mock.calls[OpenaiMock.setWidgetState.mock.calls.length - 1]?.[0]?.modelContent;
76
+ expect(lastCallArgs?.__view_context).toContain("- Updated content");
77
+ });
78
+ it("should remove node and update context when component unmounts", () => {
79
+ const { unmount } = render(_jsx(DataLLM, { content: "Content to remove", children: _jsx("div", { children: "Child" }) }));
80
+ const callsBeforeUnmount = OpenaiMock.setWidgetState.mock.calls.length;
81
+ unmount();
82
+ expect(OpenaiMock.setWidgetState.mock.calls.length).toBeGreaterThan(callsBeforeUnmount);
83
+ const lastCallArgs = OpenaiMock.setWidgetState.mock.calls[OpenaiMock.setWidgetState.mock.calls.length - 1]?.[0]?.modelContent;
84
+ expect(lastCallArgs?.__view_context).not.toContain("Content to remove");
85
+ });
86
+ });
87
+ describe("mcp-app mode", () => {
88
+ let postMessageMock;
89
+ beforeEach(() => {
90
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
91
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
92
+ postMessageMock = getMcpAppHostPostMessageMock();
93
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
94
+ });
95
+ afterEach(() => {
96
+ cleanup();
97
+ McpAppBridge.resetInstance();
98
+ McpAppAdaptor.resetInstance();
99
+ });
100
+ it("should register a node and update view state via adaptor", async () => {
101
+ const adaptor = McpAppAdaptor.getInstance();
102
+ render(_jsx(DataLLM, { content: "Test content", children: _jsx("div", { children: "Child" }) }));
103
+ await vi.waitFor(() => {
104
+ const viewState = adaptor
105
+ .getHostContextStore("viewState")
106
+ .getSnapshot();
107
+ expect(viewState?.__view_context).toContain("- Test content");
108
+ });
109
+ });
110
+ it("should preserve existing view state when updating context", async () => {
111
+ const adaptor = McpAppAdaptor.getInstance();
112
+ await adaptor.setViewState({ existingKey: "existingValue" });
113
+ render(_jsx(DataLLM, { content: "Test content", children: _jsx("div", { children: "Child" }) }));
114
+ await vi.waitFor(() => {
115
+ const viewState = adaptor
116
+ .getHostContextStore("viewState")
117
+ .getSnapshot();
118
+ expect(viewState?.existingKey).toBe("existingValue");
119
+ expect(viewState?.__view_context).toContain("- Test content");
120
+ });
121
+ });
122
+ it("should handle multiple DataLLM components sharing state through adaptor", async () => {
123
+ const adaptor = McpAppAdaptor.getInstance();
124
+ render(_jsxs(_Fragment, { children: [_jsx(DataLLM, { content: "First component", children: _jsx("div", { children: "First" }) }), _jsx(DataLLM, { content: "Second component", children: _jsx("div", { children: "Second" }) })] }));
125
+ await vi.waitFor(() => {
126
+ const viewState = adaptor
127
+ .getHostContextStore("viewState")
128
+ .getSnapshot();
129
+ const context = viewState?.__view_context;
130
+ expect(context).toContain("- First component");
131
+ expect(context).toContain("- Second component");
132
+ });
133
+ });
134
+ it("should call ui/update-model-context when view state changes", async () => {
135
+ render(_jsx(DataLLM, { content: "Test content", children: _jsx("div", { children: "Child" }) }));
136
+ await vi.waitFor(() => {
137
+ expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/update-model-context" }), "*");
138
+ });
139
+ });
140
+ });
141
+ });
142
+ //# sourceMappingURL=data-llm.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-llm.test.js","sourceRoot":"","sources":["../../src/web/data-llm.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { cleanup, render } from \"@testing-library/react\";\nimport {\n afterEach,\n beforeEach,\n describe,\n expect,\n it,\n type Mock,\n vi,\n} from \"vitest\";\nimport { McpAppAdaptor, McpAppBridge } from \"./bridges/mcp-app/index.js\";\nimport { DataLLM } from \"./data-llm.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./hooks/test/utils.js\";\n\ndescribe(\"DataLLM\", () => {\n afterEach(() => {\n // Clean up React components BEFORE unstubbing globals\n cleanup();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n describe(\"apps-sdk mode\", () => {\n let OpenaiMock: { widgetState: unknown; setWidgetState: Mock };\n\n beforeEach(() => {\n OpenaiMock = {\n widgetState: { modelContent: {} },\n setWidgetState: vi.fn(),\n };\n // Use Object.defineProperty to ensure it persists\n Object.defineProperty(globalThis, \"openai\", {\n value: OpenaiMock,\n writable: true,\n configurable: true,\n });\n // Also set on window for browser-like environment\n if (typeof window !== \"undefined\") {\n Object.defineProperty(window, \"openai\", {\n value: OpenaiMock,\n writable: true,\n configurable: true,\n });\n }\n vi.stubGlobal(\"openai\", OpenaiMock);\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n });\n\n afterEach(() => {\n // Keep the mock available for React cleanup, but reset it\n if (typeof window !== \"undefined\" && window.openai) {\n window.openai.setWidgetState = vi.fn();\n window.openai.widgetState = { modelContent: {}, privateContent: {} };\n }\n });\n\n it(\"should register a node with content and call setViewState\", () => {\n render(\n <DataLLM content=\"Test content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n expect(OpenaiMock.setWidgetState).toHaveBeenCalled();\n const callArgs =\n OpenaiMock.setWidgetState.mock.calls[0]?.[0]?.modelContent;\n expect(callArgs).toHaveProperty(\"__view_context\");\n expect(callArgs?.__view_context).toContain(\"- Test content\");\n });\n it(\"should preserve existing viewState when updating context\", () => {\n OpenaiMock.widgetState = {\n modelContent: { existingKey: \"existingValue\" },\n };\n\n render(\n <DataLLM content=\"Test content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n const callArgs =\n OpenaiMock.setWidgetState.mock.calls[0]?.[0]?.modelContent;\n expect(callArgs).toHaveProperty(\"existingKey\", \"existingValue\");\n expect(callArgs).toHaveProperty(\"__view_context\");\n });\n\n it(\"should handle deeply nested DataLLM components\", () => {\n render(\n <DataLLM content=\"Level 1\">\n <DataLLM content=\"Level 2A\" />\n <DataLLM content=\"Level 2B\">\n <DataLLM content=\"Level 3\">\n <div>Content</div>\n </DataLLM>\n </DataLLM>\n </DataLLM>,\n );\n\n const callArgs =\n OpenaiMock.setWidgetState.mock.calls[\n OpenaiMock.setWidgetState.mock.calls.length - 1\n ]?.[0]?.modelContent;\n const context = callArgs?.__view_context as string;\n expect(context).toContain(\"- Level 1\");\n expect(context).toContain(\" - Level 2A\");\n expect(context).toContain(\" - Level 2B\");\n expect(context).toContain(\" - Level 3\");\n });\n\n it(\"should update context when content changes\", () => {\n const { rerender } = render(\n <DataLLM content=\"Initial content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n const initialCalls = OpenaiMock.setWidgetState.mock.calls.length;\n\n rerender(\n <DataLLM content=\"Updated content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n expect(OpenaiMock.setWidgetState.mock.calls.length).toBeGreaterThan(\n initialCalls,\n );\n const lastCallArgs =\n OpenaiMock.setWidgetState.mock.calls[\n OpenaiMock.setWidgetState.mock.calls.length - 1\n ]?.[0]?.modelContent;\n expect(lastCallArgs?.__view_context).toContain(\"- Updated content\");\n });\n\n it(\"should remove node and update context when component unmounts\", () => {\n const { unmount } = render(\n <DataLLM content=\"Content to remove\">\n <div>Child</div>\n </DataLLM>,\n );\n\n const callsBeforeUnmount = OpenaiMock.setWidgetState.mock.calls.length;\n\n unmount();\n\n expect(OpenaiMock.setWidgetState.mock.calls.length).toBeGreaterThan(\n callsBeforeUnmount,\n );\n const lastCallArgs =\n OpenaiMock.setWidgetState.mock.calls[\n OpenaiMock.setWidgetState.mock.calls.length - 1\n ]?.[0]?.modelContent;\n expect(lastCallArgs?.__view_context).not.toContain(\"Content to remove\");\n });\n });\n\n describe(\"mcp-app mode\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n cleanup();\n McpAppBridge.resetInstance();\n McpAppAdaptor.resetInstance();\n });\n\n it(\"should register a node and update view state via adaptor\", async () => {\n const adaptor = McpAppAdaptor.getInstance();\n\n render(\n <DataLLM content=\"Test content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n await vi.waitFor(() => {\n const viewState = adaptor\n .getHostContextStore(\"viewState\")\n .getSnapshot();\n expect(viewState?.__view_context).toContain(\"- Test content\");\n });\n });\n\n it(\"should preserve existing view state when updating context\", async () => {\n const adaptor = McpAppAdaptor.getInstance();\n await adaptor.setViewState({ existingKey: \"existingValue\" });\n\n render(\n <DataLLM content=\"Test content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n await vi.waitFor(() => {\n const viewState = adaptor\n .getHostContextStore(\"viewState\")\n .getSnapshot();\n expect(viewState?.existingKey).toBe(\"existingValue\");\n expect(viewState?.__view_context).toContain(\"- Test content\");\n });\n });\n\n it(\"should handle multiple DataLLM components sharing state through adaptor\", async () => {\n const adaptor = McpAppAdaptor.getInstance();\n\n render(\n <>\n <DataLLM content=\"First component\">\n <div>First</div>\n </DataLLM>\n <DataLLM content=\"Second component\">\n <div>Second</div>\n </DataLLM>\n </>,\n );\n\n await vi.waitFor(() => {\n const viewState = adaptor\n .getHostContextStore(\"viewState\")\n .getSnapshot();\n const context = viewState?.__view_context as string;\n expect(context).toContain(\"- First component\");\n expect(context).toContain(\"- Second component\");\n });\n });\n\n it(\"should call ui/update-model-context when view state changes\", async () => {\n render(\n <DataLLM content=\"Test content\">\n <div>Child</div>\n </DataLLM>,\n );\n\n await vi.waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({ method: \"ui/update-model-context\" }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
@@ -1,7 +1,8 @@
1
1
  import type { InferTools, ToolInput, ToolOutput, ToolResponseMetadata } from "../server/index.js";
2
+ import type { CallToolResponse } from "./bridges/types.js";
2
3
  import { type CallToolAsyncFn, type CallToolFn, type CallToolState } from "./hooks/use-call-tool.js";
3
4
  import { type ToolState } from "./hooks/use-tool-info.js";
4
- import type { CallToolResponse, Objectify, Prettify } from "./types.js";
5
+ import type { Objectify, Prettify } from "./types.js";
5
6
  type TypedCallToolResponse<TOutput> = CallToolResponse & {
6
7
  structuredContent: TOutput;
7
8
  };
@@ -14,7 +15,7 @@ type TypedToolInfoReturn<TInput, TOutput, TResponseMetadata> = ToolState<Objecti
14
15
  * Creates typed versions of skybridge hooks with full type inference
15
16
  * for tool names, inputs, and outputs.
16
17
  *
17
- * This is the recommended way to use skybridge hooks in your widgets.
18
+ * This is the recommended way to use skybridge hooks in your views.
18
19
  * Set this up once in a dedicated file and export the typed hooks for use across your app.
19
20
  *
20
21
  * @typeParam ServerType - The type of your McpServer instance (use `typeof server`).
@@ -23,11 +24,13 @@ type TypedToolInfoReturn<TInput, TOutput, TResponseMetadata> = ToolState<Objecti
23
24
  *
24
25
  * @example
25
26
  * ```typescript
26
- * // server/src/index.ts
27
+ * // src/server.ts
27
28
  * const server = new McpServer({ name: "my-app", version: "1.0" }, {})
28
- * .widget("search-voyage", {}, {
29
+ * .registerTool({
30
+ * name: "search-trip",
29
31
  * inputSchema: { destination: z.string() },
30
32
  * outputSchema: { results: z.array(z.string()) },
33
+ * view: { component: "search-trip", description: "Search trips" },
31
34
  * }, async ({ destination }) => {
32
35
  * return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
33
36
  * });
@@ -37,8 +40,8 @@ type TypedToolInfoReturn<TInput, TOutput, TResponseMetadata> = ToolState<Objecti
37
40
  *
38
41
  * @example
39
42
  * ```typescript
40
- * // web/src/skybridge.ts (one-time setup)
41
- * import type { AppType } from "../server";
43
+ * // src/helpers.ts (one-time setup)
44
+ * import type { AppType } from "./server";
42
45
  * import { generateHelpers } from "skybridge/web";
43
46
  *
44
47
  * export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
@@ -46,33 +49,35 @@ type TypedToolInfoReturn<TInput, TOutput, TResponseMetadata> = ToolState<Objecti
46
49
  *
47
50
  * @example
48
51
  * ```typescript
49
- * // web/src/widgets/search.tsx (usage)
50
- * import { useCallTool, useToolInfo } from "../skybridge";
52
+ * // src/views/search.tsx (usage)
53
+ * import { useCallTool, useToolInfo } from "../helpers";
51
54
  *
52
- * export function SearchWidget() {
53
- * const { callTool, data } = useCallTool("search-voyage");
55
+ * export function SearchView() {
56
+ * const { callTool, data } = useCallTool("search-trip");
54
57
  * // ^ autocomplete for tool names
55
58
  * callTool({ destination: "Spain" });
56
59
  * // ^ autocomplete for input fields
57
60
  *
58
- * const toolInfo = useToolInfo<"search-voyage">();
59
- * // ^ autocomplete for widget names
60
- * // toolInfo.input is typed based on widget input schema
61
- * // toolInfo.output.structuredContent is typed based on widget output schema
61
+ * const toolInfo = useToolInfo<"search-trip">();
62
+ * // ^ autocomplete for view names
63
+ * // toolInfo.input is typed based on view input schema
64
+ * // toolInfo.output.structuredContent is typed based on view output schema
62
65
  * }
63
66
  * ```
67
+ *
68
+ * @see https://docs.skybridge.tech/api-reference/generate-helpers
64
69
  */
65
70
  export declare function generateHelpers<ServerType = never>(): {
66
71
  /**
67
72
  * Typed version of `useCallTool` that provides autocomplete for tool names
68
73
  * and type inference for inputs and outputs.
69
74
  *
70
- * @param name - The name of the widget to call. Autocompletes based on your server's widget registry.
75
+ * @param name - The name of the tool to call. Autocompletes based on your server's tool registry.
71
76
  * @returns A hook with typed `callTool` function and `data` property.
72
77
  *
73
78
  * @example
74
79
  * ```typescript
75
- * const { callTool, data, isPending } = useCallTool("search-voyage");
80
+ * const { callTool, data, isPending } = useCallTool("search-trip");
76
81
  * // TypeScript knows callTool expects { destination: string }
77
82
  * callTool({ destination: "Spain" });
78
83
  *
@@ -84,15 +89,15 @@ export declare function generateHelpers<ServerType = never>(): {
84
89
  */
85
90
  useCallTool: <ToolName extends keyof InferTools<ServerType> & string>(name: ToolName) => TypedCallToolReturn<ToolInput<ServerType, ToolName>, ToolOutput<ServerType, ToolName>>;
86
91
  /**
87
- * Typed version of `useToolInfo` that provides autocomplete for widget names
92
+ * Typed version of `useToolInfo` that provides autocomplete for tool names
88
93
  * and type inference for inputs, outputs, and responseMetadata.
89
94
  *
90
- * @typeParam K - The name of the widget. Autocompletes based on your server's widget registry.
95
+ * @typeParam K - The name of the tool. Autocompletes based on your server's tool registry.
91
96
  * @returns A discriminated union with `status: "pending" | "success"` that narrows correctly.
92
97
  *
93
98
  * @example
94
99
  * ```typescript
95
- * const toolInfo = useToolInfo<"search-voyage">();
100
+ * const toolInfo = useToolInfo<"search-trip">();
96
101
  * // toolInfo.input is typed as { destination: string; ... }
97
102
  * // toolInfo.output is typed as { results: Array<...>; ... }
98
103
  * // toolInfo.responseMetadata is typed based on _meta in callback return
@@ -4,7 +4,7 @@ import { useToolInfo } from "./hooks/use-tool-info.js";
4
4
  * Creates typed versions of skybridge hooks with full type inference
5
5
  * for tool names, inputs, and outputs.
6
6
  *
7
- * This is the recommended way to use skybridge hooks in your widgets.
7
+ * This is the recommended way to use skybridge hooks in your views.
8
8
  * Set this up once in a dedicated file and export the typed hooks for use across your app.
9
9
  *
10
10
  * @typeParam ServerType - The type of your McpServer instance (use `typeof server`).
@@ -13,11 +13,13 @@ import { useToolInfo } from "./hooks/use-tool-info.js";
13
13
  *
14
14
  * @example
15
15
  * ```typescript
16
- * // server/src/index.ts
16
+ * // src/server.ts
17
17
  * const server = new McpServer({ name: "my-app", version: "1.0" }, {})
18
- * .widget("search-voyage", {}, {
18
+ * .registerTool({
19
+ * name: "search-trip",
19
20
  * inputSchema: { destination: z.string() },
20
21
  * outputSchema: { results: z.array(z.string()) },
22
+ * view: { component: "search-trip", description: "Search trips" },
21
23
  * }, async ({ destination }) => {
22
24
  * return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
23
25
  * });
@@ -27,8 +29,8 @@ import { useToolInfo } from "./hooks/use-tool-info.js";
27
29
  *
28
30
  * @example
29
31
  * ```typescript
30
- * // web/src/skybridge.ts (one-time setup)
31
- * import type { AppType } from "../server";
32
+ * // src/helpers.ts (one-time setup)
33
+ * import type { AppType } from "./server";
32
34
  * import { generateHelpers } from "skybridge/web";
33
35
  *
34
36
  * export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
@@ -36,21 +38,23 @@ import { useToolInfo } from "./hooks/use-tool-info.js";
36
38
  *
37
39
  * @example
38
40
  * ```typescript
39
- * // web/src/widgets/search.tsx (usage)
40
- * import { useCallTool, useToolInfo } from "../skybridge";
41
+ * // src/views/search.tsx (usage)
42
+ * import { useCallTool, useToolInfo } from "../helpers";
41
43
  *
42
- * export function SearchWidget() {
43
- * const { callTool, data } = useCallTool("search-voyage");
44
+ * export function SearchView() {
45
+ * const { callTool, data } = useCallTool("search-trip");
44
46
  * // ^ autocomplete for tool names
45
47
  * callTool({ destination: "Spain" });
46
48
  * // ^ autocomplete for input fields
47
49
  *
48
- * const toolInfo = useToolInfo<"search-voyage">();
49
- * // ^ autocomplete for widget names
50
- * // toolInfo.input is typed based on widget input schema
51
- * // toolInfo.output.structuredContent is typed based on widget output schema
50
+ * const toolInfo = useToolInfo<"search-trip">();
51
+ * // ^ autocomplete for view names
52
+ * // toolInfo.input is typed based on view input schema
53
+ * // toolInfo.output.structuredContent is typed based on view output schema
52
54
  * }
53
55
  * ```
56
+ *
57
+ * @see https://docs.skybridge.tech/api-reference/generate-helpers
54
58
  */
55
59
  export function generateHelpers() {
56
60
  return {
@@ -58,12 +62,12 @@ export function generateHelpers() {
58
62
  * Typed version of `useCallTool` that provides autocomplete for tool names
59
63
  * and type inference for inputs and outputs.
60
64
  *
61
- * @param name - The name of the widget to call. Autocompletes based on your server's widget registry.
65
+ * @param name - The name of the tool to call. Autocompletes based on your server's tool registry.
62
66
  * @returns A hook with typed `callTool` function and `data` property.
63
67
  *
64
68
  * @example
65
69
  * ```typescript
66
- * const { callTool, data, isPending } = useCallTool("search-voyage");
70
+ * const { callTool, data, isPending } = useCallTool("search-trip");
67
71
  * // TypeScript knows callTool expects { destination: string }
68
72
  * callTool({ destination: "Spain" });
69
73
  *
@@ -77,15 +81,15 @@ export function generateHelpers() {
77
81
  return useCallTool(name);
78
82
  },
79
83
  /**
80
- * Typed version of `useToolInfo` that provides autocomplete for widget names
84
+ * Typed version of `useToolInfo` that provides autocomplete for tool names
81
85
  * and type inference for inputs, outputs, and responseMetadata.
82
86
  *
83
- * @typeParam K - The name of the widget. Autocompletes based on your server's widget registry.
87
+ * @typeParam K - The name of the tool. Autocompletes based on your server's tool registry.
84
88
  * @returns A discriminated union with `status: "pending" | "success"` that narrows correctly.
85
89
  *
86
90
  * @example
87
91
  * ```typescript
88
- * const toolInfo = useToolInfo<"search-voyage">();
92
+ * const toolInfo = useToolInfo<"search-trip">();
89
93
  * // toolInfo.input is typed as { destination: string; ... }
90
94
  * // toolInfo.output is typed as { results: Array<...>; ... }
91
95
  * // toolInfo.responseMetadata is typed based on _meta in callback return
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-helpers.js","sourceRoot":"","sources":["../../src/web/generate-helpers.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,WAAW,GACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAkB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAoBvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,UAAU,eAAe;IAI7B,OAAO;QACL;;;;;;;;;;;;;;;;;;WAkBG;QACH,WAAW,EAAE,CACX,IAAc,EAId,EAAE;YACF,OAAO,WAAW,CAAC,IAAI,CAGtB,CAAC;QACJ,CAAC;QAED;;;;;;;;;;;;;;;;;;;;;;;;;;WA0BG;QACH,WAAW,EAAE,GAIX,EAAE;YACF,OAAO,WAAW,EAIjB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type {\n InferTools,\n ToolInput,\n ToolOutput,\n ToolResponseMetadata,\n} from \"../server/index.js\";\nimport type { CallToolResponse } from \"./bridges/types.js\";\nimport {\n type CallToolAsyncFn,\n type CallToolFn,\n type CallToolState,\n useCallTool,\n} from \"./hooks/use-call-tool.js\";\nimport { type ToolState, useToolInfo } from \"./hooks/use-tool-info.js\";\nimport type { Objectify, Prettify } from \"./types.js\";\n\ntype TypedCallToolResponse<TOutput> = CallToolResponse & {\n structuredContent: TOutput;\n};\n\ntype TypedCallToolReturn<TInput, TOutput> = Prettify<\n CallToolState<TypedCallToolResponse<TOutput>> & {\n callTool: CallToolFn<TInput, TypedCallToolResponse<TOutput>>;\n callToolAsync: CallToolAsyncFn<TInput, TypedCallToolResponse<TOutput>>;\n }\n>;\n\ntype TypedToolInfoReturn<TInput, TOutput, TResponseMetadata> = ToolState<\n Objectify<TInput>,\n Objectify<TOutput>,\n Objectify<TResponseMetadata>\n>;\n\n/**\n * Creates typed versions of skybridge hooks with full type inference\n * for tool names, inputs, and outputs.\n *\n * This is the recommended way to use skybridge hooks in your views.\n * Set this up once in a dedicated file and export the typed hooks for use across your app.\n *\n * @typeParam ServerType - The type of your McpServer instance (use `typeof server`).\n * Must be a server instance created with method chaining.\n * TypeScript will validate that tools can be inferred from this type.\n *\n * @example\n * ```typescript\n * // src/server.ts\n * const server = new McpServer({ name: \"my-app\", version: \"1.0\" }, {})\n * .registerTool({\n * name: \"search-trip\",\n * inputSchema: { destination: z.string() },\n * outputSchema: { results: z.array(z.string()) },\n * view: { component: \"search-trip\", description: \"Search trips\" },\n * }, async ({ destination }) => {\n * return { content: [{ type: \"text\", text: `Found trips to ${destination}` }] };\n * });\n *\n * export type AppType = typeof server;\n * ```\n *\n * @example\n * ```typescript\n * // src/helpers.ts (one-time setup)\n * import type { AppType } from \"./server\";\n * import { generateHelpers } from \"skybridge/web\";\n *\n * export const { useCallTool, useToolInfo } = generateHelpers<AppType>();\n * ```\n *\n * @example\n * ```typescript\n * // src/views/search.tsx (usage)\n * import { useCallTool, useToolInfo } from \"../helpers\";\n *\n * export function SearchView() {\n * const { callTool, data } = useCallTool(\"search-trip\");\n * // ^ autocomplete for tool names\n * callTool({ destination: \"Spain\" });\n * // ^ autocomplete for input fields\n *\n * const toolInfo = useToolInfo<\"search-trip\">();\n * // ^ autocomplete for view names\n * // toolInfo.input is typed based on view input schema\n * // toolInfo.output.structuredContent is typed based on view output schema\n * }\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/generate-helpers\n */\nexport function generateHelpers<ServerType = never>() {\n type Tools = InferTools<ServerType>;\n type ToolNames = keyof Tools & string;\n\n return {\n /**\n * Typed version of `useCallTool` that provides autocomplete for tool names\n * and type inference for inputs and outputs.\n *\n * @param name - The name of the tool to call. Autocompletes based on your server's tool registry.\n * @returns A hook with typed `callTool` function and `data` property.\n *\n * @example\n * ```typescript\n * const { callTool, data, isPending } = useCallTool(\"search-trip\");\n * // TypeScript knows callTool expects { destination: string }\n * callTool({ destination: \"Spain\" });\n *\n * // data.structuredContent is typed based on your outputSchema\n * if (data) {\n * console.log(data.structuredContent.results);\n * }\n * ```\n */\n useCallTool: <ToolName extends ToolNames>(\n name: ToolName,\n ): TypedCallToolReturn<\n ToolInput<ServerType, ToolName>,\n ToolOutput<ServerType, ToolName>\n > => {\n return useCallTool(name) as TypedCallToolReturn<\n ToolInput<ServerType, ToolName>,\n ToolOutput<ServerType, ToolName>\n >;\n },\n\n /**\n * Typed version of `useToolInfo` that provides autocomplete for tool names\n * and type inference for inputs, outputs, and responseMetadata.\n *\n * @typeParam K - The name of the tool. Autocompletes based on your server's tool registry.\n * @returns A discriminated union with `status: \"pending\" | \"success\"` that narrows correctly.\n *\n * @example\n * ```typescript\n * const toolInfo = useToolInfo<\"search-trip\">();\n * // toolInfo.input is typed as { destination: string; ... }\n * // toolInfo.output is typed as { results: Array<...>; ... }\n * // toolInfo.responseMetadata is typed based on _meta in callback return\n * // toolInfo.status narrows correctly: \"pending\" | \"success\"\n *\n * if (toolInfo.isPending) {\n * // TypeScript knows output and responseMetadata are undefined here\n * console.log(toolInfo.input.destination);\n * }\n *\n * if (toolInfo.isSuccess) {\n * // TypeScript knows output and responseMetadata are defined here\n * console.log(toolInfo.output.results);\n * console.log(toolInfo.responseMetadata);\n * }\n * ```\n */\n useToolInfo: <ToolName extends ToolNames>(): TypedToolInfoReturn<\n ToolInput<ServerType, ToolName>,\n ToolOutput<ServerType, ToolName>,\n ToolResponseMetadata<ServerType, ToolName>\n > => {\n return useToolInfo() as TypedToolInfoReturn<\n ToolInput<ServerType, ToolName>,\n ToolOutput<ServerType, ToolName>,\n ToolResponseMetadata<ServerType, ToolName>\n >;\n },\n };\n}\n"]}
@@ -3,18 +3,18 @@ import { createInterfaceTestServer, createTestServer } from "../test/utils.js";
3
3
  import { generateHelpers } from "./generate-helpers.js";
4
4
  const server = createTestServer();
5
5
  const interfaceServer = createInterfaceTestServer();
6
- test("InferTools extracts the tool registry type (widgets + registerTool)", () => {
7
- expectTypeOf().toHaveProperty("search-voyage");
6
+ test("InferTools extracts the tool registry type (views + registerTool)", () => {
7
+ expectTypeOf().toHaveProperty("search-trip");
8
8
  expectTypeOf().toHaveProperty("get-trip-details");
9
- expectTypeOf().toHaveProperty("no-input-widget");
9
+ expectTypeOf().toHaveProperty("no-input-view");
10
10
  expectTypeOf().toHaveProperty("calculate-price");
11
- expectTypeOf().toHaveProperty("inferred-output-widget");
11
+ expectTypeOf().toHaveProperty("inferred-output-view");
12
12
  expectTypeOf().toHaveProperty("inferred-tool");
13
- expectTypeOf().toHaveProperty("widget-with-metadata");
13
+ expectTypeOf().toHaveProperty("view-with-metadata");
14
14
  expectTypeOf().toHaveProperty("tool-with-metadata");
15
- expectTypeOf().toHaveProperty("widget-with-mixed-returns");
15
+ expectTypeOf().toHaveProperty("view-with-mixed-returns");
16
16
  });
17
- test("ToolNames returns a union of tool name literals (widgets + registerTool)", () => {
17
+ test("ToolNames returns a union of tool name literals (views + registerTool)", () => {
18
18
  expectTypeOf().toEqualTypeOf();
19
19
  });
20
20
  test("ToolInput extracts the correct input type from Zod schema", () => {
@@ -32,23 +32,23 @@ test("ToolOutput extracts the correct output type from callback (inferred)", ()
32
32
  expectTypeOf().toEqualTypeOf();
33
33
  expectTypeOf().toEqualTypeOf();
34
34
  });
35
- test("generateHelpers provides autocomplete for tool names (widgets + registerTool)", () => {
35
+ test("generateHelpers provides autocomplete for tool names (views + registerTool)", () => {
36
36
  const { useCallTool } = generateHelpers();
37
- useCallTool("search-voyage");
37
+ useCallTool("search-trip");
38
38
  useCallTool("get-trip-details");
39
- useCallTool("no-input-widget");
39
+ useCallTool("no-input-view");
40
40
  useCallTool("calculate-price");
41
- useCallTool("inferred-output-widget");
41
+ useCallTool("inferred-output-view");
42
42
  useCallTool("inferred-tool");
43
- useCallTool("widget-with-metadata");
43
+ useCallTool("view-with-metadata");
44
44
  useCallTool("tool-with-metadata");
45
- useCallTool("widget-with-mixed-returns");
45
+ useCallTool("view-with-mixed-returns");
46
46
  // @ts-expect-error - "invalid-name" is not a valid tool name
47
47
  useCallTool("invalid-name");
48
48
  });
49
49
  test("useCallTool returns correctly typed callTool function", () => {
50
50
  const { useCallTool } = generateHelpers();
51
- const { callTool } = useCallTool("search-voyage");
51
+ const { callTool } = useCallTool("search-trip");
52
52
  callTool({ destination: "Spain" });
53
53
  callTool({ destination: "France", departureDate: "2024-06-01" });
54
54
  callTool({ destination: "Italy", maxPrice: 1000 });
@@ -57,7 +57,7 @@ test("useCallTool returns correctly typed callTool function", () => {
57
57
  });
58
58
  test("callTool can be called without args for tools with no required inputs", () => {
59
59
  const { useCallTool } = generateHelpers();
60
- const { callTool, callToolAsync } = useCallTool("no-input-widget");
60
+ const { callTool, callToolAsync } = useCallTool("no-input-view");
61
61
  callTool();
62
62
  callTool({});
63
63
  callToolAsync();
@@ -65,7 +65,7 @@ test("callTool can be called without args for tools with no required inputs", ()
65
65
  });
66
66
  test("callTool requires args for tools with required inputs", () => {
67
67
  const { useCallTool } = generateHelpers();
68
- const { callTool } = useCallTool("search-voyage");
68
+ const { callTool } = useCallTool("search-trip");
69
69
  // @ts-expect-error - "destination" is required
70
70
  callTool();
71
71
  // @ts-expect-error - "destination" is required
@@ -75,7 +75,7 @@ test("callTool requires args for tools with required inputs", () => {
75
75
  });
76
76
  test("callTool supports sideEffects for tools with required inputs", () => {
77
77
  const { useCallTool } = generateHelpers();
78
- const { callTool } = useCallTool("search-voyage");
78
+ const { callTool } = useCallTool("search-trip");
79
79
  callTool({ destination: "Spain" }, {
80
80
  onSuccess: (response, args) => {
81
81
  expectTypeOf(response.structuredContent.results).toBeArray();
@@ -96,7 +96,7 @@ test("callTool supports sideEffects for tools with required inputs", () => {
96
96
  });
97
97
  test("callTool supports sideEffects for tools with no required inputs", () => {
98
98
  const { useCallTool } = generateHelpers();
99
- const { callTool } = useCallTool("no-input-widget");
99
+ const { callTool } = useCallTool("no-input-view");
100
100
  callTool({
101
101
  onSuccess: (response) => {
102
102
  expectTypeOf(response).toHaveProperty("structuredContent");
@@ -110,16 +110,16 @@ test("callTool supports sideEffects for tools with no required inputs", () => {
110
110
  });
111
111
  test("callToolAsync returns correctly typed promise", () => {
112
112
  const { useCallTool } = generateHelpers();
113
- const { callToolAsync: searchAsync } = useCallTool("search-voyage");
113
+ const { callToolAsync: searchAsync } = useCallTool("search-trip");
114
114
  const searchPromise = searchAsync({ destination: "Spain" });
115
115
  expectTypeOf(searchPromise).resolves.toHaveProperty("structuredContent");
116
- const { callToolAsync: noInputAsync } = useCallTool("no-input-widget");
116
+ const { callToolAsync: noInputAsync } = useCallTool("no-input-view");
117
117
  const noInputPromise = noInputAsync();
118
118
  expectTypeOf(noInputPromise).resolves.toHaveProperty("structuredContent");
119
119
  });
120
120
  test("useCallTool returns correctly typed data", () => {
121
121
  const { useCallTool } = generateHelpers();
122
- const { data } = useCallTool("search-voyage");
122
+ const { data } = useCallTool("search-trip");
123
123
  if (data) {
124
124
  expectTypeOf(data.structuredContent).toExtend();
125
125
  expectTypeOf(data.structuredContent.results).toBeArray();
@@ -128,16 +128,16 @@ test("useCallTool returns correctly typed data", () => {
128
128
  });
129
129
  test("useCallTool returns correctly typed data for callback-inferred outputs", () => {
130
130
  const { useCallTool } = generateHelpers();
131
- const { data: widgetData } = useCallTool("inferred-output-widget");
132
- if (widgetData) {
133
- expectTypeOf(widgetData.structuredContent).toExtend();
131
+ const { data: viewData } = useCallTool("inferred-output-view");
132
+ if (viewData) {
133
+ expectTypeOf(viewData.structuredContent).toExtend();
134
134
  }
135
135
  const { data: toolData } = useCallTool("inferred-tool");
136
136
  if (toolData) {
137
137
  expectTypeOf(toolData.structuredContent).toExtend();
138
138
  }
139
139
  });
140
- test("generateHelpers provides autocomplete for tool names in useToolInfo (widgets + registerTool)", () => {
140
+ test("generateHelpers provides autocomplete for tool names in useToolInfo (views + registerTool)", () => {
141
141
  const { useToolInfo } = generateHelpers();
142
142
  useToolInfo();
143
143
  useToolInfo();
@@ -193,7 +193,7 @@ test("ToolResponseMetadata extracts correct type when using interface declaratio
193
193
  });
194
194
  test("generateHelpers works with interface-typed server", () => {
195
195
  const { useCallTool, useToolInfo } = generateHelpers();
196
- const { data } = useCallTool("interface-widget");
196
+ const { data } = useCallTool("interface-view");
197
197
  if (data) {
198
198
  expectTypeOf(data.structuredContent.itemName).toBeString();
199
199
  expectTypeOf(data.structuredContent.quantity).toBeNumber();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-helpers.test-d.js","sourceRoot":"","sources":["../../src/web/generate-helpers.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport type {\n InferTools,\n ToolInput,\n ToolNames,\n ToolOutput,\n ToolResponseMetadata,\n} from \"../server/index.js\";\nimport { createInterfaceTestServer, createTestServer } from \"../test/utils.js\";\nimport { generateHelpers } from \"./generate-helpers.js\";\n\nconst server = createTestServer();\ntype TestServer = typeof server;\n\nconst interfaceServer = createInterfaceTestServer();\ntype InterfaceTestServer = typeof interfaceServer;\n\ntest(\"InferTools extracts the tool registry type (views + registerTool)\", () => {\n type Tools = InferTools<TestServer>;\n\n expectTypeOf<Tools>().toHaveProperty(\"search-trip\");\n expectTypeOf<Tools>().toHaveProperty(\"get-trip-details\");\n expectTypeOf<Tools>().toHaveProperty(\"no-input-view\");\n expectTypeOf<Tools>().toHaveProperty(\"calculate-price\");\n expectTypeOf<Tools>().toHaveProperty(\"inferred-output-view\");\n expectTypeOf<Tools>().toHaveProperty(\"inferred-tool\");\n expectTypeOf<Tools>().toHaveProperty(\"view-with-metadata\");\n expectTypeOf<Tools>().toHaveProperty(\"tool-with-metadata\");\n expectTypeOf<Tools>().toHaveProperty(\"view-with-mixed-returns\");\n});\n\ntest(\"ToolNames returns a union of tool name literals (views + registerTool)\", () => {\n type Names = ToolNames<TestServer>;\n\n expectTypeOf<Names>().toEqualTypeOf<\n | \"search-trip\"\n | \"get-trip-details\"\n | \"no-input-view\"\n | \"calculate-price\"\n | \"inferred-output-view\"\n | \"inferred-tool\"\n | \"view-with-metadata\"\n | \"tool-with-metadata\"\n | \"view-with-mixed-returns\"\n >();\n});\n\ntest(\"ToolInput extracts the correct input type from Zod schema\", () => {\n type SearchInput = ToolInput<TestServer, \"search-trip\">;\n\n expectTypeOf<SearchInput>().toEqualTypeOf<{\n destination: string;\n departureDate?: string | undefined;\n maxPrice?: number | undefined;\n }>();\n\n type DetailsInput = ToolInput<TestServer, \"get-trip-details\">;\n\n expectTypeOf<DetailsInput>().toEqualTypeOf<{\n tripId: string;\n }>();\n\n type CalculateInput = ToolInput<TestServer, \"calculate-price\">;\n\n expectTypeOf<CalculateInput>().toEqualTypeOf<{\n tripId: string;\n passengers: number;\n }>();\n});\n\ntest(\"ToolOutput extracts the correct output type from callback's structuredContent\", () => {\n type SearchOutput = ToolOutput<TestServer, \"search-trip\">;\n\n expectTypeOf<SearchOutput>().toEqualTypeOf<{\n results: Array<{\n id: string;\n name: string;\n price: number;\n }>;\n totalCount: number;\n }>();\n\n type DetailsOutput = ToolOutput<TestServer, \"get-trip-details\">;\n\n expectTypeOf<DetailsOutput>().toEqualTypeOf<{\n name: string;\n description: string;\n images: string[];\n }>();\n\n // Note: outputSchema has totalPrice: z.string(), but callback returns number\n // Type is inferred from callback, so totalPrice is number\n type CalculateOutput = ToolOutput<TestServer, \"calculate-price\">;\n\n expectTypeOf<CalculateOutput>().toEqualTypeOf<{\n totalPrice: number;\n currency: string;\n }>();\n\n type NoInputOutput = ToolOutput<TestServer, \"no-input-view\">;\n expectTypeOf<NoInputOutput>().toEqualTypeOf<Record<never, unknown>>();\n});\n\ntest(\"ToolOutput extracts the correct output type from callback (inferred)\", () => {\n type InferredViewOutput = ToolOutput<TestServer, \"inferred-output-view\">;\n\n expectTypeOf<InferredViewOutput>().toEqualTypeOf<{\n inferredResults: { id: string; score: number }[];\n inferredCount: number;\n }>();\n\n type InferredToolOutput = ToolOutput<TestServer, \"inferred-tool\">;\n\n expectTypeOf<InferredToolOutput>().toEqualTypeOf<{\n itemDetails: { name: string; available: boolean };\n fetchedAt: string;\n }>();\n});\n\ntest(\"generateHelpers provides autocomplete for tool names (views + registerTool)\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n\n useCallTool(\"search-trip\");\n useCallTool(\"get-trip-details\");\n useCallTool(\"no-input-view\");\n useCallTool(\"calculate-price\");\n useCallTool(\"inferred-output-view\");\n useCallTool(\"inferred-tool\");\n useCallTool(\"view-with-metadata\");\n useCallTool(\"tool-with-metadata\");\n useCallTool(\"view-with-mixed-returns\");\n\n // @ts-expect-error - \"invalid-name\" is not a valid tool name\n useCallTool(\"invalid-name\");\n});\n\ntest(\"useCallTool returns correctly typed callTool function\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { callTool } = useCallTool(\"search-trip\");\n\n callTool({ destination: \"Spain\" });\n callTool({ destination: \"France\", departureDate: \"2024-06-01\" });\n callTool({ destination: \"Italy\", maxPrice: 1000 });\n\n const { callTool: calculateTool } = useCallTool(\"calculate-price\");\n calculateTool({ tripId: \"123\", passengers: 2 });\n});\n\ntest(\"callTool can be called without args for tools with no required inputs\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { callTool, callToolAsync } = useCallTool(\"no-input-view\");\n\n callTool();\n\n callTool({});\n\n callToolAsync();\n callToolAsync({});\n});\n\ntest(\"callTool requires args for tools with required inputs\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { callTool } = useCallTool(\"search-trip\");\n\n // @ts-expect-error - \"destination\" is required\n callTool();\n\n // @ts-expect-error - \"destination\" is required\n callTool({});\n\n // This should work\n callTool({ destination: \"Spain\" });\n});\n\ntest(\"callTool supports sideEffects for tools with required inputs\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { callTool } = useCallTool(\"search-trip\");\n\n callTool(\n { destination: \"Spain\" },\n {\n onSuccess: (response, args) => {\n expectTypeOf(response.structuredContent.results).toBeArray();\n expectTypeOf(args.destination).toBeString();\n },\n onError: (error, args) => {\n expectTypeOf(error).toBeUnknown();\n expectTypeOf(args.destination).toBeString();\n },\n onSettled: (response, error, args) => {\n if (response) {\n expectTypeOf(response.structuredContent.totalCount).toBeNumber();\n }\n expectTypeOf(error).toBeUnknown();\n expectTypeOf(args.destination).toBeString();\n },\n },\n );\n});\n\ntest(\"callTool supports sideEffects for tools with no required inputs\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { callTool } = useCallTool(\"no-input-view\");\n\n callTool({\n onSuccess: (response) => {\n expectTypeOf(response).toHaveProperty(\"structuredContent\");\n },\n });\n\n callTool(\n {},\n {\n onSuccess: (response) => {\n expectTypeOf(response).toHaveProperty(\"structuredContent\");\n },\n },\n );\n});\n\ntest(\"callToolAsync returns correctly typed promise\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n\n const { callToolAsync: searchAsync } = useCallTool(\"search-trip\");\n const searchPromise = searchAsync({ destination: \"Spain\" });\n expectTypeOf(searchPromise).resolves.toHaveProperty(\"structuredContent\");\n\n const { callToolAsync: noInputAsync } = useCallTool(\"no-input-view\");\n const noInputPromise = noInputAsync();\n expectTypeOf(noInputPromise).resolves.toHaveProperty(\"structuredContent\");\n});\n\ntest(\"useCallTool returns correctly typed data\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n const { data } = useCallTool(\"search-trip\");\n\n if (data) {\n expectTypeOf(data.structuredContent).toExtend<{\n results: Array<{\n id: string;\n name: string;\n price: number;\n }>;\n totalCount: number;\n }>();\n\n expectTypeOf(data.structuredContent.results).toBeArray();\n expectTypeOf(data.structuredContent.totalCount).toBeNumber();\n }\n});\n\ntest(\"useCallTool returns correctly typed data for callback-inferred outputs\", () => {\n const { useCallTool } = generateHelpers<TestServer>();\n\n const { data: viewData } = useCallTool(\"inferred-output-view\");\n if (viewData) {\n expectTypeOf(viewData.structuredContent).toExtend<{\n inferredResults: { id: string; score: number }[];\n inferredCount: number;\n }>();\n }\n\n const { data: toolData } = useCallTool(\"inferred-tool\");\n if (toolData) {\n expectTypeOf(toolData.structuredContent).toExtend<{\n itemDetails: { name: string; available: boolean };\n fetchedAt: string;\n }>();\n }\n});\n\ntest(\"generateHelpers provides autocomplete for tool names in useToolInfo (views + registerTool)\", () => {\n const { useToolInfo } = generateHelpers<TestServer>();\n\n useToolInfo<\"search-trip\">();\n useToolInfo<\"get-trip-details\">();\n useToolInfo<\"no-input-view\">();\n useToolInfo<\"calculate-price\">();\n useToolInfo<\"inferred-output-view\">();\n useToolInfo<\"inferred-tool\">();\n useToolInfo<\"view-with-metadata\">();\n useToolInfo<\"tool-with-metadata\">();\n useToolInfo<\"view-with-mixed-returns\">();\n\n // @ts-expect-error - \"invalid-name\" is not a valid tool name\n useToolInfo<\"invalid-name\">();\n});\n\ntest(\"useToolInfo infers input and output types\", () => {\n const { useToolInfo } = generateHelpers<TestServer>();\n const toolInfo = useToolInfo<\"search-trip\">();\n\n // Input is only available when not in idle state\n if (!(toolInfo.status === \"idle\")) {\n expectTypeOf(toolInfo.input).toExtend<\n ToolInput<TestServer, \"search-trip\">\n >();\n }\n\n if (toolInfo.status === \"success\") {\n expectTypeOf(toolInfo.output).toExtend<\n ToolOutput<TestServer, \"search-trip\">\n >();\n expectTypeOf(toolInfo.output.results).toBeArray();\n expectTypeOf(toolInfo.output.totalCount).toBeNumber();\n }\n});\n\ntest(\"ToolResponseMetadata extracts _meta type from callback\", () => {\n type ViewMeta = ToolResponseMetadata<TestServer, \"view-with-metadata\">;\n expectTypeOf<ViewMeta>().toEqualTypeOf<{\n requestId: string;\n timestamp: number;\n cached: boolean;\n }>();\n\n type ToolMeta = ToolResponseMetadata<TestServer, \"tool-with-metadata\">;\n expectTypeOf<ToolMeta>().toEqualTypeOf<{\n executionTime: number;\n source: string;\n }>();\n\n type SearchMeta = ToolResponseMetadata<TestServer, \"search-trip\">;\n expectTypeOf<SearchMeta>().toBeUnknown();\n});\n\ntest(\"useToolInfo infers responseMetadata type from generateHelpers\", () => {\n const { useToolInfo } = generateHelpers<TestServer>();\n const toolInfo = useToolInfo<\"view-with-metadata\">();\n\n if (toolInfo.isSuccess) {\n expectTypeOf(toolInfo.responseMetadata.requestId).toBeString();\n expectTypeOf(toolInfo.responseMetadata.timestamp).toBeNumber();\n expectTypeOf(toolInfo.responseMetadata.cached).toBeBoolean();\n }\n});\n\ntest(\"ToolResponseMetadata extracts _meta from mixed return paths\", () => {\n // View has multiple return paths: some with _meta, some without\n // ExtractMeta should still infer the _meta type from branches that have it\n type MixedMeta = ToolResponseMetadata<TestServer, \"view-with-mixed-returns\">;\n expectTypeOf<MixedMeta>().toEqualTypeOf<{\n processedAt: number;\n region: string;\n }>();\n});\n\ntest(\"ToolOutput extracts correct type when using interface declaration\", () => {\n type InterfaceViewOutput = ToolOutput<InterfaceTestServer, \"interface-view\">;\n\n expectTypeOf<InterfaceViewOutput>().toHaveProperty(\"itemName\");\n expectTypeOf<InterfaceViewOutput[\"itemName\"]>().toBeString();\n expectTypeOf<InterfaceViewOutput[\"quantity\"]>().toBeNumber();\n});\n\ntest(\"ToolResponseMetadata extracts correct type when using interface declaration\", () => {\n type InterfaceViewMeta = ToolResponseMetadata<\n InterfaceTestServer,\n \"interface-view\"\n >;\n\n expectTypeOf<InterfaceViewMeta>().toHaveProperty(\"processedBy\");\n expectTypeOf<InterfaceViewMeta[\"processedBy\"]>().toBeString();\n expectTypeOf<InterfaceViewMeta[\"version\"]>().toBeNumber();\n});\n\ntest(\"generateHelpers works with interface-typed server\", () => {\n const { useCallTool, useToolInfo } = generateHelpers<InterfaceTestServer>();\n\n const { data } = useCallTool(\"interface-view\");\n if (data) {\n expectTypeOf(data.structuredContent.itemName).toBeString();\n expectTypeOf(data.structuredContent.quantity).toBeNumber();\n }\n\n const toolInfo = useToolInfo<\"interface-view\">();\n if (toolInfo.isSuccess) {\n expectTypeOf(toolInfo.output.itemName).toBeString();\n expectTypeOf(toolInfo.output.quantity).toBeNumber();\n expectTypeOf(toolInfo.responseMetadata.processedBy).toBeString();\n expectTypeOf(toolInfo.responseMetadata.version).toBeNumber();\n }\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-helpers.test.js","sourceRoot":"","sources":["../../src/web/generate-helpers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,MAAM,GAAG,uBAAuB,EAAE,CAAC;AAGzC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,eAAe,EAAc,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,eAAe,EAAc,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { createMinimalTestServer } from \"../test/utils.js\";\nimport { generateHelpers } from \"./generate-helpers.js\";\n\nconst server = createMinimalTestServer();\ntype TestServer = typeof server;\n\ndescribe(\"generateHelpers\", () => {\n it(\"should return an object with useCallTool hook\", () => {\n const hooks = generateHelpers<TestServer>();\n expect(hooks).toHaveProperty(\"useCallTool\");\n expect(typeof hooks.useCallTool).toBe(\"function\");\n });\n\n it(\"should return an object with useToolInfo hook\", () => {\n const hooks = generateHelpers<TestServer>();\n expect(hooks).toHaveProperty(\"useToolInfo\");\n expect(typeof hooks.useToolInfo).toBe(\"function\");\n });\n});\n"]}