@elabs-ai/components-ai 4.2.0 → 5.0.0

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 (462) hide show
  1. package/README.md +1 -1
  2. package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
  3. package/dist/_code-block-theme.js +12 -0
  4. package/dist/_code-block-theme.js.map +1 -0
  5. package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
  6. package/dist/_flow-boundary.js.map +1 -0
  7. package/dist/_flow-lazy.js +8 -0
  8. package/dist/_flow-lazy.js.map +1 -0
  9. package/dist/_lazy-boundary-conformance.js +2 -0
  10. package/dist/_lazy-boundary-conformance.js.map +1 -0
  11. package/dist/_lazy-cjk.js +13 -0
  12. package/dist/_lazy-cjk.js.map +1 -0
  13. package/dist/_lazy-engine-boundary.js +9 -0
  14. package/dist/_lazy-engine-boundary.js.map +1 -0
  15. package/dist/_lazy-math.js +13 -0
  16. package/dist/_lazy-math.js.map +1 -0
  17. package/dist/_lazy-mermaid.js +12 -0
  18. package/dist/_lazy-mermaid.js.map +1 -0
  19. package/dist/_mermaid-error-panel.js +9 -0
  20. package/dist/_mermaid-error-panel.js.map +1 -0
  21. package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
  22. package/dist/_persona-rive.js.map +1 -0
  23. package/dist/_streamdown-i18n.js +21 -0
  24. package/dist/_streamdown-i18n.js.map +1 -0
  25. package/dist/_streamdown-safety.js +10 -0
  26. package/dist/_streamdown-safety.js.map +1 -0
  27. package/dist/_theme-scope-store.js +13 -0
  28. package/dist/_theme-scope-store.js.map +1 -0
  29. package/dist/a2ui/a2ui-surface.js +17 -0
  30. package/dist/a2ui/a2ui-surface.js.map +1 -0
  31. package/dist/a2ui/core/catalog.generated.js +10 -0
  32. package/dist/a2ui/core/catalog.generated.js.map +1 -0
  33. package/dist/a2ui/core/complete-json.js +10 -0
  34. package/dist/a2ui/core/complete-json.js.map +1 -0
  35. package/dist/a2ui/core/index.js +37 -0
  36. package/dist/a2ui/core/index.js.map +1 -0
  37. package/dist/a2ui/core/schema.js +11 -0
  38. package/dist/a2ui/core/schema.js.map +1 -0
  39. package/dist/a2ui/core/spec.js +10 -0
  40. package/dist/a2ui/core/spec.js.map +1 -0
  41. package/dist/a2ui/core/validate.js +16 -0
  42. package/dist/a2ui/core/validate.js.map +1 -0
  43. package/dist/a2ui/index.js +54 -0
  44. package/dist/a2ui/index.js.map +1 -0
  45. package/dist/a2ui/ui-catalog.js +18 -0
  46. package/dist/a2ui/ui-catalog.js.map +1 -0
  47. package/dist/agent-event.js +10 -0
  48. package/dist/agent-event.js.map +1 -0
  49. package/dist/agent-timeline.js +11 -0
  50. package/dist/agent-timeline.js.map +1 -0
  51. package/dist/agent.js +25 -0
  52. package/dist/agent.js.map +1 -0
  53. package/dist/artifact.js +23 -0
  54. package/dist/artifact.js.map +1 -0
  55. package/dist/asset-preview.js +22 -0
  56. package/dist/asset-preview.js.map +1 -0
  57. package/dist/attachments.js +33 -0
  58. package/dist/attachments.js.map +1 -0
  59. package/dist/audio-player.js +30 -0
  60. package/dist/audio-player.js.map +1 -0
  61. package/dist/audio-visualizer.js +9 -0
  62. package/dist/audio-visualizer.js.map +1 -0
  63. package/dist/canvas.js +10 -0
  64. package/dist/canvas.js.map +1 -0
  65. package/dist/chain-of-thought.js +22 -0
  66. package/dist/chain-of-thought.js.map +1 -0
  67. package/dist/chat-greeting.js +8 -0
  68. package/dist/chat-greeting.js.map +1 -0
  69. package/dist/chat-shell.js +9 -0
  70. package/dist/chat-shell.js.map +1 -0
  71. package/dist/checkpoint.js +13 -0
  72. package/dist/checkpoint.js.map +1 -0
  73. package/dist/chunk-2XOIG5TG.js +72 -0
  74. package/dist/chunk-2XOIG5TG.js.map +1 -0
  75. package/dist/chunk-34CQ2VHM.js +172 -0
  76. package/dist/chunk-34CQ2VHM.js.map +1 -0
  77. package/dist/chunk-3TDHPXZZ.js +60 -0
  78. package/dist/chunk-3TDHPXZZ.js.map +1 -0
  79. package/dist/chunk-3XNPMDZY.js +478 -0
  80. package/dist/chunk-3XNPMDZY.js.map +1 -0
  81. package/dist/chunk-3YPT3V7L.js +56 -0
  82. package/dist/chunk-3YPT3V7L.js.map +1 -0
  83. package/dist/chunk-475UEU2Q.js +87 -0
  84. package/dist/chunk-475UEU2Q.js.map +1 -0
  85. package/dist/chunk-4CBTII2I.js +95 -0
  86. package/dist/chunk-4CBTII2I.js.map +1 -0
  87. package/dist/chunk-4XRNIZMG.js +22 -0
  88. package/dist/chunk-4XRNIZMG.js.map +1 -0
  89. package/dist/chunk-5NNWUKK5.js +2 -0
  90. package/dist/chunk-5NNWUKK5.js.map +1 -0
  91. package/dist/chunk-5UOMU27Z.js +164 -0
  92. package/dist/chunk-5UOMU27Z.js.map +1 -0
  93. package/dist/chunk-5VGYZ62I.js +264 -0
  94. package/dist/chunk-5VGYZ62I.js.map +1 -0
  95. package/dist/chunk-6IQPH2OS.js +21 -0
  96. package/dist/chunk-6IQPH2OS.js.map +1 -0
  97. package/dist/chunk-6PB2MXCI.js +482 -0
  98. package/dist/chunk-6PB2MXCI.js.map +1 -0
  99. package/dist/chunk-7FD5CZEU.js +215 -0
  100. package/dist/chunk-7FD5CZEU.js.map +1 -0
  101. package/dist/chunk-7RL6KZDF.js +266 -0
  102. package/dist/chunk-7RL6KZDF.js.map +1 -0
  103. package/dist/chunk-ADOYAGGK.js +482 -0
  104. package/dist/chunk-ADOYAGGK.js.map +1 -0
  105. package/dist/chunk-AXMNJMMH.js +984 -0
  106. package/dist/chunk-AXMNJMMH.js.map +1 -0
  107. package/dist/chunk-BA3AEMOU.js +21 -0
  108. package/dist/chunk-BA3AEMOU.js.map +1 -0
  109. package/dist/chunk-BBHFOYML.js +336 -0
  110. package/dist/chunk-BBHFOYML.js.map +1 -0
  111. package/dist/chunk-BHUVISIY.js +221 -0
  112. package/dist/chunk-BHUVISIY.js.map +1 -0
  113. package/dist/chunk-BM2LWERA.js +100 -0
  114. package/dist/chunk-BM2LWERA.js.map +1 -0
  115. package/dist/chunk-CMOYXNPJ.js +211 -0
  116. package/dist/chunk-CMOYXNPJ.js.map +1 -0
  117. package/dist/chunk-CZP3RHC4.js +74 -0
  118. package/dist/chunk-CZP3RHC4.js.map +1 -0
  119. package/dist/chunk-DDG5JHQT.js +112 -0
  120. package/dist/chunk-DDG5JHQT.js.map +1 -0
  121. package/dist/chunk-DJODXO7I.js +38 -0
  122. package/dist/chunk-DJODXO7I.js.map +1 -0
  123. package/dist/chunk-DWJDJLPU.js +192 -0
  124. package/dist/chunk-DWJDJLPU.js.map +1 -0
  125. package/dist/chunk-DZW6LM22.js +45 -0
  126. package/dist/chunk-DZW6LM22.js.map +1 -0
  127. package/dist/chunk-ELGCZLZF.js +305 -0
  128. package/dist/chunk-ELGCZLZF.js.map +1 -0
  129. package/dist/chunk-EV3U6ZZB.js +209 -0
  130. package/dist/chunk-EV3U6ZZB.js.map +1 -0
  131. package/dist/chunk-EY7LVUKQ.js +87 -0
  132. package/dist/chunk-EY7LVUKQ.js.map +1 -0
  133. package/dist/chunk-F4C74F7M.js +230 -0
  134. package/dist/chunk-F4C74F7M.js.map +1 -0
  135. package/dist/chunk-FERYDFZA.js +108 -0
  136. package/dist/chunk-FERYDFZA.js.map +1 -0
  137. package/dist/chunk-FUIYG2DS.js +166 -0
  138. package/dist/chunk-FUIYG2DS.js.map +1 -0
  139. package/dist/chunk-GKYZT3LA.js +136 -0
  140. package/dist/chunk-GKYZT3LA.js.map +1 -0
  141. package/dist/chunk-H42LRUQ4.js +102 -0
  142. package/dist/chunk-H42LRUQ4.js.map +1 -0
  143. package/dist/chunk-HVXM2G5F.js +222 -0
  144. package/dist/chunk-HVXM2G5F.js.map +1 -0
  145. package/dist/chunk-I4RDAGVY.js +53 -0
  146. package/dist/chunk-I4RDAGVY.js.map +1 -0
  147. package/dist/chunk-IQJG4IDX.js +208 -0
  148. package/dist/chunk-IQJG4IDX.js.map +1 -0
  149. package/dist/chunk-IX2PXG4Y.js +144 -0
  150. package/dist/chunk-IX2PXG4Y.js.map +1 -0
  151. package/dist/chunk-IXICSOOP.js +287 -0
  152. package/dist/chunk-IXICSOOP.js.map +1 -0
  153. package/dist/chunk-JY5HSN4D.js +84 -0
  154. package/dist/chunk-JY5HSN4D.js.map +1 -0
  155. package/dist/chunk-LMNSBOBG.js +19 -0
  156. package/dist/chunk-LMNSBOBG.js.map +1 -0
  157. package/dist/chunk-MBI7D6IL.js +42 -0
  158. package/dist/chunk-MBI7D6IL.js.map +1 -0
  159. package/dist/chunk-MLFMYCPH.js +192 -0
  160. package/dist/chunk-MLFMYCPH.js.map +1 -0
  161. package/dist/chunk-MOK66734.js +33 -0
  162. package/dist/chunk-MOK66734.js.map +1 -0
  163. package/dist/chunk-MXTAWPYM.js +196 -0
  164. package/dist/chunk-MXTAWPYM.js.map +1 -0
  165. package/dist/chunk-NCL2UZKI.js +96 -0
  166. package/dist/chunk-NCL2UZKI.js.map +1 -0
  167. package/dist/chunk-NET4YLRY.js +107 -0
  168. package/dist/chunk-NET4YLRY.js.map +1 -0
  169. package/dist/chunk-NIG67CFM.js +329 -0
  170. package/dist/chunk-NIG67CFM.js.map +1 -0
  171. package/dist/chunk-NMVNNO3L.js +10 -0
  172. package/dist/chunk-NMVNNO3L.js.map +1 -0
  173. package/dist/chunk-NP7VID4K.js +2 -0
  174. package/dist/chunk-NP7VID4K.js.map +1 -0
  175. package/dist/chunk-NPUCMAG2.js +382 -0
  176. package/dist/chunk-NPUCMAG2.js.map +1 -0
  177. package/dist/chunk-NSCLRHES.js +102 -0
  178. package/dist/chunk-NSCLRHES.js.map +1 -0
  179. package/dist/chunk-OEUXHVFW.js +86 -0
  180. package/dist/chunk-OEUXHVFW.js.map +1 -0
  181. package/dist/chunk-ONBHFIMZ.js +137 -0
  182. package/dist/chunk-ONBHFIMZ.js.map +1 -0
  183. package/dist/chunk-OPH2HHL2.js +228 -0
  184. package/dist/chunk-OPH2HHL2.js.map +1 -0
  185. package/dist/chunk-OQERHIQP.js +287 -0
  186. package/dist/chunk-OQERHIQP.js.map +1 -0
  187. package/dist/chunk-P6YJAZFG.js +103 -0
  188. package/dist/chunk-P6YJAZFG.js.map +1 -0
  189. package/dist/chunk-PG7ERDOD.js +65 -0
  190. package/dist/chunk-PG7ERDOD.js.map +1 -0
  191. package/dist/chunk-PIB5JBMA.js +90 -0
  192. package/dist/chunk-PIB5JBMA.js.map +1 -0
  193. package/dist/chunk-PQ5BPIWQ.js +22 -0
  194. package/dist/chunk-PQ5BPIWQ.js.map +1 -0
  195. package/dist/chunk-PQBF6ZIQ.js +55 -0
  196. package/dist/chunk-PQBF6ZIQ.js.map +1 -0
  197. package/dist/chunk-PTWCTSZL.js +173 -0
  198. package/dist/chunk-PTWCTSZL.js.map +1 -0
  199. package/dist/chunk-QJUNPVOS.js +101 -0
  200. package/dist/chunk-QJUNPVOS.js.map +1 -0
  201. package/dist/chunk-QUDZOTRV.js +43 -0
  202. package/dist/chunk-QUDZOTRV.js.map +1 -0
  203. package/dist/chunk-RB7G65JC.js +213 -0
  204. package/dist/chunk-RB7G65JC.js.map +1 -0
  205. package/dist/chunk-RPHAOR7P.js +45 -0
  206. package/dist/chunk-RPHAOR7P.js.map +1 -0
  207. package/dist/chunk-RTCSH2AN.js +331 -0
  208. package/dist/chunk-RTCSH2AN.js.map +1 -0
  209. package/dist/chunk-S3ISPW3A.js +28 -0
  210. package/dist/chunk-S3ISPW3A.js.map +1 -0
  211. package/dist/chunk-SEVN656N.js +36 -0
  212. package/dist/chunk-SEVN656N.js.map +1 -0
  213. package/dist/chunk-SKVG672B.js +64 -0
  214. package/dist/chunk-SKVG672B.js.map +1 -0
  215. package/dist/chunk-SPQIU7GA.js +236 -0
  216. package/dist/chunk-SPQIU7GA.js.map +1 -0
  217. package/dist/chunk-SSGJ6MEM.js +1076 -0
  218. package/dist/chunk-SSGJ6MEM.js.map +1 -0
  219. package/dist/chunk-SSKZ2AED.js +118 -0
  220. package/dist/chunk-SSKZ2AED.js.map +1 -0
  221. package/dist/chunk-T56JFGXI.js +561 -0
  222. package/dist/chunk-T56JFGXI.js.map +1 -0
  223. package/dist/chunk-TCB6O74A.js +137 -0
  224. package/dist/chunk-TCB6O74A.js.map +1 -0
  225. package/dist/chunk-TTEYPO6X.js +57 -0
  226. package/dist/chunk-TTEYPO6X.js.map +1 -0
  227. package/dist/chunk-TWPHAJNM.js +462 -0
  228. package/dist/chunk-TWPHAJNM.js.map +1 -0
  229. package/dist/chunk-TXJJLP4O.js +336 -0
  230. package/dist/chunk-TXJJLP4O.js.map +1 -0
  231. package/dist/chunk-TZ6TB7VM.js +245 -0
  232. package/dist/chunk-TZ6TB7VM.js.map +1 -0
  233. package/dist/chunk-UBLKJJ7K.js +278 -0
  234. package/dist/chunk-UBLKJJ7K.js.map +1 -0
  235. package/dist/chunk-UCJ6IUFS.js +52 -0
  236. package/dist/chunk-UCJ6IUFS.js.map +1 -0
  237. package/dist/chunk-UCKFJ3QF.js +197 -0
  238. package/dist/chunk-UCKFJ3QF.js.map +1 -0
  239. package/dist/chunk-UPXSLILN.js +20 -0
  240. package/dist/chunk-UPXSLILN.js.map +1 -0
  241. package/dist/chunk-V4DORGWJ.js +92 -0
  242. package/dist/chunk-V4DORGWJ.js.map +1 -0
  243. package/dist/chunk-V6E5DYZD.js +80 -0
  244. package/dist/chunk-V6E5DYZD.js.map +1 -0
  245. package/dist/chunk-VLLYKF3P.js +96 -0
  246. package/dist/chunk-VLLYKF3P.js.map +1 -0
  247. package/dist/chunk-VLNBTOH6.js +43 -0
  248. package/dist/chunk-VLNBTOH6.js.map +1 -0
  249. package/dist/chunk-WMDSMSPL.js +303 -0
  250. package/dist/chunk-WMDSMSPL.js.map +1 -0
  251. package/dist/chunk-WU5BLGTF.js +149 -0
  252. package/dist/chunk-WU5BLGTF.js.map +1 -0
  253. package/dist/chunk-WYTZVSGK.js +245 -0
  254. package/dist/chunk-WYTZVSGK.js.map +1 -0
  255. package/dist/chunk-X47QMM6K.js +187 -0
  256. package/dist/chunk-X47QMM6K.js.map +1 -0
  257. package/dist/chunk-XNBKO32Y.js +174 -0
  258. package/dist/chunk-XNBKO32Y.js.map +1 -0
  259. package/dist/chunk-YHUSW7D2.js +40 -0
  260. package/dist/chunk-YHUSW7D2.js.map +1 -0
  261. package/dist/chunk-YSKD7UXX.js +126 -0
  262. package/dist/chunk-YSKD7UXX.js.map +1 -0
  263. package/dist/chunk-YYRDGWOU.js +72 -0
  264. package/dist/chunk-YYRDGWOU.js.map +1 -0
  265. package/dist/chunk-ZIGZMWM7.js +19 -0
  266. package/dist/chunk-ZIGZMWM7.js.map +1 -0
  267. package/dist/chunk-ZKRTUKNP.js +40 -0
  268. package/dist/chunk-ZKRTUKNP.js.map +1 -0
  269. package/dist/code-block.js +38 -0
  270. package/dist/code-block.js.map +1 -0
  271. package/dist/commit.js +51 -0
  272. package/dist/commit.js.map +1 -0
  273. package/dist/composer.js +15 -0
  274. package/dist/composer.js.map +1 -0
  275. package/dist/confirmation.js +53 -0
  276. package/dist/confirmation.js.map +1 -0
  277. package/dist/connection.js +8 -0
  278. package/dist/connection.js.map +1 -0
  279. package/dist/context-panel.js +25 -0
  280. package/dist/context-panel.js.map +1 -0
  281. package/dist/controls.js +10 -0
  282. package/dist/controls.js.map +1 -0
  283. package/dist/conversation.js +19 -0
  284. package/dist/conversation.js.map +1 -0
  285. package/dist/diff-view.js +15 -0
  286. package/dist/diff-view.js.map +1 -0
  287. package/dist/edge.js +10 -0
  288. package/dist/edge.js.map +1 -0
  289. package/dist/environment-variables.js +29 -0
  290. package/dist/environment-variables.js.map +1 -0
  291. package/dist/file-tree.js +23 -0
  292. package/dist/file-tree.js.map +1 -0
  293. package/dist/gallery.js +9 -0
  294. package/dist/gallery.js.map +1 -0
  295. package/dist/grouped-parts.js +21 -0
  296. package/dist/grouped-parts.js.map +1 -0
  297. package/dist/image.js +9 -0
  298. package/dist/image.js.map +1 -0
  299. package/dist/index.d.ts +366 -98
  300. package/dist/index.js +672 -13577
  301. package/dist/index.js.map +1 -1
  302. package/dist/inline-citation.js +39 -0
  303. package/dist/inline-citation.js.map +1 -0
  304. package/dist/jsx-preview.js +17 -0
  305. package/dist/jsx-preview.js.map +1 -0
  306. package/dist/markdown-view.js +17 -0
  307. package/dist/markdown-view.js.map +1 -0
  308. package/dist/message-compare.js +12 -0
  309. package/dist/message-compare.js.map +1 -0
  310. package/dist/message-edit.js +19 -0
  311. package/dist/message-edit.js.map +1 -0
  312. package/dist/message-feedback.js +11 -0
  313. package/dist/message-feedback.js.map +1 -0
  314. package/dist/message-form-spec.js +38 -0
  315. package/dist/message-form-spec.js.map +1 -0
  316. package/dist/message-form.js +26 -0
  317. package/dist/message-form.js.map +1 -0
  318. package/dist/message-table-spec.js +26 -0
  319. package/dist/message-table-spec.js.map +1 -0
  320. package/dist/message-table.js +12 -0
  321. package/dist/message-table.js.map +1 -0
  322. package/dist/message.js +51 -0
  323. package/dist/message.js.map +1 -0
  324. package/dist/mic-selector.js +27 -0
  325. package/dist/mic-selector.js.map +1 -0
  326. package/dist/model-provider-logo.js +13 -0
  327. package/dist/model-provider-logo.js.map +1 -0
  328. package/dist/motion-config.js +9 -0
  329. package/dist/motion-config.js.map +1 -0
  330. package/dist/node.js +22 -0
  331. package/dist/node.js.map +1 -0
  332. package/dist/open-in-chat.js +31 -0
  333. package/dist/open-in-chat.js.map +1 -0
  334. package/dist/package-info.js +25 -0
  335. package/dist/package-info.js.map +1 -0
  336. package/dist/panel.js +10 -0
  337. package/dist/panel.js.map +1 -0
  338. package/dist/part-groups.js +18 -0
  339. package/dist/part-groups.js.map +1 -0
  340. package/dist/permission-mode-select.js +9 -0
  341. package/dist/permission-mode-select.js.map +1 -0
  342. package/dist/persona-sources.js +8 -0
  343. package/dist/persona-sources.js.map +1 -0
  344. package/dist/persona.js +14 -0
  345. package/dist/persona.js.map +1 -0
  346. package/dist/plan.js +32 -0
  347. package/dist/plan.js.map +1 -0
  348. package/dist/prompt-input-effort.js +9 -0
  349. package/dist/prompt-input-effort.js.map +1 -0
  350. package/dist/prompt-input-mode.js +10 -0
  351. package/dist/prompt-input-mode.js.map +1 -0
  352. package/dist/prompt-input-slash.js +12 -0
  353. package/dist/prompt-input-slash.js.map +1 -0
  354. package/dist/prompt-input.js +89 -0
  355. package/dist/prompt-input.js.map +1 -0
  356. package/dist/queue.js +37 -0
  357. package/dist/queue.js.map +1 -0
  358. package/dist/reasoning.js +23 -0
  359. package/dist/reasoning.js.map +1 -0
  360. package/dist/sandbox.js +28 -0
  361. package/dist/sandbox.js.map +1 -0
  362. package/dist/schema-display.js +33 -0
  363. package/dist/schema-display.js.map +1 -0
  364. package/dist/selection-toolbar.js +11 -0
  365. package/dist/selection-toolbar.js.map +1 -0
  366. package/dist/session-header.js +9 -0
  367. package/dist/session-header.js.map +1 -0
  368. package/dist/session-status-bar.js +9 -0
  369. package/dist/session-status-bar.js.map +1 -0
  370. package/dist/shimmer.js +9 -0
  371. package/dist/shimmer.js.map +1 -0
  372. package/dist/snippet.js +17 -0
  373. package/dist/snippet.js.map +1 -0
  374. package/dist/sources.js +17 -0
  375. package/dist/sources.js.map +1 -0
  376. package/dist/speech-input.js +9 -0
  377. package/dist/speech-input.js.map +1 -0
  378. package/dist/stack-trace.js +27 -0
  379. package/dist/stack-trace.js.map +1 -0
  380. package/dist/suggestion.js +16 -0
  381. package/dist/suggestion.js.map +1 -0
  382. package/dist/task.js +18 -0
  383. package/dist/task.js.map +1 -0
  384. package/dist/test-results.js +43 -0
  385. package/dist/test-results.js.map +1 -0
  386. package/dist/token-usage.js +27 -0
  387. package/dist/token-usage.js.map +1 -0
  388. package/dist/tool-result-card.js +9 -0
  389. package/dist/tool-result-card.js.map +1 -0
  390. package/dist/tool.js +27 -0
  391. package/dist/tool.js.map +1 -0
  392. package/dist/toolbar.js +10 -0
  393. package/dist/toolbar.js.map +1 -0
  394. package/dist/transcription.js +11 -0
  395. package/dist/transcription.js.map +1 -0
  396. package/dist/turn-status.js +9 -0
  397. package/dist/turn-status.js.map +1 -0
  398. package/dist/use-audio-level.js +9 -0
  399. package/dist/use-audio-level.js.map +1 -0
  400. package/dist/voice-selector.js +47 -0
  401. package/dist/voice-selector.js.map +1 -0
  402. package/dist/web-preview.js +19 -0
  403. package/dist/web-preview.js.map +1 -0
  404. package/package.json +11 -9
  405. package/schemas/a2ui-surface.v1.schema.json +5425 -0
  406. package/src/_chat-shell-rail.tsx +3 -1
  407. package/src/_flow-boundary.tsx +2 -2
  408. package/src/_persona-rive.tsx +27 -41
  409. package/src/a2ui/a2ui-surface.stories.tsx +662 -0
  410. package/src/a2ui/a2ui-surface.test.tsx +201 -0
  411. package/src/a2ui/a2ui-surface.tsx +354 -0
  412. package/src/a2ui/catalog.source.json +772 -0
  413. package/src/a2ui/core/a2ui-core.test.ts +178 -0
  414. package/src/a2ui/core/catalog.generated.ts +1006 -0
  415. package/src/a2ui/core/complete-json.ts +81 -0
  416. package/src/a2ui/core/index.ts +10 -0
  417. package/src/a2ui/core/schema.ts +111 -0
  418. package/src/a2ui/core/spec.ts +148 -0
  419. package/src/a2ui/core/validate.ts +266 -0
  420. package/src/a2ui/index.ts +7 -0
  421. package/src/a2ui/ui-catalog.tsx +225 -0
  422. package/src/a2ui/wave1-chart-spec.test.ts +87 -0
  423. package/src/a2ui/wave2-chart-spec.test.ts +108 -0
  424. package/src/agentic-workspace.stories.tsx +6 -45
  425. package/src/chat-shell.test.tsx +40 -10
  426. package/src/chat-shell.tsx +90 -44
  427. package/src/chat.stories.tsx +47 -42
  428. package/src/composer.stories.tsx +4 -5
  429. package/src/composer.test.tsx +45 -0
  430. package/src/composer.tsx +104 -21
  431. package/src/context-panel.stories.tsx +1 -1
  432. package/src/context-panel.tsx +1 -1
  433. package/src/conversation.stories.tsx +1 -0
  434. package/src/conversation.test.tsx +16 -0
  435. package/src/conversation.tsx +16 -2
  436. package/src/diff-view.stories.tsx +79 -0
  437. package/src/diff-view.tsx +3 -2
  438. package/src/file-tree.tsx +24 -17
  439. package/src/gallery.stories.tsx +42 -0
  440. package/src/gallery.tsx +2 -2
  441. package/src/grouped-parts.stories.tsx +23 -0
  442. package/src/grouped-parts.tsx +1 -1
  443. package/src/index.ts +1 -0
  444. package/src/message-compare.stories.tsx +40 -0
  445. package/src/message-compare.tsx +2 -1
  446. package/src/message-form.tsx +1 -1
  447. package/src/message-table.stories.tsx +24 -0
  448. package/src/message-table.tsx +1 -1
  449. package/src/package-info.tsx +12 -9
  450. package/src/reasoning.stories.tsx +27 -0
  451. package/src/reasoning.tsx +1 -1
  452. package/src/session-header.stories.tsx +35 -1
  453. package/src/session-header.tsx +1 -1
  454. package/src/sources.stories.tsx +30 -0
  455. package/src/sources.tsx +4 -1
  456. package/src/templates-ai-assistant.stories.tsx +151 -87
  457. package/src/tool.stories.tsx +39 -0
  458. package/src/tool.tsx +3 -3
  459. package/src/toolbar.tsx +0 -10
  460. package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
  461. package/dist/_persona-rive-JEG44YHX.js.map +0 -1
  462. /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * complete-json.ts — close a PARTIAL JSON document so a streaming surface can be
3
+ * parsed and drawn before the model has finished (the A2UI counterpart of
4
+ * `JSXPreview`'s `completeJsxTag`).
5
+ *
6
+ * Strategy: one linear scan tracking the bracket stack, string state and escape
7
+ * state; then (1) close an open string, (2) drop a dangling `,` or supply `null`
8
+ * for a dangling `"key":`, (3) close every open bracket in reverse. The result is
9
+ * always syntactically valid JSON for any prefix of a valid document that has
10
+ * passed its first `{`. Semantic gaps (a half-typed prop value, a node without
11
+ * its `type` yet) are the validator's business — the renderer prunes what does
12
+ * not validate while streaming and keeps the last good tree.
13
+ */
14
+ export function completeJson(text: string): string {
15
+ const stack: string[] = [];
16
+ let inString = false;
17
+ let escaped = false;
18
+ // Index just after the last STRUCTURALLY complete token, so a half-typed key
19
+ // (`{"ty`) can be cut rather than closed into `{"ty":null}`.
20
+ let lastGood = 0;
21
+ let lastNonWs = "";
22
+
23
+ for (let i = 0; i < text.length; i++) {
24
+ const ch = text[i] as string;
25
+ if (inString) {
26
+ if (escaped) escaped = false;
27
+ else if (ch === "\\") escaped = true;
28
+ else if (ch === '"') {
29
+ inString = false;
30
+ lastNonWs = ch;
31
+ lastGood = i + 1;
32
+ }
33
+ continue;
34
+ }
35
+ if (ch === '"') {
36
+ inString = true;
37
+ continue;
38
+ }
39
+ if (ch === "{" || ch === "[") stack.push(ch === "{" ? "}" : "]");
40
+ else if (ch === "}" || ch === "]") stack.pop();
41
+ if (!/\s/.test(ch)) {
42
+ lastNonWs = ch;
43
+ lastGood = i + 1;
44
+ }
45
+ }
46
+
47
+ let out = text;
48
+ if (inString) {
49
+ // Inside a value string → close it. Inside a KEY (the string follows `{` or
50
+ // `,` inside an object) → cut it: a key without a value is not renderable.
51
+ const top = stack[stack.length - 1];
52
+ if (top === "}" && (lastNonWs === "{" || lastNonWs === ",")) out = text.slice(0, lastGood);
53
+ else out = escaped ? `${text.slice(0, -1)}"` : `${text}"`;
54
+ lastNonWs = out.trimEnd().slice(-1);
55
+ }
56
+ out = out.trimEnd();
57
+ if (lastNonWs === ",") out = out.slice(0, -1);
58
+ else if (lastNonWs === ":") out = `${out}null`;
59
+ // A `"key"` with no colon yet (`{"type"`) is also unfinished — cut it.
60
+ else if (lastNonWs === '"' && stack[stack.length - 1] === "}") {
61
+ const m = /(?:^|[{,])\s*"(?:[^"\\]|\\.)*"$/.exec(out);
62
+ if (m) out = out.slice(0, m.index + (out[m.index] === "{" || out[m.index] === "," ? 1 : 0));
63
+ }
64
+ out = out.replace(/,\s*$/, "");
65
+ return out + stack.reverse().join("");
66
+ }
67
+
68
+ /**
69
+ * Parse `text`, completing it first when `partial`. Returns `null` (never throws)
70
+ * when even the completed text is not JSON — the caller treats that as "no tree
71
+ * yet".
72
+ */
73
+ export function parseSurfaceJson(text: string, partial = false): unknown | null {
74
+ const trimmed = text.trim();
75
+ if (!trimmed) return null;
76
+ try {
77
+ return JSON.parse(partial ? completeJson(trimmed) : trimmed);
78
+ } catch {
79
+ return null;
80
+ }
81
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The engine-free A2UI core: protocol types, the catalog schema, the validator,
3
+ * the streaming JSON completer and the JSON-Schema builder. No React here —
4
+ * `pnpm gen` bundles this folder into the `brand-ui a2ui` CLI verbs.
5
+ */
6
+ export * from "./spec";
7
+ export * from "./validate";
8
+ export * from "./complete-json";
9
+ export * from "./schema";
10
+ export { A2UI_CATALOG_SCHEMA, A2UI_CATALOG_VERSION } from "./catalog.generated";
@@ -0,0 +1,111 @@
1
+ /**
2
+ * schema.ts — the A2UI surface as a JSON Schema (draft 2020-12), built from the
3
+ * catalog so editors, structured-output modes and JSON-Schema validators see the
4
+ * SAME contract `validateA2uiSurface` enforces. Published as
5
+ * `@elabs-ai/components-ai/a2ui/schema.json` and printed by `brand-ui a2ui schema`.
6
+ */
7
+ import {
8
+ A2UI_COMMON_PROPS,
9
+ A2UI_VERSION,
10
+ type A2uiCatalogSchema,
11
+ type A2uiCatalogTypeSchema,
12
+ type A2uiPropSchema,
13
+ } from "./spec";
14
+
15
+ export const A2UI_SURFACE_SCHEMA_ID =
16
+ "https://github.com/mreimitz/elabs-components/packages/ai/schemas/a2ui-surface.v1.schema.json";
17
+
18
+ type JsonSchema = Record<string, unknown>;
19
+
20
+ function propSchema(p: A2uiPropSchema): JsonSchema {
21
+ const base: JsonSchema = {};
22
+ if (p.description) base.description = p.description;
23
+ if (p.default !== undefined) base.default = p.default;
24
+ if (p.enum) return { ...base, enum: p.enum };
25
+ switch (p.type) {
26
+ case "string":
27
+ case "number":
28
+ case "boolean":
29
+ case "array":
30
+ case "object":
31
+ return { ...base, type: p.type };
32
+ case "node":
33
+ return {
34
+ ...base,
35
+ anyOf: [
36
+ { type: "string" },
37
+ { type: "number" },
38
+ { $ref: "#/$defs/element" },
39
+ { type: "array", items: { $ref: "#/$defs/node" } },
40
+ ],
41
+ };
42
+ default:
43
+ return base;
44
+ }
45
+ }
46
+
47
+ function elementSchema(type: string, entry: A2uiCatalogTypeSchema): JsonSchema {
48
+ const props = entry.builtin ? entry.props : { ...A2UI_COMMON_PROPS, ...entry.props };
49
+ const required = Object.entries(entry.props)
50
+ .filter(([, p]) => p.required)
51
+ .map(([name]) => name);
52
+ const properties: JsonSchema = {
53
+ type: { const: type },
54
+ id: { type: "string" },
55
+ props: {
56
+ type: "object",
57
+ properties: Object.fromEntries(Object.entries(props).map(([n, p]) => [n, propSchema(p)])),
58
+ ...(required.length ? { required } : {}),
59
+ additionalProperties: false,
60
+ },
61
+ on: {
62
+ type: "object",
63
+ properties: Object.fromEntries(
64
+ Object.keys(entry.events).map((ev) => [ev, { $ref: "#/$defs/action" }]),
65
+ ),
66
+ additionalProperties: false,
67
+ },
68
+ };
69
+ if (entry.children) properties.children = { type: "array", items: { $ref: "#/$defs/node" } };
70
+ return {
71
+ type: "object",
72
+ ...(entry.summary ? { description: entry.summary } : {}),
73
+ properties,
74
+ required: required.length ? ["type", "props"] : ["type"],
75
+ additionalProperties: false,
76
+ };
77
+ }
78
+
79
+ /** Build the JSON Schema document for `catalog`. Deterministic: sorted types. */
80
+ export function buildA2uiSurfaceSchema(catalog: A2uiCatalogSchema): JsonSchema {
81
+ const types = Object.keys(catalog).sort();
82
+ return {
83
+ $schema: "https://json-schema.org/draft/2020-12/schema",
84
+ $id: A2UI_SURFACE_SCHEMA_ID,
85
+ title: "A2UI surface v1 (brand-ui)",
86
+ description:
87
+ "An agent-designed screen as data: a tree of brand-ui catalog nodes. Every `type` is a catalog entry, props are checked per type, and `on` binds catalog events to host actions. Text is a plain string child.",
88
+ type: "object",
89
+ properties: {
90
+ a2ui: { const: A2UI_VERSION },
91
+ title: { type: "string", description: "Accessible name of the surface region." },
92
+ root: { $ref: "#/$defs/node" },
93
+ },
94
+ required: ["a2ui", "root"],
95
+ additionalProperties: false,
96
+ $defs: {
97
+ action: {
98
+ type: "object",
99
+ properties: {
100
+ name: { type: "string", minLength: 1, description: "The host-side verb." },
101
+ payload: { description: "Free JSON attached to the action." },
102
+ },
103
+ required: ["name"],
104
+ additionalProperties: false,
105
+ },
106
+ node: { anyOf: [{ type: "string" }, { $ref: "#/$defs/element" }] },
107
+ element: { oneOf: types.map((t) => ({ $ref: `#/$defs/${t}` })) },
108
+ ...Object.fromEntries(types.map((t) => [t, elementSchema(t, catalog[t]!)])),
109
+ },
110
+ };
111
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * spec.ts — the A2UI surface protocol (D2, the generative-UI path: "the agent
3
+ * describes a screen as DATA, validated against a catalog").
4
+ *
5
+ * An `A2uiSurface` is plain JSON an agent emits — a tree of catalog nodes. It is
6
+ * NOT JSX (that is `JSXPreview`, the escape hatch) and it carries no code: every
7
+ * `type` must exist in the catalog, every prop is checked against that type's
8
+ * schema, and interaction is a named `on` binding the HOST app resolves
9
+ * (`onAction`). brand-ui renders the tree; the app owns the model call and what
10
+ * an action means (D5).
11
+ *
12
+ * Engine-free on purpose (no React import): `validateA2uiSurface` runs in the
13
+ * browser, in Node, and — bundled by `pnpm gen` — inside the dependency-free
14
+ * `brand-ui a2ui` CLI, so the CLI and `@elabs-ai/components-ai` can never
15
+ * disagree about what a valid surface is.
16
+ */
17
+
18
+ /** Protocol version this module understands (`"a2ui": "1"` on the root). */
19
+ export const A2UI_VERSION = "1";
20
+
21
+ /**
22
+ * A JSON value an agent may place in a prop. The `object` arm is there for
23
+ * authoring: an app hands typed records (an interface for a KPI, a chart row) to
24
+ * a spec literal without an index-signature cast; the runtime validator, not the
25
+ * type, is what decides whether a value is acceptable.
26
+ */
27
+ export type A2uiJson =
28
+ | string
29
+ | number
30
+ | boolean
31
+ | null
32
+ | undefined
33
+ | readonly A2uiJson[]
34
+ | { readonly [key: string]: A2uiJson }
35
+ | object;
36
+
37
+ /**
38
+ * A node's prop value: a JSON value, or — for props the catalog types as `node`
39
+ * (`title`, `description`, `actions`, …) — a nested node or list of nodes.
40
+ */
41
+ export type A2uiPropValue = A2uiJson | A2uiNode | A2uiNode[];
42
+
43
+ /** What a bound event sends to the host: a NAME (the app's verb) and a payload. */
44
+ export interface A2uiAction {
45
+ /** The host-side verb, e.g. `"approve"`, `"open-order"`. Never a code string. */
46
+ name: string;
47
+ /** Free JSON the agent attaches (an id, a row, a form draft). */
48
+ payload?: A2uiJson;
49
+ }
50
+
51
+ /** An element node. Text nodes are plain strings inside `children`. */
52
+ export interface A2uiElement {
53
+ /** A catalog type — `"Card"`, `"Button"`, `"Stack"`, … Unknown types are errors. */
54
+ type: string;
55
+ /** Optional stable id (→ `data-a2ui-id`), useful for the host to address a node. */
56
+ id?: string;
57
+ /** Props checked against the catalog entry's schema. */
58
+ props?: Record<string, A2uiPropValue>;
59
+ /** Child nodes — only for catalog types that accept children. */
60
+ children?: A2uiNode[];
61
+ /**
62
+ * Event bindings by the catalog's event vocabulary (`click`, `change`, …) →
63
+ * the action the host receives. The renderer wires the React handler.
64
+ */
65
+ on?: Record<string, A2uiAction>;
66
+ }
67
+
68
+ export type A2uiNode = string | A2uiElement;
69
+
70
+ /** The document an agent emits (the whole tool-call result / message part). */
71
+ export interface A2uiSurfaceSpec {
72
+ /** Protocol version — currently always `"1"`. */
73
+ a2ui: string;
74
+ /** Optional accessible name for the surface region. */
75
+ title?: string;
76
+ /** The root node — usually a `Stack`, `Grid` or `Card`. */
77
+ root: A2uiNode;
78
+ }
79
+
80
+ /** The value shape of one prop in a catalog entry. */
81
+ export type A2uiPropType = "string" | "number" | "boolean" | "node" | "array" | "object" | "any";
82
+
83
+ export interface A2uiPropSchema {
84
+ type: A2uiPropType;
85
+ /** Closed set of allowed values (strings or numbers); `type` is then informational. */
86
+ enum?: (string | number)[];
87
+ required?: boolean;
88
+ default?: A2uiJson;
89
+ description?: string;
90
+ }
91
+
92
+ /** One catalog type — what an agent may emit for it. */
93
+ export interface A2uiCatalogTypeSchema {
94
+ /** Drawn by the renderer itself (`Stack`, `Grid`), not a library component. */
95
+ builtin?: boolean;
96
+ /** May carry `children`. */
97
+ children: boolean;
98
+ /** One line for the agent (rendered by `brand-ui a2ui catalog`). */
99
+ summary?: string;
100
+ /** Prop name → schema. Anything not listed (and not in `A2UI_COMMON_PROPS`) is an error. */
101
+ props: Record<string, A2uiPropSchema>;
102
+ /** Event vocabulary → React handler prop (`click` → `onClick`). */
103
+ events: Record<string, string>;
104
+ /** Where the component comes from (`@elabs-ai/components-ui`) or `"builtin"`. */
105
+ source: string;
106
+ }
107
+
108
+ export type A2uiCatalogSchema = Record<string, A2uiCatalogTypeSchema>;
109
+
110
+ /**
111
+ * Props every non-builtin element accepts on top of its own schema: the DOM
112
+ * attributes that are safe for an agent to set. Deliberately NO `className` or
113
+ * `style` — a surface inherits the app's theme and tokens; it never restyles.
114
+ */
115
+ export const A2UI_COMMON_PROPS: Record<string, A2uiPropSchema> = {
116
+ id: { type: "string" },
117
+ title: { type: "string" },
118
+ role: { type: "string" },
119
+ hidden: { type: "boolean" },
120
+ lang: { type: "string" },
121
+ dir: { type: "string", enum: ["ltr", "rtl", "auto"] },
122
+ "aria-label": { type: "string" },
123
+ "aria-labelledby": { type: "string" },
124
+ "aria-describedby": { type: "string" },
125
+ "aria-hidden": { type: "boolean" },
126
+ };
127
+
128
+ /** Machine-readable problem codes from `validateA2uiSurface`. */
129
+ export type A2uiErrorCode =
130
+ | "invalid-root"
131
+ | "unsupported-version"
132
+ | "invalid-node"
133
+ | "unknown-type"
134
+ | "unknown-prop"
135
+ | "missing-prop"
136
+ | "invalid-value"
137
+ | "children-not-allowed"
138
+ | "unknown-event"
139
+ | "invalid-action";
140
+
141
+ export interface A2uiError {
142
+ /** JSON-pointer-ish path: `root.children[2].props.variant`. */
143
+ path: string;
144
+ /** The path of the NODE that owns the problem (`root.children[2]`) — what a streaming renderer prunes. */
145
+ node: string;
146
+ code: A2uiErrorCode;
147
+ message: string;
148
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * validate.ts — `validateA2uiSurface`: is this JSON a surface the catalog can
3
+ * render? Never throws, never repairs; every problem is a typed `A2uiError` with
4
+ * a path, so an agent can fix its own output from the message and a host can
5
+ * prune the failing subtree while streaming (`invalidNodePaths`).
6
+ */
7
+ import {
8
+ A2UI_COMMON_PROPS,
9
+ A2UI_VERSION,
10
+ type A2uiAction,
11
+ type A2uiCatalogSchema,
12
+ type A2uiCatalogTypeSchema,
13
+ type A2uiElement,
14
+ type A2uiError,
15
+ type A2uiNode,
16
+ type A2uiPropSchema,
17
+ type A2uiSurfaceSpec,
18
+ } from "./spec";
19
+
20
+ export type A2uiValidation =
21
+ | { ok: true; spec: A2uiSurfaceSpec; errors: [] }
22
+ | { ok: false; spec: A2uiSurfaceSpec | null; errors: A2uiError[] };
23
+
24
+ type Report = (e: Omit<A2uiError, "node">) => void;
25
+
26
+ const isRecord = (v: unknown): v is Record<string, unknown> =>
27
+ typeof v === "object" && v !== null && !Array.isArray(v);
28
+
29
+ /** An element-shaped value: an object with a string `type`. */
30
+ export const isA2uiElement = (v: unknown): v is A2uiElement =>
31
+ isRecord(v) && typeof v.type === "string";
32
+
33
+ /** Reserved keys on an element — anything else is a typo, not a prop. */
34
+ const ELEMENT_KEYS = new Set(["type", "id", "props", "children", "on"]);
35
+
36
+ function checkValue(
37
+ value: unknown,
38
+ schema: A2uiPropSchema,
39
+ path: string,
40
+ report: Report,
41
+ errors: A2uiError[],
42
+ catalog: A2uiCatalogSchema,
43
+ ): void {
44
+ if (schema.enum) {
45
+ if (!schema.enum.includes(value as string | number)) {
46
+ report({
47
+ path,
48
+ code: "invalid-value",
49
+ message: `must be one of ${schema.enum.map((e) => JSON.stringify(e)).join(", ")}; got ${JSON.stringify(value)}`,
50
+ });
51
+ }
52
+ return;
53
+ }
54
+ const t = schema.type;
55
+ const bad = (expected: string) =>
56
+ report({
57
+ path,
58
+ code: "invalid-value",
59
+ message: `expected ${expected}; got ${Array.isArray(value) ? "array" : typeof value}`,
60
+ });
61
+ switch (t) {
62
+ case "string":
63
+ if (typeof value !== "string") bad("a string");
64
+ break;
65
+ case "number":
66
+ if (typeof value !== "number" || !Number.isFinite(value)) bad("a number");
67
+ break;
68
+ case "boolean":
69
+ if (typeof value !== "boolean") bad("a boolean");
70
+ break;
71
+ case "array":
72
+ if (!Array.isArray(value)) bad("an array");
73
+ break;
74
+ case "object":
75
+ if (!isRecord(value)) bad("an object");
76
+ break;
77
+ case "node": {
78
+ // Text, a number, one element, or a list of nodes — each element validated.
79
+ const items = Array.isArray(value) ? value : [value];
80
+ items.forEach((item, i) => {
81
+ const p = Array.isArray(value) ? `${path}[${i}]` : path;
82
+ if (typeof item === "string" || typeof item === "number") return;
83
+ if (isA2uiElement(item)) return checkNode(item, p, errors, catalog);
84
+ report({
85
+ path: p,
86
+ code: "invalid-value",
87
+ message: "expected text or a node ({ type, … })",
88
+ });
89
+ });
90
+ break;
91
+ }
92
+ case "any":
93
+ break;
94
+ }
95
+ }
96
+
97
+ function checkAction(value: unknown, path: string, report: Report): value is A2uiAction {
98
+ if (!isRecord(value) || typeof value.name !== "string" || !value.name.trim()) {
99
+ report({
100
+ path,
101
+ code: "invalid-action",
102
+ message: 'an action is { "name": "<host verb>", "payload"?: <json> }',
103
+ });
104
+ return false;
105
+ }
106
+ return true;
107
+ }
108
+
109
+ function checkNode(
110
+ node: unknown,
111
+ path: string,
112
+ errors: A2uiError[],
113
+ catalog: A2uiCatalogSchema,
114
+ ): void {
115
+ const report: Report = (e) => errors.push({ ...e, node: path });
116
+ if (typeof node === "string") return;
117
+ if (!isA2uiElement(node)) {
118
+ report({
119
+ path,
120
+ code: "invalid-node",
121
+ message: 'a node is a string or { "type": "<catalog type>", … }',
122
+ });
123
+ return;
124
+ }
125
+ const entry: A2uiCatalogTypeSchema | undefined = catalog[node.type];
126
+ if (!entry) {
127
+ report({
128
+ path: `${path}.type`,
129
+ code: "unknown-type",
130
+ message: `"${node.type}" is not in the catalog (run \`brand-ui a2ui catalog\`)`,
131
+ });
132
+ return;
133
+ }
134
+ for (const key of Object.keys(node)) {
135
+ if (!ELEMENT_KEYS.has(key)) {
136
+ report({
137
+ path: `${path}.${key}`,
138
+ code: "invalid-node",
139
+ message: `unknown key "${key}" — a node has type, id, props, children, on`,
140
+ });
141
+ }
142
+ }
143
+ if (node.id !== undefined && typeof node.id !== "string") {
144
+ report({ path: `${path}.id`, code: "invalid-value", message: "id must be a string" });
145
+ }
146
+ const props = node.props;
147
+ if (props !== undefined && !isRecord(props)) {
148
+ report({ path: `${path}.props`, code: "invalid-value", message: "props must be an object" });
149
+ } else {
150
+ const allowed: Record<string, A2uiPropSchema> = entry.builtin
151
+ ? entry.props
152
+ : { ...A2UI_COMMON_PROPS, ...entry.props };
153
+ for (const [name, schema] of Object.entries(entry.props)) {
154
+ if (schema.required && (props === undefined || props[name] === undefined)) {
155
+ report({
156
+ path: `${path}.props.${name}`,
157
+ code: "missing-prop",
158
+ message: `"${node.type}" requires "${name}"`,
159
+ });
160
+ }
161
+ }
162
+ if (props) {
163
+ for (const [name, value] of Object.entries(props)) {
164
+ const schema = allowed[name];
165
+ if (!schema) {
166
+ report({
167
+ path: `${path}.props.${name}`,
168
+ code: "unknown-prop",
169
+ message: `"${name}" is not a prop of "${node.type}" (allowed: ${Object.keys(allowed).join(", ") || "none"})`,
170
+ });
171
+ continue;
172
+ }
173
+ checkValue(value, schema, `${path}.props.${name}`, report, errors, catalog);
174
+ }
175
+ }
176
+ }
177
+ if (node.children !== undefined) {
178
+ if (!entry.children) {
179
+ report({
180
+ path: `${path}.children`,
181
+ code: "children-not-allowed",
182
+ message: `"${node.type}" does not take children`,
183
+ });
184
+ } else if (!Array.isArray(node.children)) {
185
+ report({
186
+ path: `${path}.children`,
187
+ code: "invalid-value",
188
+ message: "children must be an array of nodes",
189
+ });
190
+ } else {
191
+ node.children.forEach((child, i) =>
192
+ checkNode(child, `${path}.children[${i}]`, errors, catalog),
193
+ );
194
+ }
195
+ }
196
+ if (node.on !== undefined) {
197
+ if (!isRecord(node.on)) {
198
+ report({ path: `${path}.on`, code: "invalid-value", message: "on must be an object" });
199
+ } else {
200
+ for (const [event, action] of Object.entries(node.on)) {
201
+ if (!entry.events[event]) {
202
+ report({
203
+ path: `${path}.on.${event}`,
204
+ code: "unknown-event",
205
+ message: `"${node.type}" has no "${event}" event (${Object.keys(entry.events).join(", ") || "none"})`,
206
+ });
207
+ continue;
208
+ }
209
+ checkAction(action, `${path}.on.${event}`, report);
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Validate an untrusted value (a parsed tool result, a streamed JSON prefix)
217
+ * against `catalog`. `ok: false` carries every problem found, in document order.
218
+ */
219
+ export function validateA2uiSurface(input: unknown, catalog: A2uiCatalogSchema): A2uiValidation {
220
+ const errors: A2uiError[] = [];
221
+ const report: Report = (e) => errors.push({ ...e, node: "root" });
222
+ if (!isRecord(input)) {
223
+ return {
224
+ ok: false,
225
+ spec: null,
226
+ errors: [
227
+ {
228
+ path: "",
229
+ node: "root",
230
+ code: "invalid-root",
231
+ message: 'expected { "a2ui": "1", "root": … }',
232
+ },
233
+ ],
234
+ };
235
+ }
236
+ if (input.a2ui !== A2UI_VERSION) {
237
+ report({
238
+ path: "a2ui",
239
+ code: "unsupported-version",
240
+ message: `expected "a2ui": "${A2UI_VERSION}"; got ${JSON.stringify(input.a2ui)}`,
241
+ });
242
+ }
243
+ if (input.title !== undefined && typeof input.title !== "string") {
244
+ report({ path: "title", code: "invalid-value", message: "title must be a string" });
245
+ }
246
+ if (input.root === undefined) {
247
+ report({ path: "root", code: "invalid-root", message: "root is required" });
248
+ } else {
249
+ checkNode(input.root, "root", errors, catalog);
250
+ }
251
+ const spec = input as unknown as A2uiSurfaceSpec;
252
+ return errors.length ? { ok: false, spec, errors } : { ok: true, spec, errors: [] };
253
+ }
254
+
255
+ /**
256
+ * The set of NODE paths (`root`, `root.children[1]`, …) that own at least one
257
+ * error — the renderer drops exactly those subtrees while a surface is still
258
+ * streaming, so a half-arrived node never blanks its finished siblings.
259
+ */
260
+ export function invalidNodePaths(errors: A2uiError[]): Set<string> {
261
+ return new Set(errors.map((e) => e.node));
262
+ }
263
+
264
+ /** Re-export for hosts that want the version without importing the whole spec module. */
265
+ export { A2UI_VERSION };
266
+ export type { A2uiNode };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A2UI — the generative-UI path (D2): an agent describes a screen as data, brand-ui
3
+ * validates it against a catalog and renders it with the real components.
4
+ */
5
+ export * from "./a2ui-surface";
6
+ export * from "./ui-catalog";
7
+ export * from "./core";