@kitn.ai/ui 0.20.0 → 0.21.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 (500) hide show
  1. package/README.md +44 -45
  2. package/dist/components/artifact-card.d.ts +51 -0
  3. package/dist/components/artifact.d.ts +1 -1
  4. package/dist/components/attachments.d.ts +2 -2
  5. package/dist/components/audio-visualizer/index.d.ts +3 -3
  6. package/dist/components/audio-visualizer/labs/lab-choreography.d.ts +59 -0
  7. package/dist/components/audio-visualizer/labs/lab-shaders.d.ts +22 -0
  8. package/dist/components/audio-visualizer/labs/lab-visualizer.d.ts +18 -0
  9. package/dist/components/audio-visualizer/variant-aurora.d.ts +2 -2
  10. package/dist/components/audio-visualizer/variant-bar.d.ts +2 -2
  11. package/dist/components/audio-visualizer/variant-custom.d.ts +2 -2
  12. package/dist/components/audio-visualizer/variant-grid.d.ts +1 -1
  13. package/dist/components/audio-visualizer/variant-radial.d.ts +1 -1
  14. package/dist/components/audio-visualizer/variant-wave.d.ts +1 -1
  15. package/dist/components/card-fallback.d.ts +12 -2
  16. package/dist/components/card-renderer.d.ts +63 -2
  17. package/dist/components/chat-container.d.ts +3 -0
  18. package/dist/components/chat-scope-picker.d.ts +2 -2
  19. package/dist/components/chat-thread.d.ts +68 -18
  20. package/dist/components/choice-card.d.ts +3 -28
  21. package/dist/components/composer-dom.d.ts +1 -1
  22. package/dist/components/composer-highlight.d.ts +1 -1
  23. package/dist/components/composer-history.d.ts +1 -1
  24. package/dist/components/composer.d.ts +1 -1
  25. package/dist/components/confirm-card.d.ts +3 -18
  26. package/dist/components/context.d.ts +8 -4
  27. package/dist/components/conversation-item.d.ts +1 -1
  28. package/dist/components/conversation-list.d.ts +4 -3
  29. package/dist/components/embed.d.ts +3 -3
  30. package/dist/components/file-tree.d.ts +11 -22
  31. package/dist/components/form-widgets.d.ts +1 -1
  32. package/dist/components/form.d.ts +3 -44
  33. package/dist/components/link-preview.d.ts +3 -3
  34. package/dist/components/loader.d.ts +30 -48
  35. package/dist/components/message-skills.d.ts +4 -0
  36. package/dist/components/message.d.ts +84 -21
  37. package/dist/components/model-switcher.d.ts +2 -2
  38. package/dist/components/prompt-input.d.ts +2 -2
  39. package/dist/components/response-compare-types.d.ts +11 -2
  40. package/dist/components/response-compare.d.ts +3 -3
  41. package/dist/components/source.d.ts +12 -3
  42. package/dist/components/tasks-card.d.ts +3 -31
  43. package/dist/components/thread.d.ts +17 -5
  44. package/dist/components/toast.d.ts +2 -2
  45. package/dist/components/tool-classify.d.ts +8 -0
  46. package/dist/components/tool-types.d.ts +29 -1
  47. package/dist/components/tool.d.ts +3 -3
  48. package/dist/components/use-card-resolution.d.ts +1 -1
  49. package/dist/create-tween-D3Y5qiij.js +338 -0
  50. package/dist/create-tween-DGKY1FDY.js +341 -0
  51. package/dist/create-tween-paho5Rh-.js +7 -0
  52. package/dist/custom-elements.json +1681 -454
  53. package/dist/elements/agent-card.js +1 -1
  54. package/dist/elements/artifact.js +1 -1
  55. package/dist/elements/attachments.js +1 -1
  56. package/dist/elements/audio-visualizer.js +1 -1
  57. package/dist/elements/avatar.js +1 -1
  58. package/dist/elements/badge.js +1 -1
  59. package/dist/elements/button.js +1 -1
  60. package/dist/elements/card.js +1 -1
  61. package/dist/elements/cards.js +1 -1
  62. package/dist/elements/chain-of-thought.js +1 -1
  63. package/dist/elements/chat-scope-picker.js +1 -1
  64. package/dist/elements/chat-types.d.ts +70 -10
  65. package/dist/elements/chat-workspace.js +1 -1
  66. package/dist/elements/chat.js +1 -1
  67. package/dist/elements/checkpoint.js +1 -1
  68. package/dist/elements/choice.js +1 -1
  69. package/dist/elements/chunks/{Icon-Tj58ES_d.js → Icon-C-2LvGDG.js} +1 -1
  70. package/dist/elements/chunks/{action-icons-ns1Fnedj.js → action-icons-CaYoImEk.js} +1 -1
  71. package/dist/elements/chunks/arrow-left-Bb46H7w9.js +1 -0
  72. package/dist/elements/chunks/artifact-BBIscOxJ.js +1 -0
  73. package/dist/elements/chunks/{attachments-mCB5F1Fq.js → attachments-BB56zoji.js} +1 -1
  74. package/dist/elements/chunks/audio-visualizer-BxOx4THz.js +1 -0
  75. package/dist/elements/chunks/{badge-B4Zuajl2.js → badge-SxLSZ19R.js} +1 -1
  76. package/dist/elements/chunks/{button-ZWNif3--.js → button-CmkUkz6c.js} +1 -1
  77. package/dist/elements/chunks/card-renderer-Db4ffkWv.js +1 -0
  78. package/dist/elements/chunks/card-tags-D8lZ-C_U.js +1 -0
  79. package/dist/elements/chunks/chat-thread-B3Ks-cKr.js +1 -0
  80. package/dist/elements/chunks/check-C8desc_h.js +1 -0
  81. package/dist/elements/chunks/chevron-down-DKtc2HNB.js +1 -0
  82. package/dist/elements/chunks/chevron-right-Dw4GPhwL.js +1 -0
  83. package/dist/elements/chunks/choice-card-Q9cYYDyM.js +1 -0
  84. package/dist/elements/chunks/circle-BeokBsvB.js +1 -0
  85. package/dist/elements/chunks/circle-check-wJSqt859.js +1 -0
  86. package/dist/elements/chunks/{circle-x-B7faJFlY.js → circle-x-D0MEfxOM.js} +1 -1
  87. package/dist/elements/chunks/code-block-C8VzAraE.js +1 -0
  88. package/dist/elements/chunks/{collapsible-DM1Ckd4e.js → collapsible-Cvj61obE.js} +1 -1
  89. package/dist/elements/chunks/{composer-BguS0QL_.js → composer-D86ztyL0.js} +2 -2
  90. package/dist/elements/chunks/confirm-card-BdyDAGLw.js +1 -0
  91. package/dist/elements/chunks/context-WHDl-xSx.js +1 -0
  92. package/dist/elements/chunks/conversation-list-CdR14_Y4.js +1 -0
  93. package/dist/elements/chunks/create-tween-C_A_B638.js +7 -0
  94. package/dist/elements/chunks/{default-input-Cqqilg9t.js → default-input-CSZqUM81.js} +1 -1
  95. package/dist/elements/chunks/define-BzPnNsXg.js +1 -0
  96. package/dist/elements/chunks/{disclosure-CIZ5c8nO.js → disclosure-DVKsoc1F.js} +1 -1
  97. package/dist/elements/chunks/{download-Dsbg3ste.js → download-BjA54IMJ.js} +1 -1
  98. package/dist/elements/chunks/{dropdown-BDd1-Zgi.js → dropdown-BjVVHWXH.js} +1 -1
  99. package/dist/elements/chunks/{ellipsis-Dw6qrss-.js → ellipsis-BNedmqfi.js} +1 -1
  100. package/dist/elements/chunks/embed-DQsl4XEq.js +1 -0
  101. package/dist/elements/chunks/{external-link-Vt74zAoL.js → external-link-Di-dw2CU.js} +1 -1
  102. package/dist/elements/chunks/{file-text-CZrZF6_v.js → file-text-B3sAODCV.js} +1 -1
  103. package/dist/elements/chunks/{file-tree-DF4okKyo.js → file-tree-Dgto-bMn.js} +1 -1
  104. package/dist/elements/chunks/{folder-glP5rha4.js → folder-D6rMadFV.js} +1 -1
  105. package/dist/elements/chunks/form-CILxvhQ7.js +1 -0
  106. package/dist/elements/chunks/hover-card-BtiF4XiU.js +1 -0
  107. package/dist/elements/chunks/{icon-BLb8beoi.js → icon-DKkmze3y.js} +1 -1
  108. package/dist/elements/chunks/{info-CIsv92JK.js → info-CWRjZkuy.js} +1 -1
  109. package/dist/elements/chunks/{input-Dds1kFyt.js → input--QJBK6BA.js} +1 -1
  110. package/dist/elements/chunks/{kbd-De_xbgi9.js → kbd-C3zuKh8R.js} +1 -1
  111. package/dist/elements/chunks/{link-i4r_k7z4.js → link-BL5JA7Q0.js} +1 -1
  112. package/dist/elements/chunks/link-preview-CU37bbXh.js +1 -0
  113. package/dist/elements/chunks/{loader-BmQH4s3V.js → loader-XmpyxyRH.js} +1 -1
  114. package/dist/elements/chunks/{markdown-Zi21WhUz.js → markdown-3Gv5UZ_o.js} +1 -1
  115. package/dist/elements/chunks/message-CnBA2OUt.js +1 -0
  116. package/dist/elements/chunks/message-X5NZbq-W.js +1 -0
  117. package/dist/elements/chunks/message-square-CnpAm_P0.js +1 -0
  118. package/dist/elements/chunks/{minimize-2--ifeCGrl.js → minimize-2-DwyrUTcM.js} +1 -1
  119. package/dist/elements/chunks/{model-switcher-B94YAKsM.js → model-switcher-CclaJEHt.js} +1 -1
  120. package/dist/elements/chunks/{overlay-kD8dwRv_.js → overlay-Cepd-KcS.js} +1 -1
  121. package/dist/elements/chunks/{paperclip-q21dYOSK.js → paperclip-CdwKjrlu.js} +1 -1
  122. package/dist/elements/chunks/{progress-bar-BrAIIaaJ.js → progress-bar-DMVXBD3b.js} +1 -1
  123. package/dist/elements/chunks/{prompt-suggestion-Bjn2K-fR.js → prompt-suggestion-Di_WZE_5.js} +1 -1
  124. package/dist/elements/chunks/reasoning-D0jMch5u.js +1 -0
  125. package/dist/elements/chunks/{resizable-Dp4JExql.js → resizable-1znbL1Gv.js} +1 -1
  126. package/dist/elements/chunks/{rotate-cw-CFWWkpj2.js → rotate-cw-DVhhgx8n.js} +1 -1
  127. package/dist/elements/chunks/{scroll-area-Bb0kHH1j.js → scroll-area-Bs4bFS1P.js} +1 -1
  128. package/dist/elements/chunks/scroll-button-Bet5NLc4.js +1 -0
  129. package/dist/elements/chunks/{separator-9kRgr1X9.js → separator-C5Gh8qGC.js} +1 -1
  130. package/dist/elements/chunks/{settings-B8lmec4D.js → settings-5vmEFg0K.js} +1 -1
  131. package/dist/elements/chunks/{settings-group-I0hEuXiN.js → settings-group-BWLB38kz.js} +1 -1
  132. package/dist/elements/chunks/{share-C3lTiYGt.js → share-BZ3G_DaB.js} +1 -1
  133. package/dist/elements/chunks/skeleton-DafPJQTp.js +1 -0
  134. package/dist/elements/chunks/slots-CIw9RlAe.js +1 -0
  135. package/dist/elements/chunks/source-D_qj_6uJ.js +1 -0
  136. package/dist/elements/chunks/{star-CSJtGxgv.js → star-Cuv7j2IE.js} +1 -1
  137. package/dist/elements/chunks/{store-CHyW95TP.js → store-C1StPHfW.js} +1 -1
  138. package/dist/elements/chunks/tasks-card-EyoBZfpA.js +1 -0
  139. package/dist/elements/chunks/{text-shimmer-Cn9TmNpI.js → text-shimmer-D9gRSh34.js} +1 -1
  140. package/dist/elements/chunks/textarea-DuhtHfcm.js +1 -0
  141. package/dist/elements/chunks/{thumbs-up-PNVVThEF.js → thumbs-up-B9hwv43w.js} +1 -1
  142. package/dist/elements/chunks/{toast-store-DKbQn3Wn.js → toast-store-Bm3DUEDe.js} +1 -1
  143. package/dist/elements/chunks/{tool-DjTRpIpl.js → tool-CDtW7L0z.js} +1 -1
  144. package/dist/elements/chunks/tooltip-eB226mGK.js +1 -0
  145. package/dist/elements/chunks/{triangle-alert-DsHTHCPm.js → triangle-alert-C1SNzTqK.js} +1 -1
  146. package/dist/elements/chunks/use-card-resolution-YZh2MvI5.js +1 -0
  147. package/dist/elements/chunks/{variant-aurora-Dc4nQUia.js → variant-aurora-Cj1F7D0l.js} +2 -2
  148. package/dist/elements/chunks/{variant-custom-y_3kVQhS.js → variant-custom-T9gpt7QE.js} +1 -1
  149. package/dist/elements/chunks/{variant-wave-D5OR1-9Z.js → variant-wave-CxU9z-TE.js} +2 -2
  150. package/dist/elements/chunks/{video-B7vmenoC.js → video-CK4R7Rus.js} +1 -1
  151. package/dist/elements/chunks/x-D1qx0aLd.js +1 -0
  152. package/dist/elements/coachmark.js +1 -1
  153. package/dist/elements/code-block.js +1 -1
  154. package/dist/elements/command.js +1 -1
  155. package/dist/elements/compare.js +1 -1
  156. package/dist/elements/composer.js +1 -1
  157. package/dist/elements/confirm-card.js +1 -1
  158. package/dist/elements/context-meter.js +1 -1
  159. package/dist/elements/conversation-list.js +1 -1
  160. package/dist/elements/default-input.d.ts +7 -7
  161. package/dist/elements/define.d.ts +1 -0
  162. package/dist/elements/dialog.js +1 -1
  163. package/dist/elements/disclosure.d.ts +1 -1
  164. package/dist/elements/editable-label.js +1 -1
  165. package/dist/elements/element-data-types.d.ts +107 -0
  166. package/dist/elements/embed.js +1 -1
  167. package/dist/elements/empty.js +1 -1
  168. package/dist/elements/feedback-bar.js +1 -1
  169. package/dist/elements/file-tree.js +1 -1
  170. package/dist/elements/file-upload.js +1 -1
  171. package/dist/elements/form.js +1 -1
  172. package/dist/elements/hover-card.js +1 -1
  173. package/dist/elements/icon.js +1 -1
  174. package/dist/elements/image.js +1 -1
  175. package/dist/elements/input.js +1 -1
  176. package/dist/elements/kbd.js +1 -1
  177. package/dist/elements/link-preview.js +1 -1
  178. package/dist/elements/loader.js +1 -1
  179. package/dist/elements/markdown.js +1 -1
  180. package/dist/elements/menu.js +1 -1
  181. package/dist/elements/message-skills.js +1 -1
  182. package/dist/elements/message.js +1 -1
  183. package/dist/elements/model-switcher.js +1 -1
  184. package/dist/elements/nav.js +1 -1
  185. package/dist/elements/notice.js +1 -1
  186. package/dist/elements/pane-group.js +1 -1
  187. package/dist/elements/pane.js +1 -1
  188. package/dist/elements/popover.js +1 -1
  189. package/dist/elements/progress-bar.js +1 -1
  190. package/dist/elements/prompt-dock.js +1 -1
  191. package/dist/elements/prompt-input.js +1 -1
  192. package/dist/elements/prompt-suggestions.js +1 -1
  193. package/dist/elements/reasoning.js +1 -1
  194. package/dist/elements/register.d.ts +8 -6
  195. package/dist/elements/remote.js +1 -1
  196. package/dist/elements/resizable.js +1 -1
  197. package/dist/elements/response-stream.js +2 -2
  198. package/dist/elements/screen.js +1 -1
  199. package/dist/elements/scroll-area.js +1 -1
  200. package/dist/elements/scroll-button.js +1 -1
  201. package/dist/elements/search.js +1 -1
  202. package/dist/elements/segmented.js +1 -1
  203. package/dist/elements/separator.js +1 -1
  204. package/dist/elements/setting-item.js +1 -1
  205. package/dist/elements/settings-group.js +1 -1
  206. package/dist/elements/skeleton.js +1 -1
  207. package/dist/elements/slots.d.ts +16 -0
  208. package/dist/elements/source.js +1 -1
  209. package/dist/elements/status.js +1 -1
  210. package/dist/elements/switch.js +1 -1
  211. package/dist/elements/tabs.js +1 -1
  212. package/dist/elements/tasks.js +1 -1
  213. package/dist/elements/text-shimmer.js +1 -1
  214. package/dist/elements/thinking-bar.js +1 -1
  215. package/dist/elements/thread.js +1 -1
  216. package/dist/elements/toast.js +1 -1
  217. package/dist/elements/tool.js +1 -1
  218. package/dist/elements/tooltip.js +1 -1
  219. package/dist/elements/validate-messages.d.ts +25 -0
  220. package/dist/elements/voice-input.js +1 -1
  221. package/dist/elements/voice-output.js +1 -1
  222. package/dist/elements.d.ts +2725 -214
  223. package/dist/index.d.ts +163 -125
  224. package/dist/index.js +6336 -5802
  225. package/dist/index.server.d.ts +5 -0
  226. package/dist/index.server.js +16913 -0
  227. package/dist/kai-provider.es.d.ts +5 -0
  228. package/dist/kai-provider.es.js +79 -77
  229. package/dist/kai.es.d.ts +5 -0
  230. package/dist/kai.es.js +1 -1
  231. package/dist/llms/llms-full.txt +762 -148
  232. package/dist/llms/llms.txt +57 -5
  233. package/dist/mcp.es.js +4010 -770
  234. package/dist/primitives/card-component-types.d.ts +11 -0
  235. package/dist/primitives/card-data-types.d.ts +196 -0
  236. package/dist/primitives/card-host.d.ts +1 -1
  237. package/dist/primitives/card-recovery.d.ts +3 -3
  238. package/dist/primitives/card-registry.d.ts +4 -14
  239. package/dist/primitives/card-resolution.d.ts +1 -1
  240. package/dist/primitives/card-routing.d.ts +1 -1
  241. package/dist/primitives/card-tags.d.ts +11 -0
  242. package/dist/primitives/card-validate-cards.d.ts +57 -0
  243. package/dist/primitives/card-validate-generator.testlib.d.ts +20 -0
  244. package/dist/primitives/card-validate-schemas.d.ts +17 -0
  245. package/dist/primitives/card-validate.d.ts +24 -0
  246. package/dist/primitives/create-kai-chat.d.ts +3 -3
  247. package/dist/primitives/embed-providers.d.ts +1 -1
  248. package/dist/primitives/link-preview.d.ts +1 -1
  249. package/dist/primitives/message-feedback.d.ts +2 -2
  250. package/dist/primitives/toast-store.d.ts +1 -1
  251. package/dist/react/index.d.ts +717 -299
  252. package/dist/react/use-kai-chat.d.ts +8 -4
  253. package/dist/react.d.ts +5 -0
  254. package/dist/react.js +417 -316
  255. package/dist/register-impl-bzrZ44ft.js +145 -0
  256. package/dist/remote/host-embed.d.ts +1 -1
  257. package/dist/remote/index.d.ts +2 -2
  258. package/dist/remote/provider-runtime.d.ts +2 -2
  259. package/dist/remote/provider.d.ts +2 -2
  260. package/dist/remote/validate.d.ts +1 -1
  261. package/dist/remote/wire.d.ts +1 -1
  262. package/dist/schemas/artifact.schema.json +92 -0
  263. package/dist/schemas/embed.schema.json +0 -2
  264. package/dist/schemas/from-tool-call.d.ts +48 -0
  265. package/dist/schemas/index.d.ts +48 -0
  266. package/dist/schemas/link.schema.json +0 -2
  267. package/dist/schemas/provider-subsets.d.ts +136 -0
  268. package/dist/schemas/registry.d.ts +140 -0
  269. package/dist/schemas/tool-defs.d.ts +121 -0
  270. package/dist/schemas.d.ts +5 -0
  271. package/dist/schemas.js +717 -0
  272. package/dist/solid-BCJUQqwS.js +22750 -0
  273. package/dist/solid-BdENBcEq.js +20108 -0
  274. package/dist/solid.d.ts +66 -0
  275. package/dist/solid.js +261 -0
  276. package/dist/solid.server.d.ts +5 -0
  277. package/dist/solid.server.js +261 -0
  278. package/dist/state/index.d.ts +14 -4
  279. package/dist/state/messages.d.ts +8 -3
  280. package/dist/state/mock.d.ts +46 -0
  281. package/dist/state/parts.d.ts +85 -0
  282. package/dist/state/stream.d.ts +15 -9
  283. package/dist/state.d.ts +5 -0
  284. package/dist/state.js +253 -84
  285. package/dist/ui/action-icons.d.ts +1 -1
  286. package/dist/ui/collapsible.d.ts +11 -6
  287. package/dist/ui/dropdown.d.ts +47 -42
  288. package/dist/ui/pane-group.d.ts +1 -1
  289. package/dist/variant-aurora-1wMcXRUS.js +381 -0
  290. package/dist/variant-aurora-BKHHiOgL.js +391 -0
  291. package/dist/{variant-aurora-DVtGqVH6.js → variant-aurora-DOb_o4pC.js} +1 -1
  292. package/dist/{variant-custom-Dif-IV4u.js → variant-custom-CJGB0Kbw.js} +1 -1
  293. package/dist/variant-custom-Co0CkXJF.js +200 -0
  294. package/dist/variant-custom-DWSSgmd2.js +170 -0
  295. package/dist/variant-wave-C3-45cL6.js +218 -0
  296. package/dist/{variant-wave-DbfNdvSi.js → variant-wave-CEODq-9q.js} +1 -1
  297. package/dist/variant-wave-jdXBnCUZ.js +208 -0
  298. package/dist/wire/chunk.d.ts +171 -0
  299. package/dist/wire/consume.d.ts +26 -0
  300. package/dist/wire/encode.d.ts +148 -0
  301. package/dist/wire/formats/anthropic.d.ts +2 -0
  302. package/dist/wire/formats/openai.d.ts +5 -0
  303. package/dist/wire/index.d.ts +14 -0
  304. package/dist/wire/read.d.ts +26 -0
  305. package/dist/wire/sink-helpers.d.ts +21 -0
  306. package/dist/wire/sse.d.ts +33 -0
  307. package/dist/wire.d.ts +5 -53
  308. package/dist/wire.js +898 -0
  309. package/frameworks/react/index.tsx +183 -154
  310. package/frameworks/react/runtime.tsx +21 -1
  311. package/frameworks/react/use-kai-chat.tsx +11 -1
  312. package/llms-full.txt +762 -148
  313. package/llms.txt +57 -5
  314. package/package.json +65 -7
  315. package/src/agent-tooling/archetypes.ts +96 -0
  316. package/src/agent-tooling/integrations/anthropic.ts +412 -0
  317. package/src/agent-tooling/integrations/cloudflare.ts +136 -52
  318. package/src/agent-tooling/integrations/langgraph.ts +67 -13
  319. package/src/agent-tooling/integrations/mastra.ts +120 -12
  320. package/src/agent-tooling/integrations/mock.ts +43 -8
  321. package/src/agent-tooling/integrations/ollama.ts +61 -24
  322. package/src/agent-tooling/integrations/openai.ts +87 -0
  323. package/src/agent-tooling/integrations/openrouter.ts +56 -8
  324. package/src/agent-tooling/integrations/pi.ts +79 -23
  325. package/src/agent-tooling/integrations/pydantic-ai.ts +24 -2
  326. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +84 -13
  327. package/src/agent-tooling/mcp/manifest.ts +206 -25
  328. package/src/agent-tooling/mcp/tools/debug.ts +13 -7
  329. package/src/agent-tooling/mcp/tools/reference.ts +285 -6
  330. package/src/agent-tooling/mcp/tools/scaffold.ts +3345 -675
  331. package/src/agent-tooling/registry.ts +17 -0
  332. package/src/agent-tooling/types.ts +229 -1
  333. package/src/components/artifact-card.tsx +120 -0
  334. package/src/components/audio-visualizer/index.tsx +9 -0
  335. package/src/components/audio-visualizer/labs/lab-choreography.ts +187 -0
  336. package/src/components/audio-visualizer/labs/lab-shaders.ts +363 -0
  337. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +102 -0
  338. package/src/components/audio-visualizer/shader-canvas.tsx +31 -1
  339. package/src/components/card-fallback.tsx +42 -10
  340. package/src/components/card-renderer.tsx +146 -9
  341. package/src/components/chat-container.tsx +4 -0
  342. package/src/components/chat-thread.tsx +118 -51
  343. package/src/components/choice-card.tsx +17 -29
  344. package/src/components/composer.tsx +12 -2
  345. package/src/components/confirm-card.tsx +24 -20
  346. package/src/components/context.tsx +12 -4
  347. package/src/components/conversation-list.tsx +18 -2
  348. package/src/components/file-tree.tsx +11 -22
  349. package/src/components/file-upload.tsx +14 -8
  350. package/src/components/form.tsx +14 -47
  351. package/src/components/loader.tsx +39 -12
  352. package/src/components/message-skills.tsx +4 -0
  353. package/src/components/message.tsx +294 -46
  354. package/src/components/reasoning.tsx +92 -5
  355. package/src/components/response-compare-types.ts +25 -0
  356. package/src/components/response-compare.tsx +4 -9
  357. package/src/components/source.tsx +50 -24
  358. package/src/components/tasks-card.tsx +10 -33
  359. package/src/components/thread.tsx +84 -42
  360. package/src/components/toast.tsx +11 -5
  361. package/src/components/tool-classify.ts +26 -0
  362. package/src/components/tool-types.ts +31 -1
  363. package/src/elements/agent-card.tsx +11 -11
  364. package/src/elements/artifact.tsx +15 -7
  365. package/src/elements/attachments.tsx +6 -4
  366. package/src/elements/avatar.tsx +1 -1
  367. package/src/elements/button.tsx +3 -3
  368. package/src/elements/card.tsx +2 -2
  369. package/src/elements/cards.tsx +109 -14
  370. package/src/elements/chain-of-thought.tsx +14 -10
  371. package/src/elements/chat-scope-picker.tsx +9 -7
  372. package/src/elements/chat-types.ts +59 -6
  373. package/src/elements/chat-workspace.tsx +50 -9
  374. package/src/elements/chat.tsx +64 -3
  375. package/src/elements/choice.tsx +8 -8
  376. package/src/elements/coachmark.tsx +1 -1
  377. package/src/elements/command.tsx +8 -23
  378. package/src/elements/compare.tsx +7 -6
  379. package/src/elements/compiled.css +1 -1
  380. package/src/elements/composer.tsx +8 -8
  381. package/src/elements/confirm-card.tsx +9 -9
  382. package/src/elements/context-meter.tsx +4 -18
  383. package/src/elements/conversation-list.tsx +14 -9
  384. package/src/elements/default-input.tsx +3 -3
  385. package/src/elements/define.tsx +178 -43
  386. package/src/elements/editable-label.tsx +17 -2
  387. package/src/elements/element-data-types.ts +112 -0
  388. package/src/elements/element-meta.json +1596 -304
  389. package/src/elements/element-types.d.ts +2636 -211
  390. package/src/elements/feedback-bar.tsx +1 -1
  391. package/src/elements/file-tree.tsx +1 -1
  392. package/src/elements/file-upload.tsx +1 -1
  393. package/src/elements/form.tsx +14 -6
  394. package/src/elements/input.tsx +1 -1
  395. package/src/elements/kbd.tsx +1 -1
  396. package/src/elements/menu.tsx +10 -29
  397. package/src/elements/message-skills.tsx +7 -9
  398. package/src/elements/message.tsx +200 -32
  399. package/src/elements/model-switcher.tsx +5 -3
  400. package/src/elements/pane.tsx +1 -1
  401. package/src/elements/prompt-dock.tsx +8 -8
  402. package/src/elements/prompt-input.tsx +10 -10
  403. package/src/elements/prompt-suggestions.tsx +7 -4
  404. package/src/elements/reasoning.tsx +1 -1
  405. package/src/elements/register.ts +9 -0
  406. package/src/elements/resizable.globals.d.ts +36 -0
  407. package/src/elements/resizable.tsx +24 -13
  408. package/src/elements/response-stream.tsx +1 -1
  409. package/src/elements/scroll-button.tsx +1 -1
  410. package/src/elements/search.tsx +6 -1
  411. package/src/elements/segmented.tsx +5 -11
  412. package/src/elements/separator.tsx +1 -1
  413. package/src/elements/slots.ts +57 -24
  414. package/src/elements/source.tsx +21 -22
  415. package/src/elements/switch.tsx +3 -3
  416. package/src/elements/tasks.tsx +5 -4
  417. package/src/elements/thread.tsx +36 -4
  418. package/src/elements/toast.tsx +3 -2
  419. package/src/elements/tool.tsx +1 -1
  420. package/src/elements/validate-messages.ts +76 -0
  421. package/src/elements/voice-input.tsx +7 -7
  422. package/src/elements/voice-output.tsx +4 -4
  423. package/src/index.ts +141 -6
  424. package/src/primitives/card-component-types.ts +63 -0
  425. package/src/primitives/card-data-types.ts +312 -0
  426. package/src/primitives/card-recovery.ts +13 -2
  427. package/src/primitives/card-registry.tsx +34 -23
  428. package/src/primitives/card-schemas/artifact.schema.json +92 -0
  429. package/src/primitives/card-schemas/embed.schema.json +0 -2
  430. package/src/primitives/card-schemas/link.schema.json +0 -2
  431. package/src/primitives/card-tags.ts +61 -0
  432. package/src/primitives/card-validate-cards.ts +255 -0
  433. package/src/primitives/card-validate-generator.testlib.ts +38 -0
  434. package/src/primitives/card-validate-schemas.ts +58 -0
  435. package/src/primitives/card-validate.ts +48 -20
  436. package/src/primitives/create-tween.ts +54 -2
  437. package/src/primitives/message-feedback.ts +3 -2
  438. package/src/primitives/use-audio-analysis.ts +20 -1
  439. package/src/primitives/use-sequencer.ts +20 -1
  440. package/src/schemas/from-tool-call.ts +151 -0
  441. package/src/schemas/index.ts +340 -0
  442. package/src/schemas/provider-subsets.ts +538 -0
  443. package/src/schemas/registry.ts +355 -0
  444. package/src/schemas/tool-defs.ts +492 -0
  445. package/src/solid.ts +150 -0
  446. package/src/state/index.ts +27 -1
  447. package/src/state/messages.ts +21 -4
  448. package/src/state/mock.ts +211 -0
  449. package/src/state/parts.ts +295 -0
  450. package/src/state/stream.ts +56 -58
  451. package/src/ui/collapsible.tsx +17 -5
  452. package/src/ui/dropdown.tsx +46 -12
  453. package/src/ui/overlay.tsx +10 -4
  454. package/src/wire/chunk.ts +201 -0
  455. package/src/wire/consume.ts +440 -0
  456. package/src/wire/encode.ts +474 -0
  457. package/src/wire/formats/anthropic.ts +267 -0
  458. package/src/wire/formats/openai.ts +187 -0
  459. package/src/wire/index.ts +52 -0
  460. package/src/wire/read.ts +152 -0
  461. package/src/wire/sink-helpers.ts +50 -0
  462. package/src/wire/sse.ts +140 -0
  463. package/dist/create-tween-hvpmSuwW.js +0 -7
  464. package/dist/elements/chunks/arrow-left-DQocUFvy.js +0 -1
  465. package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +0 -1
  466. package/dist/elements/chunks/card-BkHbp4BA.js +0 -1
  467. package/dist/elements/chunks/chat-thread-CkRN6pZ7.js +0 -1
  468. package/dist/elements/chunks/check-B9-gn6SS.js +0 -1
  469. package/dist/elements/chunks/chevron-down-BNsxc2hk.js +0 -1
  470. package/dist/elements/chunks/chevron-right-Hv00StBO.js +0 -1
  471. package/dist/elements/chunks/circle-0e3KJTDr.js +0 -1
  472. package/dist/elements/chunks/circle-check-BNAS0JEy.js +0 -1
  473. package/dist/elements/chunks/code-block-BFUHn6Va.js +0 -1
  474. package/dist/elements/chunks/context-Cb7k4F-v.js +0 -1
  475. package/dist/elements/chunks/conversation-list-CvoAkWhN.js +0 -1
  476. package/dist/elements/chunks/create-tween-oVvAIG8r.js +0 -7
  477. package/dist/elements/chunks/define-D1din7Ld.js +0 -1
  478. package/dist/elements/chunks/hover-card-Cmm6Q53m.js +0 -1
  479. package/dist/elements/chunks/message-BqyXDN3-.js +0 -1
  480. package/dist/elements/chunks/message-feedback-Djr3z6Yb.js +0 -1
  481. package/dist/elements/chunks/message-square-vFAgbDaX.js +0 -1
  482. package/dist/elements/chunks/reasoning-DTpCGtnY.js +0 -1
  483. package/dist/elements/chunks/scroll-button-B0cH5fXf.js +0 -1
  484. package/dist/elements/chunks/skeleton-DSXW5Yya.js +0 -1
  485. package/dist/elements/chunks/slots--V19HwUb.js +0 -1
  486. package/dist/elements/chunks/textarea-CUwqAX0G.js +0 -1
  487. package/dist/elements/chunks/tooltip-CgBZCVKp.js +0 -1
  488. package/dist/elements/chunks/use-card-resolution-BSu_XHjH.js +0 -1
  489. package/dist/elements/chunks/x-GRUeeQFT.js +0 -1
  490. package/dist/host-embed.d.ts +0 -33
  491. package/dist/kai-provider.d.ts +0 -2
  492. package/dist/origin.d.ts +0 -5
  493. package/dist/provider-runtime.d.ts +0 -27
  494. package/dist/register-impl-DQyejdfb.js +0 -145
  495. package/dist/validate.d.ts +0 -4
  496. package/dist/version.d.ts +0 -4
  497. package/src/components/component-meta.json +0 -4550
  498. package/src/elements/card-media.jpg +0 -0
  499. package/src/elements/resizable.d.ts +0 -27
  500. package/src/elements/video-poster.jpg +0 -0
@@ -10,20 +10,26 @@
10
10
  import { createWebComponent, registerAll, type WebComponentProps } from './runtime';
11
11
  export { registerAll };
12
12
  export { useKaiChat } from './use-kai-chat';
13
- export type { UseKaiChatOptions, KaiChatController, ChatMessage } from './use-kai-chat';
13
+ export type { UseKaiChatOptions, KaiChatController } from './use-kai-chat';
14
+ // The content-model types, re-exported so a consumer can annotate a `parts`
15
+ // array or an `addSource` argument without reaching into the main entry.
16
+ export type {
17
+ ChatMessage, ChatMessageAction, CustomAction, AvatarData, FeedbackVote, MessagePart,
18
+ MessageSource, RawOrigin, ToolPart, ToolKind, CardEnvelope, AttachmentData,
19
+ } from './use-kai-chat';
14
20
  export { useVoiceInput } from './use-voice-input';
15
21
 
16
22
 
17
23
  export interface AgentCardProps extends WebComponentProps {
18
- /** The agent's name the primary label. Attribute: `name`. */
24
+ /** The agent's name, the primary label. Attribute: `name`. */
19
25
  name?: string;
20
26
  /** Selected / focused state: highlighted border + surface. Attribute: `active`. */
21
27
  active?: boolean;
22
- /** Raise a prominent "Needs you" pill plus a glowing amber edge the attention-routing signal that pulls focus to this agent. Attribute: `needs-attention`. */
28
+ /** Raise a prominent "Needs you" pill plus a glowing amber edge. This is the attention-routing signal that pulls focus to this agent. Attribute: `needs-attention`. */
23
29
  needsAttention?: boolean;
24
- /** Run status a JS PROPERTY (object), not an attribute. Shape: `{ tone, label?, pulse? }`, where `tone` is one of `working` | `idle` | `done` | `error` | `blocked` (maps to the kit's tool hues), `label` is an optional short string beside the dot, and `pulse` animates the dot. Set it with `el.status = { tone: 'working', label: 'Working', pulse: true }`. */
30
+ /** Run status. A JS PROPERTY (object), not an attribute. Shape: `{ tone, label?, pulse? }`, where `tone` is one of `working` | `idle` | `done` | `error` | `blocked` (maps to the kit's tool hues), `label` is an optional short string beside the dot, and `pulse` animates the dot. Set it with `el.status = { tone: 'working', label: 'Working', pulse: true }`. */
25
31
  status?: { tone: "working" | "idle" | "done" | "error" | "blocked"; label?: string; pulse?: boolean };
26
- /** The card was activated clicked, or Enter / Space while focused. Promote this agent back to focus. */
32
+ /** The card was activated by a click, or by Enter / Space while focused. Promote this agent back to focus. */
27
33
  onActivate?: (event: CustomEvent) => void;
28
34
  /** The trailing "..." kebab was clicked. The consumer opens its own menu; the card only surfaces the affordance (the click does not also activate the card). */
29
35
  onMenu?: (event: CustomEvent) => void;
@@ -39,13 +45,13 @@ export const AgentCard = /*#__PURE__*/ createWebComponent<AgentCardProps>(
39
45
  export interface ArtifactProps extends WebComponentProps {
40
46
  /** URL the preview iframe frames. Consumer-controlled. */
41
47
  src?: string;
42
- /** Files for the Code tab tree + each file's preview `url`. Set as a JS property (array). */
43
- files: { path: string; url?: undefined | string; code?: undefined | string; language?: undefined | string; type?: undefined | "html" | "pdf" | "image" | "other"; additions?: undefined | number; deletions?: undefined | number; status?: undefined | "added" | "modified" | "deleted" | "renamed" | "untracked" }[];
48
+ /** Files for the Code tab tree + each file's preview `url`. Omit for a preview-only artifact (the Code tab then has nothing to show; pair it with `no-tabs` to hide the toggle). Set as a JS property (array). */
49
+ files?: { path: string; url?: string; code?: string; language?: string; type?: "html" | "pdf" | "image" | "other"; additions?: number; deletions?: number; status?: "added" | "modified" | "deleted" | "renamed" | "untracked" }[];
44
50
  /** Controlled active tab: `preview` or `code`. When set, the artifact follows it (re-asserted on change). Leave unset for an uncontrolled tab (see `defaultTab`). */
45
51
  tab?: "preview" | "code";
46
52
  /** Uncontrolled INITIAL tab (used only when `tab` is unset). Default `preview`. Seeds the starting tab; the user can then switch freely without the consumer re-asserting a controlled `tab`. */
47
53
  defaultTab?: "preview" | "code";
48
- /** Selected file path syncs the tree highlight, Code source, and preview. */
54
+ /** Selected file path. Syncs the tree highlight, Code source, and preview. */
49
55
  activeFile?: string;
50
56
  /** iframe `sandbox` override. Secure default `allow-scripts allow-forms` (NOT `allow-same-origin`). */
51
57
  sandbox?: string;
@@ -77,6 +83,8 @@ export interface ArtifactProps extends WebComponentProps {
77
83
  onFileSelect?: (event: CustomEvent<{ path: string }>) => void;
78
84
  /** Artifact's own maximize button toggled (consumer-observable; non-bubbling). */
79
85
  onMaximizeChange?: (event: CustomEvent<{ maximized: boolean }>) => void;
86
+ /** The maximize PROTOCOL intent, raised as a raw bubbling + composed CustomEvent (not through `dispatch`) so an enclosing `<kai-resizable>` can catch it and maximize the containing panel. Declared here so it is typed and reaches the generated API. Listen for it to drive maximize from your own chrome, or re-emit it to trigger one. */
87
+ onMaximizeIntent?: (event: CustomEvent<{ requested: boolean }>) => void;
80
88
  /** Fired when the preview navigates. `detail.url` = the new location. */
81
89
  onNavigate?: (event: CustomEvent<{ url: string }>) => void;
82
90
  /** Fired when the Preview|Code tab changes. `detail.tab`. */
@@ -86,13 +94,13 @@ export interface ArtifactProps extends WebComponentProps {
86
94
  export const Artifact = /*#__PURE__*/ createWebComponent<ArtifactProps>(
87
95
  'kai-artifact',
88
96
  ["theme","src","files","tab","defaultTab","activeFile","sandbox","iframeTitle","maximized","expandable","openInTab","noNav","noReload","noHome","noPathField","noTabs","standalone","readonlyPath","displayUrl"],
89
- { onFileSelect: 'kai-file-select', onMaximizeChange: 'kai-maximize-change', onNavigate: 'kai-navigate', onTabChange: 'kai-tab-change' },
97
+ { onFileSelect: 'kai-file-select', onMaximizeChange: 'kai-maximize-change', onMaximizeIntent: 'kai-maximize-intent', onNavigate: 'kai-navigate', onTabChange: 'kai-tab-change' },
90
98
  () => import('@kitn.ai/ui/elements/artifact'),
91
99
  );
92
100
 
93
101
  export interface AttachmentsProps extends WebComponentProps {
94
- /** The attachments to render. Set as a JS property (array). */
95
- items: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[];
102
+ /** The attachments to render. Omit (or pass an empty array) for the empty state, which shows `emptyText` if set and nothing otherwise. Set as a JS property (array). */
103
+ items?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[];
96
104
  /** Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. */
97
105
  variant?: "grid" | "inline" | "list";
98
106
  /** Wrap each item in a hover card that previews its details. */
@@ -161,7 +169,7 @@ export interface AvatarProps extends WebComponentProps {
161
169
  src?: string;
162
170
  /** Alt text for the image. Defaults to `fallback`. */
163
171
  alt?: string;
164
- /** Short text shown when there's no image usually initials (e.g. "JD", "AI"). */
172
+ /** Short text shown when there's no image, usually initials (e.g. "JD", "AI"). */
165
173
  fallback?: string;
166
174
  /** Size token: `sm` | `md` (default) | `lg`. */
167
175
  size?: "sm" | "md" | "lg";
@@ -187,7 +195,7 @@ export const Badge = /*#__PURE__*/ createWebComponent<BadgeProps>(
187
195
  );
188
196
 
189
197
  export interface ButtonProps extends WebComponentProps {
190
- /** Visual style. `default` (filled), `subtle` (muted text, hover tint the toolbar icon look), `ghost` (transparent, hover fill), `outline`, or `destructive`. Defaults to `default`. */
198
+ /** Visual style. `default` (filled), `subtle` (muted text, hover tint, the toolbar icon look), `ghost` (transparent, hover fill), `outline`, or `destructive`. Defaults to `default`. */
191
199
  variant?: "default" | "subtle" | "ghost" | "outline" | "destructive";
192
200
  /** Size token. `icon` / `icon-sm` are square (for icon-only buttons); `sm` / `md` / `lg` size text buttons. Defaults to `md`. */
193
201
  size?: "sm" | "md" | "lg" | "icon" | "icon-sm";
@@ -199,7 +207,7 @@ export interface ButtonProps extends WebComponentProps {
199
207
  label?: string;
200
208
  /** Disable the button (non-interactive, dimmed). */
201
209
  disabled?: boolean;
202
- /** Stretch the button to the full width of its container (a block button) e.g. a card CTA or a stacked action. Attribute: `full`. */
210
+ /** Stretch the button to the full width of its container (a block button), e.g. a card CTA or a stacked action. Attribute: `full`. */
203
211
  full?: boolean;
204
212
  /** Justify the button's content: `start`, `center` (default), or `end`. Combine with `full` for a full-width, left-aligned button. */
205
213
  align?: "start" | "center" | "end";
@@ -219,7 +227,7 @@ export const Button = /*#__PURE__*/ createWebComponent<ButtonProps>(
219
227
  export interface CardProps extends WebComponentProps {
220
228
  /** Surface treatment: `outlined` (default) | `filled` | `plain` | `accent`. Attribute: `appearance`. */
221
229
  appearance?: "outlined" | "filled" | "plain" | "accent";
222
- /** `vertical` (default, media on top) | `horizontal` (media at the start) | `responsive` (horizontal when the card's container is wide enough, else vertical a container query on the card's own width). Attribute: `orientation`. */
230
+ /** `vertical` (default, media on top) | `horizontal` (media at the start) | `responsive` (horizontal when the card's container is wide enough, else vertical, via a container query on the card's own width). Attribute: `orientation`. */
223
231
  orientation?: "vertical" | "horizontal" | "responsive";
224
232
  /** The card width below which a `responsive` card collapses to vertical and the footer actions stack. A CSS length; default `28rem`. Attribute: `collapse`. */
225
233
  collapse?: string;
@@ -253,29 +261,33 @@ export interface CardsProps extends WebComponentProps {
253
261
  cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }[];
254
262
  /** Optional type→tag overrides/additions (merged over the built-ins). Property: `el.types`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
255
263
  types?: Record<string, string>;
264
+ /** JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `types`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.schemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name, matching `mergeCardTags`, where your entry is spread over ours. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `"type"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one. See `CardSchemaMap` in components/card-renderer.tsx. */
265
+ schemas?: Record<string, object>;
256
266
  /** Optional CardPolicy handling child events. Property: `el.policy`. */
257
267
  policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onReopen?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
258
- /** A child card transitioned to a resolved/deferred state (an action was chosen, a form/tasks submission landed, or it was dismissed) re-emitted off the host as a non-bubbling convenience event so a consumer can observe resolution centrally without diffing the cards array. `detail` = `{ cardId, resolution }`. (A `reopen` un-resolves a card and has no `CardResolution`, so it does NOT fire this observe reopen via the underlying bubbling `kai-card` event.) */
268
+ /** Validate each envelope's `data` against the schema for its type before rendering it, using a built-in's own schema or yours from `schemas`. Default `true`; set `validate-cards="false"` (or `el.validateCards = false`) to opt out. A hard failure (wrong type, a missing required field) renders a diagnostic naming the field instead of the card; a soft failure (bounds) renders the card unchanged. Both emit a contract `error` event. On in production too: a model emitting a bad shape is a production failure mode, so stripping the check there would hide it from exactly the person who needs to see it. */
269
+ validateCards?: boolean;
270
+ /** A child card transitioned to a resolved/deferred state (an action was chosen, a form/tasks submission landed, or it was dismissed). Re-emitted off the host as a non-bubbling convenience event so a consumer can observe resolution centrally without diffing the cards array. `detail` = `{ cardId, resolution }`. (A `reopen` un-resolves a card and has no `CardResolution`, so it does NOT fire this; observe reopen via the underlying bubbling `kai-card` event.) */
259
271
  onCardResolved?: (event: CustomEvent<{ cardId: string; resolution: { kind: "action"; action: string; payload?: unknown; at?: undefined | string } | { kind: "submit"; data: unknown; at?: undefined | string } | { kind: "dismissed"; at?: undefined | string } | { kind: "expired"; reason?: undefined | string; at?: undefined | string } }>) => void;
260
272
  }
261
273
 
262
274
  export const Cards = /*#__PURE__*/ createWebComponent<CardsProps>(
263
275
  'kai-cards',
264
- ["theme","cards","types","policy"],
276
+ ["theme","cards","types","schemas","policy","validateCards"],
265
277
  { onCardResolved: 'kai-card-resolved' },
266
278
  () => import('@kitn.ai/ui/elements/cards'),
267
279
  );
268
280
 
269
281
  export interface ChainOfThoughtProps extends WebComponentProps {
270
- /** The reasoning steps. Set as a JS property. Compound sub-parts collapse to this one data model (Route 1). Each `{ label, content?, id? }`. */
271
- steps: { label: string; content?: undefined | string; id?: undefined | string }[];
272
- /** Open mode: `'multiple'` (default any number of steps open at once) or `'single'` (at most one open; opening a step closes the others). */
282
+ /** The reasoning steps. Set as a JS property. Compound sub-parts collapse to this one data model (Route 1). Each `{ label, content?, id? }`. Omit to supply the steps as `<kai-step>` light-DOM children instead; when both are present the property's steps come first. */
283
+ steps?: { label: string; content?: string; id?: string }[];
284
+ /** Open mode: `'multiple'` (default, any number of steps open at once) or `'single'` (at most one open; opening a step closes the others). */
273
285
  type?: "single" | "multiple";
274
286
  /** Controlled open step key(s). When set, it WINS over user interaction (the consumer owns the open set). String in `single` mode, string[] in `multiple` mode. Set as a JS property. */
275
287
  value?: string | string[];
276
- /** Uncontrolled INITIAL open step key(s) seeds which steps render expanded. Ignored once `value` is provided. Set as a JS property. */
288
+ /** Uncontrolled INITIAL open step key(s), seeding which steps render expanded. Ignored once `value` is provided. Set as a JS property. */
277
289
  defaultValue?: string | string[];
278
- /** The open set changed by user click OR an expand()/collapse()/toggle() call. `value` is a string in `single` mode, a string[] in `multiple` mode. (Maps Radix Accordion's onValueChange.) */
290
+ /** The open set changed, by user click OR an expand()/collapse()/toggle() call. `value` is a string in `single` mode, a string[] in `multiple` mode. (Maps Radix Accordion's onValueChange.) */
279
291
  onValueChange?: (event: CustomEvent<{ value: string | string[] }>) => void;
280
292
  }
281
293
 
@@ -287,8 +299,8 @@ export const ChainOfThought = /*#__PURE__*/ createWebComponent<ChainOfThoughtPro
287
299
  );
288
300
 
289
301
  export interface ChatProps extends WebComponentProps {
290
- /** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). */
291
- messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
302
+ /** Show a Search (Globe) button in the input toolbar; fires a `search` event. */
303
+ search?: boolean;
292
304
  /** Value of the input. A **string** is controlled (the host owns the text and updates it on `kai-value-change`). A **ComposerDoc** is a one-time seed that pre-populates pills; the user then edits freely. Leave unset for uncontrolled. */
293
305
  value?: string | ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: string; promptText?: string; data?: Record<string, unknown> } })[];
294
306
  /** Placeholder text shown in the empty input. */
@@ -302,7 +314,7 @@ export interface ChatProps extends WebComponentProps {
302
314
  /** Keep suggestions visible after the conversation starts. By default suggestions are conversation starters and hide once `messages` is non-empty; set this to keep them always shown. Default false. */
303
315
  persistSuggestions?: boolean;
304
316
  /** Body/prose font scale for rendered markdown (`'xs' | 'sm' | 'base' | 'lg'`). Defaults to `'sm'`. */
305
- proseSize?: "sm" | "lg" | "xs" | "base";
317
+ proseSize?: "xs" | "sm" | "base" | "lg";
306
318
  /** Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). */
307
319
  codeTheme?: string;
308
320
  /** Enable Shiki syntax highlighting in code blocks. Turn off to render plain `<pre>` blocks (lighter, no highlighter load). Default true. */
@@ -317,32 +329,36 @@ export interface ChatProps extends WebComponentProps {
317
329
  context?: { usedTokens: number; maxTokens: number; inputTokens?: number; outputTokens?: number; estimatedCost?: number };
318
330
  /** Show the scroll-to-bottom button inside the scroll area. Default true. */
319
331
  scrollButton?: boolean;
320
- /** Whether the host has `slot="header-start"` content (left of the title) set by the `<kai-chat>` facade so a custom control forces the header open. */
332
+ /** Whether the host has `slot="header-start"` content (left of the title). Set by the `<kai-chat>` facade so a custom control forces the header open. */
321
333
  headerStart?: boolean;
322
334
  /** Whether the host has `slot="header-end"` content (right of the controls). */
323
335
  headerEnd?: boolean;
324
- /** REPLACE full custom header in place of the built-in title/model/context bar. */
336
+ /** REPLACE: full custom header in place of the built-in title/model/context bar. */
325
337
  headerFull?: boolean;
326
- /** INJECT left sidebar column (e.g. a conversation list / your own nav). */
338
+ /** INJECT: left sidebar column (e.g. a conversation list / your own nav). */
327
339
  sidebar?: boolean;
328
- /** REPLACE custom zero-state rendered in the message area while the thread is empty (replaces the empty message list only; the composer and its suggestions still render). */
340
+ /** REPLACE: custom zero-state rendered in the message area while the thread is empty (replaces the empty message list only; the composer and its suggestions still render). */
329
341
  empty?: boolean;
330
- /** REPLACE full custom composer in place of the built-in prompt input. The projected content wires its own submit (the data-flow boundary). */
342
+ /** REPLACE: full custom composer in place of the built-in prompt input. The projected content wires its own submit (the data-flow boundary). */
331
343
  composer?: boolean;
332
- /** INJECT accessory row just above the composer (e.g. extra actions). */
344
+ /** INJECT: accessory row just above the composer (e.g. extra actions). */
333
345
  composerActions?: boolean;
334
- /** INJECT footer row below the composer (disclaimers, token meter, …). */
346
+ /** INJECT: footer row below the composer (disclaimers, token meter, …). */
335
347
  footer?: boolean;
336
- /** Show a Search (Globe) button in the input toolbar; fires a `search` event. */
337
- search?: boolean;
338
348
  /** Show a Voice (Mic) button in the input toolbar; fires a `voice` event. */
339
349
  voice?: boolean;
340
- /** Rich entity triggers each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill (`/` skills, `@` agents/plugins). Set as a JS property; forwarded to the input. */
350
+ /** Rich entity triggers. Each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill (`/` skills, `@` agents/plugins). Set as a JS property; forwarded to the input. */
341
351
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record<string, unknown> }[] }[];
342
352
  /** Default icon per entity kind (kind → image src) for pills/menu items. */
343
353
  kindIcons?: Record<string, string>;
344
354
  /** Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). */
345
355
  actionsReveal?: "always" | "hover";
356
+ /** The full message thread to render, newest last. Each entry carries its role, ordered `parts`, and optional actions/avatar/feedback. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). Omit for an empty thread. Re-declared here (rather than inherited from `ChatThreadProps`) because the ELEMENT registers a `[]` default and renders the empty state without it, while the SolidJS `<ChatThread>` component still requires it. The facade hands it a validated array either way. Matches `<kai-thread>`. */
357
+ messages?: { id: string; role: "user" | "assistant"; parts: ({ type: "text"; text: string; raw?: { source: string; payload: unknown } } | { type: "reasoning"; text: string; label?: string; index?: number; streamId?: string; signature?: string; raw?: { source: string; payload: unknown } } | { type: "tool"; tool: { type: string; kind?: "command" | "file-change" | "search" | "fetch" | "mcp" | "image" | "generic"; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; rawInput?: string; output?: Record<string, unknown>; toolCallId?: string; errorText?: string; raw?: { source: string; payload: unknown } }; raw?: { source: string; payload: unknown } } | { type: "card"; envelope: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }; raw?: { source: string; payload: unknown } } | { type: "source"; source: { id?: string; url?: string; title?: string; snippet?: string; index?: number }; raw?: { source: string; payload: unknown } } | { type: "file"; attachment: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }; raw?: { source: string; payload: unknown } })[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" }[];
358
+ /** Optional card type -> custom-element tag overrides/additions for `card` parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
359
+ cardTypes?: Record<string, string>;
360
+ /** JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `"type"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one. */
361
+ cardSchemas?: Record<string, object>;
346
362
  /** The staged attachments changed (file added or removed). Carries the full current list so a consumer can react in real time. */
347
363
  onAttachmentsChange?: (event: CustomEvent<{ attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
348
364
  /** An action button on a message was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
@@ -363,7 +379,7 @@ export interface ChatProps extends WebComponentProps {
363
379
 
364
380
  export const Chat = /*#__PURE__*/ createWebComponent<ChatProps>(
365
381
  'kai-chat',
366
- ["theme","messages","value","placeholder","loading","suggestions","suggestionMode","persistSuggestions","proseSize","codeTheme","codeHighlight","chatTitle","models","currentModel","context","scrollButton","headerStart","headerEnd","headerFull","sidebar","empty","composer","composerActions","footer","search","voice","triggers","kindIcons","actionsReveal"],
382
+ ["theme","search","value","placeholder","loading","suggestions","suggestionMode","persistSuggestions","proseSize","codeTheme","codeHighlight","chatTitle","models","currentModel","context","scrollButton","headerStart","headerEnd","headerFull","sidebar","empty","composer","composerActions","footer","voice","triggers","kindIcons","actionsReveal","messages","cardTypes","cardSchemas"],
367
383
  { onAttachmentsChange: 'kai-attachments-change', onMessageAction: 'kai-message-action', onModelChange: 'kai-model-change', onSearch: 'kai-search', onSubmit: 'kai-submit', onSuggestionClick: 'kai-suggestion-click', onValueChange: 'kai-value-change', onVoice: 'kai-voice' },
368
384
  () => import('@kitn.ai/ui/elements/chat'),
369
385
  );
@@ -374,7 +390,7 @@ export interface CheckpointProps extends WebComponentProps {
374
390
  /** Tooltip on hover. */
375
391
  tooltip?: string;
376
392
  /** Visual button style. */
377
- variant?: "default" | "ghost" | "outline";
393
+ variant?: "ghost" | "default" | "outline";
378
394
  /** Button size (use an `icon*` size for an icon-only checkpoint). */
379
395
  size?: "sm" | "md" | "lg" | "icon" | "icon-sm";
380
396
  /** The checkpoint was clicked. */
@@ -390,14 +406,14 @@ export const Checkpoint = /*#__PURE__*/ createWebComponent<CheckpointProps>(
390
406
 
391
407
  export interface ChoiceProps extends WebComponentProps {
392
408
  /** The choice definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { prompt, options:[…], allowOther?, submitLabel? }`. Import `ChoiceCardData` from `@kitn.ai/ui` for the full shape. */
393
- data?: Record<string, unknown>;
409
+ data?: { prompt?: string; options: { id: string; label: string; description?: string; media?: { image?: string; imageAlt?: string; icon?: string }; meta?: string; recommended?: boolean; disabled?: boolean; payload?: unknown }[]; allowOther?: boolean | { label?: string; placeholder?: string }; submitLabel?: string; dismissible?: boolean };
394
410
  /** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
395
411
  cardId?: string;
396
412
  /** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
397
413
  heading?: string;
398
414
  /** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'action', action:'…' }`. */
399
415
  resolution?: Record<string, unknown>;
400
- /** Controlled selection the selected option id. When set, the consumer owns the current pick (RadioGroup `value`). Attribute: `value`. */
416
+ /** Controlled selection: the selected option id. When set, the consumer owns the current pick (RadioGroup `value`). Attribute: `value`. */
401
417
  value?: string;
402
418
  /** Option id to pre-select on mount (uncontrolled seed). Attribute: `default-value`. */
403
419
  defaultValue?: string;
@@ -425,8 +441,8 @@ export interface CoachmarkProps extends WebComponentProps {
425
441
  badge?: string;
426
442
  /** Floating placement relative to the anchor (default `bottom`). */
427
443
  placement?: string;
428
- /** Color tone: `primary` (default, theme accent), `info` (blue), `success` (green), `warning` (amber), or `error` (red) reusing the kit's tool hues. */
429
- tone?: "error" | "primary" | "info" | "success" | "warning";
444
+ /** Color tone: `primary` (default, theme accent), `info` (blue), `success` (green), `warning` (amber), or `error` (red), reusing the kit's tool hues. */
445
+ tone?: "primary" | "info" | "success" | "warning" | "error";
430
446
  /** Render the arrow that points at the anchor (default `true`). Set `arrow="false"` for a plain bubble with no pointer. */
431
447
  arrow?: boolean;
432
448
  /** The × dismiss button was pressed. The consumer records that this hint was seen so it won't show again. */
@@ -452,7 +468,7 @@ export interface CodeBlockProps extends WebComponentProps {
452
468
  /** Disable syntax highlighting (renders plain text, no Shiki). */
453
469
  codeHighlight?: boolean;
454
470
  /** Code text sizing. */
455
- proseSize?: "sm" | "lg" | "xs" | "base";
471
+ proseSize?: "xs" | "sm" | "base" | "lg";
456
472
  }
457
473
 
458
474
  export const CodeBlock = /*#__PURE__*/ createWebComponent<CodeBlockProps>(
@@ -463,14 +479,14 @@ export const CodeBlock = /*#__PURE__*/ createWebComponent<CodeBlockProps>(
463
479
  );
464
480
 
465
481
  export interface CommandProps extends WebComponentProps {
466
- /** Flat list of items. Set as a JS property not an HTML attribute. */
482
+ /** Flat list of items. Set as a JS property, not an HTML attribute. */
467
483
  items?: { id: string; label: string; icon?: string; description?: string; shortcut?: string; group?: string }[];
468
484
  /** Placeholder text for the search input. */
469
485
  placeholder?: string;
470
486
  /** Label shown when no items match the current query. */
471
487
  emptyLabel?: string;
472
- /** Fired when the highlighted/active item changes via Arrow keys or when filtering re-clamps the active row. `id` is the newly active item's id, or `undefined` when no item is active (e.g. the filtered list is empty). Lets a host preview the active item without committing a selection. */
473
- onActiveChange?: (event: CustomEvent<{ id: undefined | string }>) => void;
488
+ /** Fired when the highlighted/active item changes, via Arrow keys or when filtering re-clamps the active row. `id` is the newly active item's id, or `undefined` when no item is active (e.g. the filtered list is empty). Lets a host preview the active item without committing a selection. */
489
+ onActiveChange?: (event: CustomEvent<{ id: string | undefined }>) => void;
474
490
  /** Fired on every keystroke in the search input. */
475
491
  onQueryChange?: (event: CustomEvent<{ value: string }>) => void;
476
492
  /** Fired when the user selects an item (click or Enter). */
@@ -491,10 +507,10 @@ export interface CompareProps extends WebComponentProps {
491
507
  compareId?: string;
492
508
  /** Re-hydrate / control the user's pick. Set as a JS PROPERTY: `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. */
493
509
  selection?: Record<string, unknown>;
494
- /** Layout: `'auto'` (default columns when wide, tabs when narrow, by CONTAINER width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
510
+ /** Layout: `'auto'` (default, columns when wide, tabs when narrow, by CONTAINER width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
495
511
  layout?: "auto" | "columns" | "tabs";
496
512
  /** Prose/text size for the rendered candidates. Attribute: `prose-size`. */
497
- proseSize?: "sm" | "lg" | "xs" | "base";
513
+ proseSize?: "xs" | "sm" | "base" | "lg";
498
514
  /** Shiki theme for code blocks in the candidates. Attribute: `code-theme`. */
499
515
  codeTheme?: string;
500
516
  /** Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. */
@@ -515,7 +531,7 @@ export const Compare = /*#__PURE__*/ createWebComponent<CompareProps>(
515
531
  );
516
532
 
517
533
  export interface ComposerProps extends WebComponentProps {
518
- /** Controlled value string or a full ComposerDoc (set as JS property). */
534
+ /** Controlled value: a string or a full ComposerDoc (set as JS property). */
519
535
  value?: string | ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: string; promptText?: string; data?: Record<string, unknown> } })[];
520
536
  /** Placeholder text shown when the composer is empty. */
521
537
  placeholder?: string;
@@ -524,12 +540,12 @@ export interface ComposerProps extends WebComponentProps {
524
540
  /** Show a loading/streaming state and block submit. */
525
541
  loading?: boolean;
526
542
  /** Maximum height in px before the content scrolls. Default 240. */
527
- maxHeight?: string | number;
543
+ maxHeight?: number | string;
528
544
  /** Whether pressing Enter (without Shift) submits. Default true. */
529
545
  submitOnEnter?: boolean;
530
- /** Trigger definitions set as a JS property. */
546
+ /** Trigger definitions. Set as a JS property. */
531
547
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record<string, unknown> }[] }[];
532
- /** Keyword highlight rules set as a JS property. */
548
+ /** Keyword highlight rules. Set as a JS property. */
533
549
  highlights?: (string | { pattern: string; flags?: string; class?: string })[];
534
550
  /** Default icon per entity kind (kind → image URL/data-URI) for items without their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. */
535
551
  kindIcons?: Record<string, string>;
@@ -539,7 +555,7 @@ export interface ComposerProps extends WebComponentProps {
539
555
  onEntityAdd?: (event: CustomEvent<{ entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> } }>) => void;
540
556
  /** An entity pill was deleted from the composer. */
541
557
  onEntityRemove?: (event: CustomEvent<{ entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> } }>) => void;
542
- /** The composer gained focus. `focus`/`blur` are NOT composed natively, so they don't escape the shadow root these re-expose them on the host. (For `keydown`/`paste`/`focusin`/`focusout`, listen NATIVELY on `<kai-composer>`: they're composed and already cross the shadow boundary.) */
558
+ /** The composer gained focus. `focus`/`blur` are NOT composed natively, so they don't escape the shadow root; these re-expose them on the host. (For `keydown`/`paste`/`focusin`/`focusout`, listen NATIVELY on `<kai-composer>`: they're composed and already cross the shadow boundary.) */
543
559
  onFocus?: (event: CustomEvent<{ originalEvent: FocusEvent }>) => void;
544
560
  /** The user submitted the composer (Enter or programmatic submit). */
545
561
  onSubmit?: (event: CustomEvent<{ doc: ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> } })[]; text: string; entities: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> }[] }>) => void;
@@ -560,12 +576,12 @@ export const Composer = /*#__PURE__*/ createWebComponent<ComposerProps>(
560
576
 
561
577
  export interface ConfirmProps extends WebComponentProps {
562
578
  /** The confirm definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { body, tone, actions:[…] }`. Import `ConfirmCardData` from `@kitn.ai/ui` for the full shape. */
563
- data?: Record<string, unknown>;
579
+ data?: { heading?: string; body?: string; tone?: "default" | "warning" | "danger"; actions: { id: string; label: string; style?: "primary" | "default" | "destructive"; payload?: unknown; default?: boolean }[]; dismissible?: boolean };
564
580
  /** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
565
581
  cardId?: string;
566
582
  /** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
567
583
  heading?: string;
568
- /** Focus the default action on mount (off by default no focus-stealing). Attribute: `autofocus`. */
584
+ /** Focus the default action on mount (off by default, so nothing steals focus). Attribute: `autofocus`. */
569
585
  autofocus?: boolean;
570
586
  /** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'action', action:'…' }`. */
571
587
  resolution?: Record<string, unknown>;
@@ -597,10 +613,10 @@ export const Context = /*#__PURE__*/ createWebComponent<ContextProps>(
597
613
  );
598
614
 
599
615
  export interface ConversationsProps extends WebComponentProps {
600
- /** Pre-bucketed conversation groups (e.g. "Today", "Yesterday"), each with its own conversations. Use this when you want to control the grouping/headers yourself; otherwise pass a flat `conversations` array. Set as a JS property. */
601
- groups: { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[];
602
- /** A flat list of conversation summaries; the component buckets them by recency for you. Ignored when `groups` is provided. Set as a JS property. */
603
- conversations: { id: string; title: string; groupId?: undefined | string; scope: { type: "document" | "collection"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[];
616
+ /** The list's section headers (`{ id, name, sortOrder, createdAt }`), rendered in array order. A group carries no conversations of its own; it is matched against `conversations` by id, so the two props are complementary rather than alternatives. Omit for an ungrouped list. Set as a JS property. */
617
+ groups?: { id: string; userId?: string; teamId?: string; name: string; sortOrder: number; createdAt: string }[];
618
+ /** Every conversation the list renders, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing "Ungrouped" section, so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit to supply them as `<kai-conversation>` light-DOM children instead, or for the empty state. */
619
+ conversations?: { id: string; title: string; groupId?: string; scope: { type: "document" | "collection"; documentId?: string; filters?: { tags?: string[]; authors?: string[]; contentType?: "transcript" | "markdown"; dateRange?: { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: string }[];
604
620
  /** The id of the currently-open conversation, highlighted in the list. */
605
621
  activeId?: string;
606
622
  /** Controlled collapsed state. Set as a JS property (`el.collapsed = true`) to drive the rail from your app, updating it in response to `kai-collapse-toggle`. Omit for uncontrolled (the element manages it). Collapsed shrinks the rail to a floating reopen button. */
@@ -643,7 +659,7 @@ export const Dialog = /*#__PURE__*/ createWebComponent<DialogProps>(
643
659
  );
644
660
 
645
661
  export interface EditableLabelProps extends WebComponentProps {
646
- /** The label text settable and reflected to the `value` attribute. Read `el.value` for live state. */
662
+ /** The label text. Settable and reflected to the `value` attribute. Read `el.value` for live state. */
647
663
  value?: string;
648
664
  /** Controlled edit state. `el.editing = true` opens the field; reflected to the `editing` attribute. */
649
665
  editing?: boolean;
@@ -693,7 +709,7 @@ export const Empty = /*#__PURE__*/ createWebComponent<EmptyProps>(
693
709
  );
694
710
 
695
711
  export interface FeedbackBarProps extends WebComponentProps {
696
- /** The banner label (e.g. "Was this helpful?"). Attribute: `bar-title` (`title` is avoided it's a global HTML attribute). */
712
+ /** The banner label (e.g. "Was this helpful?"). Attribute: `bar-title` (`title` is avoided because it is a global HTML attribute). */
697
713
  barTitle?: string;
698
714
  /** When set, a not-helpful vote opens an optional detail form before the thank-you confirmation. Attribute: `collect-detail`. */
699
715
  collectDetail?: boolean;
@@ -725,7 +741,7 @@ export const FeedbackBar = /*#__PURE__*/ createWebComponent<FeedbackBarProps>(
725
741
  export interface FileTreeProps extends WebComponentProps {
726
742
  /** The files to render. Set as a JS property (array of `{ path, url?, code?, language?, type?, additions?, deletions?, status? }`). */
727
743
  files: { path: string; url?: undefined | string; code?: undefined | string; language?: undefined | string; type?: undefined | "html" | "pdf" | "image" | "other"; additions?: undefined | number; deletions?: undefined | number; status?: undefined | "added" | "modified" | "deleted" | "renamed" | "untracked" }[];
728
- /** Selected file path highlighted in the tree. */
744
+ /** Selected file path, highlighted in the tree. */
729
745
  activeFile?: string;
730
746
  /** Folder paths expanded initially. Omit to start with all folders open. */
731
747
  defaultExpanded?: string[];
@@ -747,7 +763,7 @@ export interface FileUploadProps extends WebComponentProps {
747
763
  multiple?: boolean;
748
764
  /** `accept` attribute for the file picker (e.g. `image/*`). */
749
765
  accept?: string;
750
- /** Disable the dropzone no clicking, no drag-and-drop. */
766
+ /** Disable the dropzone: no clicking, no drag-and-drop. */
751
767
  disabled?: boolean;
752
768
  /** Default dropzone label (overridable via the default slot). */
753
769
  label?: string;
@@ -763,8 +779,8 @@ export const FileUpload = /*#__PURE__*/ createWebComponent<FileUploadProps>(
763
779
  );
764
780
 
765
781
  export interface FormProps extends WebComponentProps {
766
- /** The form definition a JSON Schema (`type:'object'`) + `x-kai-*` UI hints (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { type:'object', properties:{…} }`. Import the `FormDefinition` type from `@kitn.ai/ui` for the full shape (it is self-referential, so the element types it loosely). */
767
- data?: Record<string, unknown>;
782
+ /** The form definition: a JSON Schema (`type:'object'`) + `x-kai-*` UI hints (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { type:'object', properties:{…} }`. Import the `FormDefinition` type from `@kitn.ai/ui` for the full shape. It IS self-referential (`FormField.properties` is another `FormField` map), and the generated `element-types.d.ts` inlines every named type, so the shipped declaration bottoms out in a `Record<string, unknown>` placeholder one level down rather than carrying the recursion. That is why `FormDefinition` is a `type` alias: an interface gets no implicit index signature, so it would not be assignable to that placeholder. */
783
+ data?: { type: "object"; title?: string; description?: string; required?: string[]; properties: Record<string, { type: "string" | "number" | "integer" | "boolean" | "array" | "object"; title?: string; description?: string; default?: unknown; enum?: unknown[]; format?: "email" | "uri" | "url" | "date" | "date-time" | "time"; minimum?: number; maximum?: number; minLength?: number; maxLength?: number; pattern?: string; minItems?: number; maxItems?: number; items?: Record<string, unknown> | { enum: unknown[] }; properties?: Record<string, Record<string, unknown>>; required?: string[]; readOnly?: boolean; "x-kai-widget"?: "textarea" | "slider" | "rating" | "radio" | "select" | "checkbox" | "password" | "switch"; "x-kai-placeholder"?: string; "x-kai-step"?: number }>; "x-kai-order"?: string[]; "x-kai-inlineMax"?: number; "x-kai-submitLabel"?: string; "x-kai-dismissible"?: boolean; "x-kai-actions"?: { id: string; label: string; variant?: "default" | "ghost" | "outline" }[] };
768
784
  /** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
769
785
  cardId?: string;
770
786
  /** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
@@ -777,7 +793,7 @@ export interface FormProps extends WebComponentProps {
777
793
  defaultValues?: Record<string, unknown>;
778
794
  /** Disable all fields + submit. Attribute: `disabled`. */
779
795
  disabled?: boolean;
780
- /** The form's values changed on input current coerced values + validity. */
796
+ /** The form's values changed on input. Carries the current coerced values + validity. */
781
797
  onValuesChange?: (event: CustomEvent<{ values: Record<string, unknown>; valid: boolean }>) => void;
782
798
  }
783
799
 
@@ -847,7 +863,7 @@ export const Image = /*#__PURE__*/ createWebComponent<ImageProps>(
847
863
  export interface InputProps extends WebComponentProps {
848
864
  /** Native input type: `text` (default) · `email` · `url` · `search` · `tel` · `password` · `number`. Single-line only. */
849
865
  type?: string;
850
- /** Controlled value settable and reflected to the `value` attribute. `el.value = 'hi'` drives it (no event); typing updates it and fires `kai-input`. Read `el.value` for live state. */
866
+ /** Controlled value. Settable and reflected to the `value` attribute. `el.value = 'hi'` drives it (no event); typing updates it and fires `kai-input`. Read `el.value` for live state. */
851
867
  value?: string;
852
868
  /** Placeholder shown when empty. */
853
869
  placeholder?: string;
@@ -887,10 +903,10 @@ export const Input = /*#__PURE__*/ createWebComponent<InputProps>(
887
903
  );
888
904
 
889
905
  export interface KbdProps extends WebComponentProps {
890
- /** Shortcut spec tokens joined by `+` (e.g. `Mod+Shift+K`). Omit it to show default-slot content instead. Display only; the element does not bind keys. */
906
+ /** Shortcut spec: tokens joined by `+` (e.g. `Mod+Shift+K`). Omit it to show default-slot content instead. Display only; the element does not bind keys. */
891
907
  keys?: string;
892
908
  /** `mac` uses ⌘/⌥, `other` uses Ctrl. `auto` (default) sniffs the OS. */
893
- platform?: "other" | "auto" | "mac";
909
+ platform?: "auto" | "mac" | "other";
894
910
  /** Cap size: `sm` or `md`. Defaults to `md`. */
895
911
  size?: "sm" | "md";
896
912
  }
@@ -936,7 +952,7 @@ export interface MarkdownProps extends WebComponentProps {
936
952
  /** The markdown source to render. */
937
953
  content: string;
938
954
  /** Text/markdown sizing. */
939
- proseSize?: "sm" | "lg" | "xs" | "base";
955
+ proseSize?: "xs" | "sm" | "base" | "lg";
940
956
  /** Shiki theme for fenced code blocks. */
941
957
  codeTheme?: string;
942
958
  /** Disable syntax highlighting (no Shiki loads). */
@@ -951,11 +967,11 @@ export const Markdown = /*#__PURE__*/ createWebComponent<MarkdownProps>(
951
967
  );
952
968
 
953
969
  export interface MenuProps extends WebComponentProps {
954
- /** Tree of menu items. Set as a JS property not an HTML attribute. */
970
+ /** Tree of menu items. Set as a JS property, not an HTML attribute. */
955
971
  items?: { id?: string; label?: string; icon?: string; shortcut?: string; checked?: boolean; radioGroup?: string; disabled?: boolean; separator?: boolean; heading?: boolean; items?: Record<string, unknown>[] }[];
956
972
  /** Optional placement hint (unused by the underlying Dropdown which always positions bottom-start, kept for future extension). */
957
973
  placement?: string;
958
- /** Built-in trigger: leading icon (a named icon like `"plus"`, an image URL/data-URI, or text). Use this instead of slotting `slot="trigger"` for the common case a slotted trigger overrides it. */
974
+ /** Built-in trigger: leading icon (a named icon like `"plus"`, an image URL/data-URI, or text). Use this instead of slotting `slot="trigger"` for the common case; a slotted trigger overrides it. */
959
975
  triggerIcon?: string;
960
976
  /** Built-in trigger: a text label (e.g. `"High"`). */
961
977
  triggerLabel?: string;
@@ -967,11 +983,11 @@ export interface MenuProps extends WebComponentProps {
967
983
  open?: boolean;
968
984
  /** Initial open state on mount (uncontrolled seed). */
969
985
  defaultOpen?: boolean;
970
- /** Disable the trigger click/keyboard and `show()` no longer open the menu. */
986
+ /** Disable the trigger: click/keyboard and `show()` no longer open the menu. */
971
987
  disabled?: boolean;
972
988
  /** The menu opened or closed (by click, keyboard, Escape, outside-click, or a method). */
973
989
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
974
- /** Fired when the user selects a leaf item. - Plain items: `{ id }`. - Checkbox items: `{ id, checked }` where `checked` is the NEW state. - Radio items: `{ id, radioGroup }` the consumer marks `id` as the selected one in `radioGroup` and clears the others. */
990
+ /** Fired when the user selects a leaf item. - Plain items: `{ id }`. - Checkbox items: `{ id, checked }` where `checked` is the NEW state. - Radio items: `{ id, radioGroup }`, where the consumer marks `id` as the selected one in `radioGroup` and clears the others. */
975
991
  onSelect?: (event: CustomEvent<{ id: string; checked?: undefined | boolean; radioGroup?: undefined | string }>) => void;
976
992
  }
977
993
 
@@ -984,15 +1000,13 @@ export const Menu = /*#__PURE__*/ createWebComponent<MenuProps>(
984
1000
 
985
1001
  export interface MessageProps extends WebComponentProps {
986
1002
  /** The full message object. Set as a JS property. */
987
- message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" };
988
- /** Convenience for simple cases when not passing a `message` object. */
1003
+ message?: { id: string; role: "user" | "assistant"; parts: ({ type: "text"; text: string; raw?: { source: string; payload: unknown } } | { type: "reasoning"; text: string; label?: string; index?: number; streamId?: string; signature?: string; raw?: { source: string; payload: unknown } } | { type: "tool"; tool: { type: string; kind?: "command" | "file-change" | "search" | "fetch" | "mcp" | "image" | "generic"; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; rawInput?: string; output?: Record<string, unknown>; toolCallId?: string; errorText?: string; raw?: { source: string; payload: unknown } }; raw?: { source: string; payload: unknown } } | { type: "card"; envelope: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }; raw?: { source: string; payload: unknown } } | { type: "source"; source: { id?: string; url?: string; title?: string; snippet?: string; index?: number }; raw?: { source: string; payload: unknown } } | { type: "file"; attachment: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }; raw?: { source: string; payload: unknown } })[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" };
1004
+ /** Who is speaking: `'user'` or `'assistant'`. Convenience for simple cases when not passing a `message` object. This is the SEMANTIC role of the message, not an ARIA role. The name collides with the global ARIA `role` attribute, which is why the facade lifts it off the host (see `liftRoleOffHost`). Neither speaker is a valid ARIA role, so a `role="user"` left on `<kai-message>` is a CRITICAL axe `aria-roles` violation. The accessible role lives on the row inside the shadow root instead: `role="article"` plus an `aria-label` naming the speaker, matching the SolidJS `<Message>` component. */
989
1005
  role?: "user" | "assistant";
990
- /** Convenience content (used when `message` is not set). */
991
- content?: string;
992
1006
  /** Force markdown on/off. Defaults to on for assistant, off for user. */
993
1007
  markdown?: boolean;
994
1008
  /** Text/markdown sizing for the message body. */
995
- proseSize?: "sm" | "lg" | "xs" | "base";
1009
+ proseSize?: "xs" | "sm" | "base" | "lg";
996
1010
  /** Shiki theme name used for fenced code blocks in the content. */
997
1011
  codeTheme?: string;
998
1012
  /** Disable syntax highlighting for code blocks (no Shiki loads). */
@@ -1005,27 +1019,31 @@ export interface MessageProps extends WebComponentProps {
1005
1019
  avatarFallback?: string;
1006
1020
  /** Avatar rail mode. `'none'` omits the avatar rail entirely so the body spans the full row (predictable layout when you never show avatars). Any other value keeps the default behaviour: the built-in avatar when one resolves, or your `slot="avatar"` content when projected (which REPLACES the built-in). */
1007
1021
  avatar?: string;
1022
+ /** Optional card type -> custom-element tag overrides/additions for `card` parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
1023
+ cardTypes?: Record<string, string>;
1024
+ /** JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `"type"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one. */
1025
+ cardSchemas?: Record<string, object>;
1008
1026
  /** An action button was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
1009
1027
  onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
1010
1028
  }
1011
1029
 
1012
1030
  export const Message = /*#__PURE__*/ createWebComponent<MessageProps>(
1013
1031
  'kai-message',
1014
- ["theme","message","role","content","markdown","proseSize","codeTheme","codeHighlight","actionsReveal","avatarSrc","avatarFallback","avatar"],
1032
+ ["theme","message","role","markdown","proseSize","codeTheme","codeHighlight","actionsReveal","avatarSrc","avatarFallback","avatar","cardTypes","cardSchemas"],
1015
1033
  { onMessageAction: 'kai-message-action' },
1016
1034
  () => import('@kitn.ai/ui/elements/message'),
1017
1035
  );
1018
1036
 
1019
1037
  export interface ModelSwitcherProps extends WebComponentProps {
1020
- /** The selectable models. Set as a JS property (array). */
1021
- models: { id: string; name: string; provider?: undefined | string; description?: undefined | string; group?: undefined | string }[];
1038
+ /** The selectable models. Set as a JS property (array). Omit to supply them as `<kai-model>` light-DOM children instead; when both are present the property's models come first. */
1039
+ models?: { id: string; name: string; provider?: string; description?: string; group?: string }[];
1022
1040
  /** The currently-selected model id. Defaults to the first model. */
1023
1041
  currentModel?: string;
1024
1042
  /** Drive/observe the dropdown's open state (Shoelace-style: settable + reflected to the `open` attribute, the dropdown still self-manages on click/keyboard). Set `el.open = true`, or `<kai-model-switcher open>`; listen for `kai-open-change`. */
1025
1043
  open?: boolean;
1026
1044
  /** Initial open state on mount (uncontrolled seed). */
1027
1045
  defaultOpen?: boolean;
1028
- /** Disable the trigger click/keyboard and `show()` no longer open the dropdown. */
1046
+ /** Disable the trigger: click/keyboard and `show()` no longer open the dropdown. */
1029
1047
  disabled?: boolean;
1030
1048
  /** A model was selected. */
1031
1049
  onModelChange?: (event: CustomEvent<{ modelId: string }>) => void;
@@ -1042,7 +1060,7 @@ export const ModelSwitcher = /*#__PURE__*/ createWebComponent<ModelSwitcherProps
1042
1060
 
1043
1061
  export interface NavProps extends WebComponentProps {
1044
1062
  /** The nav items. Set as a JS property (array, not an attribute). Each item may carry `children` (a collapsible group), a `status` dot, and trailing `meta` text. */
1045
- items?: { id: string; label?: string; icon?: string; badge?: string; trailing?: string; disabled?: boolean; children?: Record<string, unknown>[]; status?: { tone: "error" | "primary" | "info" | "success" | "warning" | "neutral"; label?: string; pulse?: boolean }; meta?: string; action?: { icon: string; label: string }; closable?: boolean }[];
1063
+ items?: { id: string; label?: string; icon?: string; badge?: string; trailing?: string; disabled?: boolean; children?: Record<string, unknown>[]; status?: { tone: "primary" | "info" | "success" | "warning" | "error" | "neutral"; label?: string; pulse?: boolean }; meta?: string; action?: { icon: string; label: string }; closable?: boolean }[];
1046
1064
  /** Active item id (controlled). */
1047
1065
  value?: string;
1048
1066
  /** Initial active id when uncontrolled. */
@@ -1066,7 +1084,7 @@ export const Nav = /*#__PURE__*/ createWebComponent<NavProps>(
1066
1084
 
1067
1085
  export interface NoticeProps extends WebComponentProps {
1068
1086
  /** `neutral` (default) · `info` · `warning` · `error` · `success`. Drives the leading icon's color and the a11y role (`alert` for errors, else `status`). */
1069
- severity?: "error" | "info" | "success" | "warning" | "neutral";
1087
+ severity?: "neutral" | "info" | "warning" | "error" | "success";
1070
1088
  /** Leading icon: omit for the severity default, `"none"` to hide it, or a named icon to override. */
1071
1089
  icon?: string;
1072
1090
  /** Show a dismiss (×) that hides the notice and emits `kai-dismiss`. */
@@ -1101,7 +1119,7 @@ export interface PaneProps extends WebComponentProps {
1101
1119
  onClose?: (event: CustomEvent) => void;
1102
1120
  /** The dock control was clicked (only present when `show-dock`). */
1103
1121
  onDock?: (event: CustomEvent) => void;
1104
- /** The maximize/restore control was clicked. `detail.maximized` is the intended NEXT state drive the `maximized` prop yourself from it. */
1122
+ /** The maximize/restore control was clicked. `detail.maximized` is the intended NEXT state. Drive the `maximized` prop yourself from it. */
1105
1123
  onMaximize?: (event: CustomEvent<{ maximized: boolean }>) => void;
1106
1124
  /** The split control was clicked (only present when `show-split`). */
1107
1125
  onSplit?: (event: CustomEvent) => void;
@@ -1138,7 +1156,7 @@ export const PaneGroup = /*#__PURE__*/ createWebComponent<PaneGroupProps>(
1138
1156
 
1139
1157
  export interface PopoverProps extends WebComponentProps {
1140
1158
  /** Floating placement relative to the trigger (floating-ui placement). */
1141
- placement?: "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end";
1159
+ placement?: "top" | "right" | "bottom" | "left" | "bottom-end" | "bottom-start" | "left-end" | "left-start" | "right-end" | "right-start" | "top-end" | "top-start";
1142
1160
  /** Gap in px between the trigger and the panel. */
1143
1161
  gutter?: number;
1144
1162
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute, the element still self-manages on click). Set `el.open = true`, or `<kai-popover open>`; listen for `kai-open-change`. */
@@ -1177,10 +1195,10 @@ export const ProgressBar = /*#__PURE__*/ createWebComponent<ProgressBarProps>(
1177
1195
  );
1178
1196
 
1179
1197
  export interface PromptDockProps extends WebComponentProps {
1180
- /** How the tray frames the input the SPATIAL inset axis: `inset` (default, the classic recessed frame on every side) | `edge` (top/bottom inset only; the input sits flush left/right so the lips span the full width) | `none` (no inset; the lips attach directly as a plain stack). Attribute: `frame`. */
1181
- frame?: "none" | "inset" | "edge";
1182
- /** How the tray surface looks the VISUAL axis, orthogonal to `frame`: `soft` (default, sunken surface + border + radius) | `outlined` (transparent + border + radius) | `filled` (sunken, no border, + radius) | `plain` (bare). Attribute: `appearance`. */
1183
- appearance?: "outlined" | "filled" | "plain" | "soft";
1198
+ /** How the tray frames the input, the SPATIAL inset axis: `inset` (default, the classic recessed frame on every side) | `edge` (top/bottom inset only; the input sits flush left/right so the lips span the full width) | `none` (no inset; the lips attach directly as a plain stack). Attribute: `frame`. */
1199
+ frame?: "inset" | "edge" | "none";
1200
+ /** How the tray surface looks, the VISUAL axis orthogonal to `frame`: `soft` (default, sunken surface + border + radius) | `outlined` (transparent + border + radius) | `filled` (sunken, no border, + radius) | `plain` (bare). Attribute: `appearance`. */
1201
+ appearance?: "soft" | "outlined" | "filled" | "plain";
1184
1202
  }
1185
1203
 
1186
1204
  export const PromptDock = /*#__PURE__*/ createWebComponent<PromptDockProps>(
@@ -1209,17 +1227,17 @@ export interface PromptInputProps extends WebComponentProps {
1209
1227
  voice?: boolean;
1210
1228
  /** When set and `loading` is true, the send button is replaced by a Stop button (square icon, "Stop" aria-label). Clicking it fires `kai-stop`. */
1211
1229
  stoppable?: boolean;
1212
- /** Send-button visibility. `'always'` (default) always shows it; `'auto'` shows it only when there's text/attachments (an empty composer hides it Enter still submits). To hide it entirely (Enter-only), it's pure CSS: `::part(send){display:none}` no prop needed. Restyle via `::part(send)`. The Stop button (`stoppable` + `loading`) is unaffected. */
1230
+ /** Send-button visibility. `'always'` (default) always shows it; `'auto'` shows it only when there's text/attachments (an empty composer hides it, though Enter still submits). To hide it entirely (Enter-only), it's pure CSS: `::part(send){display:none}`, no prop needed. Restyle via `::part(send)`. The Stop button (`stoppable` + `loading`) is unaffected. */
1213
1231
  submit?: "always" | "auto";
1214
1232
  /** When `false`, hides the built-in paperclip attach button even though the element otherwise supports attachments. Use this when a `+` menu in `toolbar-start` already exposes "Add files", to avoid a duplicate control. Defaults to `true`. */
1215
1233
  attach?: boolean;
1216
1234
  /** Attachments to seed the input with (so a consumer can pre-populate staged files without an upload). Set as a JS property; the element then manages its own attachment state from there (add via the paperclip, remove per chip). */
1217
1235
  attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[];
1218
- /** Rich entity triggers each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill. Convention: `/` → skills, `@` → agents (plugins are the grouping/provenance of those items). Set as a JS property. */
1236
+ /** Rich entity triggers. Each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill. Convention: `/` → skills, `@` → agents (plugins are the grouping/provenance of those items). Set as a JS property. */
1219
1237
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record<string, unknown> }[] }[];
1220
1238
  /** Default icon per entity kind (kind → image URL/data-URI) for pills/menu items without their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. */
1221
1239
  kindIcons?: Record<string, string>;
1222
- /** The staged attachments changed a file was added (via the paperclip) or removed (per-chip ×). Carries the full current list so a consumer can react in real time (validate, show upload progress, toggle the send button). */
1240
+ /** The staged attachments changed: a file was added (via the paperclip) or removed (per-chip ×). Carries the full current list so a consumer can react in real time (validate, show upload progress, toggle the send button). */
1223
1241
  onAttachmentsChange?: (event: CustomEvent<{ attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
1224
1242
  /** The Search (Globe) toolbar button was clicked. */
1225
1243
  onSearch?: (event: CustomEvent<Record<string, never>>) => void;
@@ -1257,7 +1275,7 @@ export interface ReasoningProps extends WebComponentProps {
1257
1275
  streaming?: boolean;
1258
1276
  /** Render `text` as markdown. */
1259
1277
  markdown?: boolean;
1260
- /** Gate the disclosure trigger programmatic `show()/hide()/toggle()` still work, but the trigger click no longer toggles. */
1278
+ /** Gate the disclosure trigger: programmatic `show()/hide()/toggle()` still work, but the trigger click no longer toggles. */
1261
1279
  disabled?: boolean;
1262
1280
  /** The reasoning block expanded or collapsed (via the trigger, streaming auto-open, or a method). */
1263
1281
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
@@ -1290,21 +1308,23 @@ export const Remote = /*#__PURE__*/ createWebComponent<RemoteProps>(
1290
1308
 
1291
1309
  export interface ResizableProps extends WebComponentProps {
1292
1310
  /** Layout axis: `horizontal` (row, default) or `vertical` (column). */
1293
- orientation?: "vertical" | "horizontal";
1311
+ orientation?: "horizontal" | "vertical";
1294
1312
  /** Which item index is maximized (null = none). Declarative source of truth. */
1295
- maximizedIndex?: null | number;
1296
- /** Divider affordance drawn inside each draggable handle's 8px grab zone: - `line` (default) a 1px hairline, transparent at rest, tinting on hover/drag. - `grip` a dotted grip handle. - `none` no visible divider, just the invisible hit-area. The full grab zone and keyboard/ARIA behavior are identical for all three. */
1297
- handle?: "none" | "line" | "grip";
1313
+ maximizedIndex?: number | null;
1314
+ /** Divider affordance drawn inside each draggable handle's 8px grab zone: - `line` (default): a 1px hairline, transparent at rest, tinting on hover/drag. - `grip`: a dotted grip handle. - `none`: no visible divider, just the invisible hit-area. The full grab zone and keyboard/ARIA behavior are identical for all three. */
1315
+ handle?: "line" | "grip" | "none";
1298
1316
  /** Fired on drag-end / keyboard resize / visibility change. `detail.sizes` = panel sizes in percent. */
1299
1317
  onChange?: (event: CustomEvent<{ sizes: number[] }>) => void;
1300
1318
  /** Observe layout maximize state. */
1301
- onMaximizeChange?: (event: CustomEvent<{ maximized: boolean; index: null | number }>) => void;
1319
+ onMaximizeChange?: (event: CustomEvent<{ maximized: boolean; index: number | null }>) => void;
1320
+ /** Authoritative maximize state, dispatched as a raw composed CustomEvent (not through `dispatch`) onto the affected `<kai-resizable-item>` and, on restore, onto the group host. A nested element (e.g. `<kai-artifact>`) listens for it to reconcile its own toggle. */
1321
+ onMaximizeState?: (event: CustomEvent<{ maximized: boolean }>) => void;
1302
1322
  }
1303
1323
 
1304
1324
  export const Resizable = /*#__PURE__*/ createWebComponent<ResizableProps>(
1305
1325
  'kai-resizable',
1306
1326
  ["theme","orientation","maximizedIndex","handle"],
1307
- { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change' },
1327
+ { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change', onMaximizeState: 'kai-maximize-state' },
1308
1328
  () => import('@kitn.ai/ui/elements/resizable'),
1309
1329
  );
1310
1330
 
@@ -1319,21 +1339,22 @@ export interface ResizableItemProps extends WebComponentProps {
1319
1339
  locked?: boolean;
1320
1340
  /** Hide this panel; its divider is dropped and the rest reflow. */
1321
1341
  hidden?: boolean;
1322
- /** Collapse this panel same layout effect as `hidden` (divider dropped, the rest reflow), but it WORKS as a bare boolean from framework JSX. A plain `<kai-resizable-item collapsed>` in React/Solid/Vue/Svelte collapses the panel at the first render; `hidden` does not, because a JSX boolean sets neither the `hidden` attribute nor the IDL property on a custom element, so the parent never sees it. The facade reflects `collapsed` to a `collapsed` attribute the parent reads. Prefer this over `hidden` for declarative collapse. */
1342
+ /** Collapse this panel. Same layout effect as `hidden` (divider dropped, the rest reflow), but it WORKS as a bare boolean from framework JSX. A plain `<kai-resizable-item collapsed>` in React/Solid/Vue/Svelte collapses the panel at the first render; `hidden` does not, because a JSX boolean sets neither the `hidden` attribute nor the IDL property on a custom element, so the parent never sees it. The facade reflects `collapsed` to a `collapsed` attribute the parent reads. Prefer this over `hidden` for declarative collapse. */
1323
1343
  collapsed?: boolean;
1324
1344
  onChange?: (event: CustomEvent<unknown>) => void;
1325
1345
  onMaximizeChange?: (event: CustomEvent<unknown>) => void;
1346
+ onMaximizeState?: (event: CustomEvent<unknown>) => void;
1326
1347
  }
1327
1348
 
1328
1349
  export const ResizableItem = /*#__PURE__*/ createWebComponent<ResizableItemProps>(
1329
1350
  'kai-resizable-item',
1330
1351
  ["theme","size","min","max","locked","hidden","collapsed"],
1331
- { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change' },
1352
+ { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change', onMaximizeState: 'kai-maximize-state' },
1332
1353
  () => import('@kitn.ai/ui/elements/resizable'),
1333
1354
  );
1334
1355
 
1335
1356
  export interface ResponseStreamProps extends WebComponentProps {
1336
- /** Text to stream. A string, or an `AsyncIterable<string>` (set as a JS property async iterables can't be HTML attributes). */
1357
+ /** Text to stream. A string, or an `AsyncIterable<string>` (set as a JS property, since async iterables can't be HTML attributes). */
1337
1358
  text?: string | AsyncIterable<string>;
1338
1359
  /** Reveal animation. */
1339
1360
  mode?: "typewriter" | "fade";
@@ -1353,22 +1374,22 @@ export const ResponseStream = /*#__PURE__*/ createWebComponent<ResponseStreamPro
1353
1374
  );
1354
1375
 
1355
1376
  export interface ScopePickerProps extends WebComponentProps {
1356
- /** Authors to offer as scope filters. Set as a JS property. */
1357
- availableAuthors: string[];
1358
- /** Tags to offer as scope filters. Set as a JS property. */
1359
- availableTags: string[];
1377
+ /** Authors to offer as scope filters. Omit to drop the Authors section (for a tag-only picker). Set as a JS property. */
1378
+ availableAuthors?: string[];
1379
+ /** Tags to offer as scope filters. Omit to drop the Tags section (for an author-only picker). Set as a JS property. */
1380
+ availableTags?: string[];
1360
1381
  /** The label shown on the trigger for the active scope. */
1361
1382
  currentLabel?: string;
1362
1383
  /** Drive/observe the dropdown's open state (Shoelace-style: settable + reflected to the `open` attribute, the dropdown still self-manages on click/keyboard). Set `el.open = true`, or `<kai-scope-picker open>`; listen for `kai-open-change`. */
1363
1384
  open?: boolean;
1364
1385
  /** Initial open state on mount (uncontrolled seed). */
1365
1386
  defaultOpen?: boolean;
1366
- /** Disable the trigger click/keyboard and `show()` no longer open the dropdown. */
1387
+ /** Disable the trigger: click/keyboard and `show()` no longer open the dropdown. */
1367
1388
  disabled?: boolean;
1368
1389
  /** The scope dropdown opened or closed (by click, keyboard, Escape, outside-click, or a method). */
1369
1390
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
1370
1391
  /** A scope was chosen (`undefined` filters = "All Content"). */
1371
- onScopeChange?: (event: CustomEvent<{ filters: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }>) => void;
1392
+ onScopeChange?: (event: CustomEvent<{ filters: { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } | undefined }>) => void;
1372
1393
  }
1373
1394
 
1374
1395
  export const ScopePicker = /*#__PURE__*/ createWebComponent<ScopePickerProps>(
@@ -1418,10 +1439,10 @@ export interface ScrollButtonProps extends WebComponentProps {
1418
1439
  /** CSS id of the scroll container to control. When omitted the element walks up the DOM (outside its own shadow root) to find the nearest scrollable ancestor. Mirrors the `for` convention of `<label for="...">`. */
1419
1440
  for?: string;
1420
1441
  /** Button visual variant: `'outline' | 'ghost' | 'default'`. Defaults to `'outline'`. */
1421
- variant?: "default" | "ghost" | "outline";
1442
+ variant?: "outline" | "ghost" | "default";
1422
1443
  /** Button size token. Defaults to `'icon'` (square). */
1423
1444
  size?: "sm" | "md" | "lg" | "icon" | "icon-sm";
1424
- /** Emitted when the user clicks the button and `scrollToBottom()` is called. Carries no detail consumers use it to know a manual scroll occurred. */
1445
+ /** Emitted when the user clicks the button and `scrollToBottom()` is called. Carries no detail; consumers use it to know a manual scroll occurred. */
1425
1446
  onScroll?: (event: CustomEvent) => void;
1426
1447
  }
1427
1448
 
@@ -1433,7 +1454,7 @@ export const ScrollButton = /*#__PURE__*/ createWebComponent<ScrollButtonProps>(
1433
1454
  );
1434
1455
 
1435
1456
  export interface SearchProps extends WebComponentProps {
1436
- /** Controlled query settable and reflected to the `value` attribute. Read `el.value` for live state. */
1457
+ /** Controlled query. Settable and reflected to the `value` attribute. Read `el.value` for live state. */
1437
1458
  value?: string;
1438
1459
  /** Placeholder. Defaults to `Search…`. */
1439
1460
  placeholder?: string;
@@ -1463,7 +1484,7 @@ export const Search = /*#__PURE__*/ createWebComponent<SearchProps>(
1463
1484
  export interface SegmentedProps extends WebComponentProps {
1464
1485
  /** The selectable segments, left to right. Set as a JS property (array). */
1465
1486
  options: { value: string; label: string; icon?: undefined | string }[];
1466
- /** Controlled selected `value` settable and reflected to the `value` attribute. `el.value = 'preview'` drives it; choosing a segment updates it and fires `kai-change`. Read `el.value` for live state. */
1487
+ /** Controlled selected `value`. Settable and reflected to the `value` attribute. `el.value = 'preview'` drives it; choosing a segment updates it and fires `kai-change`. Read `el.value` for live state. */
1467
1488
  value?: string;
1468
1489
  /** Control density: `sm` or `md`. Defaults to `md`. */
1469
1490
  size?: "sm" | "md";
@@ -1479,8 +1500,8 @@ export const Segmented = /*#__PURE__*/ createWebComponent<SegmentedProps>(
1479
1500
  );
1480
1501
 
1481
1502
  export interface SeparatorProps extends WebComponentProps {
1482
- /** `horizontal` (default, block + full-width) or `vertical` (a rule inside a flex/grid row it stretches to the row height). */
1483
- orientation?: "vertical" | "horizontal";
1503
+ /** `horizontal` (default, block + full-width) or `vertical` (a rule inside a flex/grid row, stretching to the row height). */
1504
+ orientation?: "horizontal" | "vertical";
1484
1505
  }
1485
1506
 
1486
1507
  export const Separator = /*#__PURE__*/ createWebComponent<SeparatorProps>(
@@ -1537,8 +1558,8 @@ export const Skeleton = /*#__PURE__*/ createWebComponent<SkeletonProps>(
1537
1558
  );
1538
1559
 
1539
1560
  export interface SkillsProps extends WebComponentProps {
1540
- /** The active skills to badge. Set as a JS property. */
1541
- skills: { id: string; name: string }[];
1561
+ /** The active skills to badge. Set as a JS property. Omit to supply them as `<kai-skill>` light-DOM children instead; when both are present the property's skills come first. Nothing renders when there are none. */
1562
+ skills?: { id: string; name: string }[];
1542
1563
  }
1543
1564
 
1544
1565
  export const Skills = /*#__PURE__*/ createWebComponent<SkillsProps>(
@@ -1553,7 +1574,7 @@ export interface SourceProps extends WebComponentProps {
1553
1574
  href?: string;
1554
1575
  /** Trigger label (defaults to the domain). */
1555
1576
  label?: string;
1556
- /** Hover-card headline. Attribute: `headline` (`title` is avoided it's a global HTML attribute that reflects in a CE constructor and breaks it). */
1577
+ /** Hover-card headline. Attribute: `headline` (`title` is avoided because it is a global HTML attribute that reflects in a CE constructor and breaks it). */
1557
1578
  headline?: string;
1558
1579
  /** Hover-card body text describing the source. */
1559
1580
  description?: string;
@@ -1569,11 +1590,11 @@ export const Source = /*#__PURE__*/ createWebComponent<SourceProps>(
1569
1590
  );
1570
1591
 
1571
1592
  export interface SourcesProps extends WebComponentProps {
1572
- /** The sources to render. Set as a JS property. */
1573
- sources: { href: string; title?: undefined | string; description?: undefined | string; label?: undefined | string; showFavicon?: undefined | boolean }[];
1593
+ /** The sources to render. Set as a JS property. Omit to supply them as `<kai-source>` light-DOM children instead; when both are present the property's sources come first. */
1594
+ sources?: { href: string; title?: string; description?: string; label?: string; showFavicon?: boolean }[];
1574
1595
  /** Show favicons on all items (per-item `showFavicon` overrides). */
1575
1596
  showFavicon?: boolean;
1576
- /** When true, each citation chip is labelled with its 1-based index in the merged (prop + declarative-children) list (`[1]`, `[2]`, …) instead of the per-item `label` or domain fallback. HTML attribute: `numbered` (boolean bare attribute or `numbered="true"`). JS property: `el.numbered = true`. */
1597
+ /** When true, each citation chip is labelled with its 1-based index in the merged (prop + declarative-children) list (`[1]`, `[2]`, …) instead of the per-item `label` or domain fallback. HTML attribute: `numbered` (boolean: a bare attribute or `numbered="true"`). JS property: `el.numbered = true`. */
1577
1598
  numbered?: boolean;
1578
1599
  }
1579
1600
 
@@ -1603,14 +1624,14 @@ export const Status = /*#__PURE__*/ createWebComponent<StatusProps>(
1603
1624
  );
1604
1625
 
1605
1626
  export interface SuggestionsProps extends WebComponentProps {
1606
- /** The suggestions. Strings, or `{ label, value }` when the displayed text and the emitted value differ. Set as a JS property. */
1607
- suggestions: (string | { label: string; value?: undefined | string; icon?: undefined | string })[];
1627
+ /** The suggestions. Strings, or `{ label, value }` when the displayed text and the emitted value differ. Set as a JS property. Omit to supply them as `<kai-suggestion>` light-DOM children instead; when both are present the property's suggestions come first. */
1628
+ suggestions?: (string | { label: string; value?: string; icon?: string })[];
1608
1629
  /** Chip style: `'outline'` (default), `'ghost'`, or `'default'` (filled). */
1609
- variant?: "default" | "ghost" | "outline";
1630
+ variant?: "outline" | "ghost" | "default";
1610
1631
  /** Row height for `layout="list"`: `'md'` (default) or `'lg'` for taller rows. Chips are unaffected. */
1611
1632
  size?: "md" | "lg";
1612
- /** Layout: `'chips'` (default) renders a wrapping row of rounded pills; `'list'` renders a vertical, full-width "Ideas for you" list each row is left-aligned with a leading `icon`, a label, and a hover background. */
1613
- layout?: "list" | "chips";
1633
+ /** Layout: `'chips'` (default) renders a wrapping row of rounded pills; `'list'` renders a vertical, full-width "Ideas for you" list where each row is left-aligned with a leading `icon`, a label, and a hover background. */
1634
+ layout?: "chips" | "list";
1614
1635
  /** Full-width left-aligned rows instead of pills. */
1615
1636
  block?: boolean;
1616
1637
  /** Substring to highlight within each suggestion. */
@@ -1627,7 +1648,7 @@ export const Suggestions = /*#__PURE__*/ createWebComponent<SuggestionsProps>(
1627
1648
  );
1628
1649
 
1629
1650
  export interface SwitchProps extends WebComponentProps {
1630
- /** Controlled checked state settable and reflected to the `checked` attribute. `el.checked = true` (or `<kai-switch checked>`) drives it; the toggle UI updates it and fires `kai-change`. Read `el.checked` for live state. */
1651
+ /** Controlled checked state. Settable and reflected to the `checked` attribute. `el.checked = true` (or `<kai-switch checked>`) drives it; the toggle UI updates it and fires `kai-change`. Read `el.checked` for live state. */
1631
1652
  checked?: boolean;
1632
1653
  /** Initial checked state on mount (uncontrolled seed). Bare attribute (`<kai-switch default-checked>`) turns it on. */
1633
1654
  defaultChecked?: boolean;
@@ -1676,7 +1697,7 @@ export const Tabs = /*#__PURE__*/ createWebComponent<TabsProps>(
1676
1697
 
1677
1698
  export interface TasksProps extends WebComponentProps {
1678
1699
  /** The tasks definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { tasks:[…], selectAll, confirmLabel, … }`. Import `TasksCardData` from `@kitn.ai/ui` for the full shape. */
1679
- data?: Record<string, unknown>;
1700
+ data?: { mode?: "select" | "progress"; heading?: string; tasks: { id: string; label: string; description?: string; checked?: boolean; disabled?: boolean }[]; selectAll?: boolean; confirmLabel?: string; allowEmpty?: boolean; min?: number; max?: number; dismissible?: boolean };
1680
1701
  /** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
1681
1702
  cardId?: string;
1682
1703
  /** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
@@ -1691,7 +1712,7 @@ export interface TasksProps extends WebComponentProps {
1691
1712
  disabled?: boolean;
1692
1713
  /** Display-only: rows can't be toggled and show the default cursor (no pointer, hover, or focus affordances). Keeps the look as-is. Attribute: `readonly`. */
1693
1714
  readonly?: boolean;
1694
- /** The selection changed on a toggle the selected ids in input order. */
1715
+ /** The selection changed on a toggle. Carries the selected ids in input order. */
1695
1716
  onValueChange?: (event: CustomEvent<{ value: string[] }>) => void;
1696
1717
  }
1697
1718
 
@@ -1739,12 +1760,12 @@ export const ThinkingBar = /*#__PURE__*/ createWebComponent<ThinkingBarProps>(
1739
1760
  );
1740
1761
 
1741
1762
  export interface ThreadProps extends WebComponentProps {
1742
- /** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions/avatar. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). */
1743
- messages?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" }[];
1744
- /** Show a typing indicator on the pending assistant turn set while awaiting the assistant's reply. */
1763
+ /** The full message thread to render, newest last. Each entry carries its role, ordered `parts`, and optional actions/avatar/feedback. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). */
1764
+ messages?: { id: string; role: "user" | "assistant"; parts: ({ type: "text"; text: string; raw?: { source: string; payload: unknown } } | { type: "reasoning"; text: string; label?: string; index?: number; streamId?: string; signature?: string; raw?: { source: string; payload: unknown } } | { type: "tool"; tool: { type: string; kind?: "command" | "file-change" | "search" | "fetch" | "mcp" | "image" | "generic"; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; rawInput?: string; output?: Record<string, unknown>; toolCallId?: string; errorText?: string; raw?: { source: string; payload: unknown } }; raw?: { source: string; payload: unknown } } | { type: "card"; envelope: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }; raw?: { source: string; payload: unknown } } | { type: "source"; source: { id?: string; url?: string; title?: string; snippet?: string; index?: number }; raw?: { source: string; payload: unknown } } | { type: "file"; attachment: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }; raw?: { source: string; payload: unknown } })[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" }[];
1765
+ /** Show a typing indicator on the pending assistant turn. Set it while awaiting the assistant's reply. */
1745
1766
  loading?: boolean;
1746
1767
  /** Body/prose font scale for rendered markdown (`'xs' | 'sm' | 'base' | 'lg'`). Defaults to `'sm'`. */
1747
- proseSize?: "sm" | "lg" | "xs" | "base";
1768
+ proseSize?: "xs" | "sm" | "base" | "lg";
1748
1769
  /** Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). */
1749
1770
  codeTheme?: string;
1750
1771
  /** Enable Shiki syntax highlighting in code blocks. Turn off to render plain `<pre>` blocks (lighter, no highlighter load). Default true. */
@@ -1755,20 +1776,24 @@ export interface ThreadProps extends WebComponentProps {
1755
1776
  scrollButton?: boolean;
1756
1777
  /** Extra classes applied to the thread's inner root. */
1757
1778
  class?: string;
1779
+ /** Optional card type -> custom-element tag overrides/additions for `card` parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
1780
+ cardTypes?: Record<string, string>;
1781
+ /** JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `"type"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one. */
1782
+ cardSchemas?: Record<string, object>;
1758
1783
  /** A message's action button was clicked. `action` is the built-in name (`copy` / `like` / `dislike` / `regenerate` / `edit`) or a custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
1759
1784
  onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
1760
1785
  }
1761
1786
 
1762
1787
  export const Thread = /*#__PURE__*/ createWebComponent<ThreadProps>(
1763
1788
  'kai-thread',
1764
- ["theme","messages","loading","proseSize","codeTheme","codeHighlight","actionsReveal","scrollButton","class"],
1789
+ ["theme","messages","loading","proseSize","codeTheme","codeHighlight","actionsReveal","scrollButton","class","cardTypes","cardSchemas"],
1765
1790
  { onMessageAction: 'kai-message-action' },
1766
1791
  () => import('@kitn.ai/ui/elements/thread'),
1767
1792
  );
1768
1793
 
1769
1794
  export interface ToastRegionProps extends WebComponentProps {
1770
- /** The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. */
1771
- toasts: { id: string; message: string; variant?: undefined | "error" | "info" | "success" | "warning" | "neutral"; appearance?: undefined | "pill" | "card"; inverse?: undefined | boolean; description?: undefined | string; action?: undefined | { label: string; onAction: () => void | false }; duration?: undefined | number; dismissible?: undefined | boolean; target?: undefined | HTMLElement }[];
1795
+ /** The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. Omit for an empty region, which is the normal resting state and how the imperative `toast()` API starts. */
1796
+ toasts?: { id: string; message: string; variant?: "neutral" | "success" | "warning" | "error" | "info"; appearance?: "pill" | "card"; inverse?: boolean; description?: string; action?: { label: string; onAction: () => void | false }; duration?: number; dismissible?: boolean; target?: HTMLElement }[];
1772
1797
  /** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
1773
1798
  position?: "top-center" | "top-right" | "top-left" | "bottom-center" | "bottom-right" | "bottom-left";
1774
1799
  /** Max simultaneously-visible toasts; the rest queue. Defaults to `3`. */
@@ -1784,7 +1809,7 @@ export interface ToastRegionProps extends WebComponentProps {
1784
1809
  /** A toast's action button was pressed. */
1785
1810
  onAction?: (event: CustomEvent<{ id: string; label: string }>) => void;
1786
1811
  /** A toast left the stack. `reason` is `'timeout' | 'close' | 'action'`. */
1787
- onDismiss?: (event: CustomEvent<{ id: string; reason: "action" | "timeout" | "close" }>) => void;
1812
+ onDismiss?: (event: CustomEvent<{ id: string; reason: "timeout" | "close" | "action" }>) => void;
1788
1813
  }
1789
1814
 
1790
1815
  export const ToastRegion = /*#__PURE__*/ createWebComponent<ToastRegionProps>(
@@ -1796,12 +1821,12 @@ export const ToastRegion = /*#__PURE__*/ createWebComponent<ToastRegionProps>(
1796
1821
 
1797
1822
  export interface ToolProps extends WebComponentProps {
1798
1823
  /** The tool-call to display. Set as a JS property. */
1799
- tool?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string };
1824
+ tool?: { type: string; kind?: "command" | "file-change" | "search" | "fetch" | "mcp" | "image" | "generic"; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; rawInput?: string; output?: Record<string, unknown>; toolCallId?: string; errorText?: string; raw?: { source: string; payload: unknown } };
1800
1825
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages on trigger click). Set `el.open = true`, or `<kai-tool open>`; listen for `kai-open-change`. */
1801
1826
  open?: boolean;
1802
1827
  /** Initial open state on mount (uncontrolled seed). */
1803
1828
  defaultOpen?: boolean;
1804
- /** Gate the disclosure trigger programmatic `show()/hide()/toggle()` still work, but the trigger click no longer toggles. */
1829
+ /** Gate the disclosure trigger: programmatic `show()/hide()/toggle()` still work, but the trigger click no longer toggles. */
1805
1830
  disabled?: boolean;
1806
1831
  /** The panel expanded or collapsed (by trigger click or a method). */
1807
1832
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
@@ -1841,7 +1866,7 @@ export const Tooltip = /*#__PURE__*/ createWebComponent<TooltipProps>(
1841
1866
  );
1842
1867
 
1843
1868
  export interface VoiceInputProps extends WebComponentProps {
1844
- /** Transcriber the host supplies records audio, returns the text. This is a **function-valued property** (`el.transcribe = async blob => '...'`) because a value-returning callback can't be modelled as a fire-and-forget event. */
1869
+ /** Transcriber the host supplies: records audio, returns the text. This is a **function-valued property** (`el.transcribe = async blob => '...'`) because a value-returning callback can't be modelled as a fire-and-forget event. */
1845
1870
  transcribe?: (audio: Blob) => Promise<string>;
1846
1871
  /** Disable the mic button (non-interactive). */
1847
1872
  disabled?: boolean;
@@ -1849,13 +1874,13 @@ export interface VoiceInputProps extends WebComponentProps {
1849
1874
  recognitionLang?: string;
1850
1875
  /** Emit live partial transcripts (`kai-transcript-interim`) during native recognition. Attribute: `interim`. No-op on the transcribe/fallback paths. */
1851
1876
  interim?: boolean;
1852
- /** Raw audio captured (before transcription) for hosts that prefer to handle transcription themselves instead of via the `transcribe` property. Also the unsupported-fallback signal: no `transcribe`, no SpeechRecognition, so only the blob is produced (no text). */
1877
+ /** Raw audio captured (before transcription), for hosts that prefer to handle transcription themselves instead of via the `transcribe` property. Also the unsupported-fallback signal: no `transcribe`, no SpeechRecognition, so only the blob is produced (no text). */
1853
1878
  onAudioCaptured?: (event: CustomEvent<{ blob: Blob }>) => void;
1854
- /** Recording started or stopped lets the host drive its own UI (waveform, push-to-talk indicator) in sync with the mic. Fires on real transitions only (manual click and programmatic start()/stop()), never on mount. */
1879
+ /** Recording started or stopped. Lets the host drive its own UI (waveform, push-to-talk indicator) in sync with the mic. Fires on real transitions only (manual click and programmatic start()/stop()), never on mount. */
1855
1880
  onRecordingChange?: (event: CustomEvent<{ recording: boolean }>) => void;
1856
1881
  /** Live partial transcript during native recognition (only when `interim` is set). Fires repeatedly before the final `kai-transcription`. */
1857
1882
  onTranscriptInterim?: (event: CustomEvent<{ text: string }>) => void;
1858
- /** Final transcript the `transcribe` property resolved, OR native `SpeechRecognition` produced final text (no `transcribe` set). */
1883
+ /** Final transcript: the `transcribe` property resolved, OR native `SpeechRecognition` produced final text (no `transcribe` set). */
1859
1884
  onTranscription?: (event: CustomEvent<{ text: string }>) => void;
1860
1885
  }
1861
1886
 
@@ -1871,13 +1896,13 @@ export interface VoiceOutputProps extends WebComponentProps {
1871
1896
  text?: string;
1872
1897
  /** Speak automatically when `text` is set/changed. */
1873
1898
  autoplay?: boolean;
1874
- /** TTS model seam the host supplies given text, returns an audio `Blob` to play. This is a **function-valued property** (`el.synthesize = async text => blob`); when set, the native `speechSynthesis` path is bypassed. Mirrors `<kai-voice-input>`'s `transcribe`. A value-returning callback can't be modelled as a fire-and-forget event, hence a property. */
1899
+ /** TTS model seam the host supplies: given text, returns an audio `Blob` to play. This is a **function-valued property** (`el.synthesize = async text => blob`); when set, the native `speechSynthesis` path is bypassed. Mirrors `<kai-voice-input>`'s `transcribe`. A value-returning callback can't be modelled as a fire-and-forget event, hence a property. */
1875
1900
  synthesize?: (text: string) => Promise<Blob>;
1876
1901
  /** Disable the button (non-interactive). */
1877
1902
  disabled?: boolean;
1878
- /** Playback started or stopped drive your own UI in sync. Fires on real transitions only (manual click and programmatic speak()/stop()), never on mount. */
1903
+ /** Playback started or stopped. Drive your own UI in sync. Fires on real transitions only (manual click and programmatic speak()/stop()), never on mount. */
1879
1904
  onSpeakingChange?: (event: CustomEvent<{ speaking: boolean }>) => void;
1880
- /** The model path (`synthesize`) resolved audio the raw `Blob` before playback. */
1905
+ /** The model path (`synthesize`) resolved audio: the raw `Blob` before playback. */
1881
1906
  onSynthesized?: (event: CustomEvent<{ blob: Blob }>) => void;
1882
1907
  }
1883
1908
 
@@ -1889,20 +1914,20 @@ export const VoiceOutput = /*#__PURE__*/ createWebComponent<VoiceOutputProps>(
1889
1914
  );
1890
1915
 
1891
1916
  export interface WorkspaceProps extends WebComponentProps {
1892
- /** Pre-bucketed conversation groups for the sidebar. Set as a JS property. */
1893
- groups: { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[];
1894
- /** Flat conversation list (auto-bucketed if `groups` is empty). Set as a JS property. */
1895
- conversations: { id: string; title: string; groupId?: undefined | string; scope: { type: "document" | "collection"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[];
1917
+ /** The sidebar's section headers, rendered in array order. A group carries no conversations of its own; it is matched against `conversations` by id, so the two props are complementary rather than alternatives. Omit for an ungrouped sidebar. Set as a JS property. */
1918
+ groups?: { id: string; userId?: string; teamId?: string; name: string; sortOrder: number; createdAt: string }[];
1919
+ /** Every conversation in the sidebar, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing ungrouped section (headerless when `compact`), so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit for an empty sidebar, or when `no-conversations` replaces the built-in list with your own `sidebar-header` content. */
1920
+ conversations?: { id: string; title: string; groupId?: string; scope: { type: "document" | "collection"; documentId?: string; filters?: { tags?: string[]; authors?: string[]; contentType?: "transcript" | "markdown"; dateRange?: { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: string }[];
1896
1921
  /** Id of the open conversation, highlighted in the sidebar. */
1897
1922
  activeId?: string;
1898
- /** The active conversation's message thread, newest last. Set as a JS property. */
1899
- messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
1923
+ /** The active conversation's message thread, newest last. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). Omit for an empty thread. */
1924
+ messages?: { id: string; role: "user" | "assistant"; parts: ({ type: "text"; text: string; raw?: { source: string; payload: unknown } } | { type: "reasoning"; text: string; label?: string; index?: number; streamId?: string; signature?: string; raw?: { source: string; payload: unknown } } | { type: "tool"; tool: { type: string; kind?: "command" | "file-change" | "search" | "fetch" | "mcp" | "image" | "generic"; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; rawInput?: string; output?: Record<string, unknown>; toolCallId?: string; errorText?: string; raw?: { source: string; payload: unknown } }; raw?: { source: string; payload: unknown } } | { type: "card"; envelope: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }; raw?: { source: string; payload: unknown } } | { type: "source"; source: { id?: string; url?: string; title?: string; snippet?: string; index?: number }; raw?: { source: string; payload: unknown } } | { type: "file"; attachment: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }; raw?: { source: string; payload: unknown } })[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" }[];
1900
1925
  value?: string;
1901
1926
  placeholder?: string;
1902
1927
  loading?: boolean;
1903
1928
  suggestions?: string[];
1904
1929
  suggestionMode?: "submit" | "fill";
1905
- proseSize?: "sm" | "lg" | "xs" | "base";
1930
+ proseSize?: "xs" | "sm" | "base" | "lg";
1906
1931
  codeTheme?: string;
1907
1932
  codeHighlight?: boolean;
1908
1933
  chatTitle?: string;
@@ -1932,6 +1957,10 @@ export interface WorkspaceProps extends WebComponentProps {
1932
1957
  compact?: boolean;
1933
1958
  /** Suppress the built-in ConversationList so the `sidebar-header` slot owns the whole rail flex region (for apps that supply their own rail nav). Default false. Attribute: `no-conversations`. */
1934
1959
  noConversations?: boolean;
1960
+ /** Optional card type -> custom-element tag overrides/additions for `card` parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
1961
+ cardTypes?: Record<string, string>;
1962
+ /** JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `"type"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one. */
1963
+ cardSchemas?: Record<string, object>;
1935
1964
  /** A conversation was selected in the sidebar. */
1936
1965
  onConversationSelect?: (event: CustomEvent<{ id: string }>) => void;
1937
1966
  /** An action button on a message was clicked. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
@@ -1956,7 +1985,7 @@ export interface WorkspaceProps extends WebComponentProps {
1956
1985
 
1957
1986
  export const Workspace = /*#__PURE__*/ createWebComponent<WorkspaceProps>(
1958
1987
  'kai-workspace',
1959
- ["theme","groups","conversations","activeId","messages","value","placeholder","loading","suggestions","suggestionMode","proseSize","codeTheme","codeHighlight","chatTitle","models","currentModel","context","scrollButton","search","voice","triggers","kindIcons","sidebarWidth","sidebarMinWidth","sidebarMaxWidth","sidebarCollapsed","defaultSidebarCollapsed","collapseBelow","compact","noConversations"],
1988
+ ["theme","groups","conversations","activeId","messages","value","placeholder","loading","suggestions","suggestionMode","proseSize","codeTheme","codeHighlight","chatTitle","models","currentModel","context","scrollButton","search","voice","triggers","kindIcons","sidebarWidth","sidebarMinWidth","sidebarMaxWidth","sidebarCollapsed","defaultSidebarCollapsed","collapseBelow","compact","noConversations","cardTypes","cardSchemas"],
1960
1989
  { onConversationSelect: 'kai-conversation-select', onMessageAction: 'kai-message-action', onModelChange: 'kai-model-change', onNewChat: 'kai-new-chat', onSearch: 'kai-search', onSidebarToggle: 'kai-sidebar-toggle', onSubmit: 'kai-submit', onSuggestionClick: 'kai-suggestion-click', onValueChange: 'kai-value-change', onVoice: 'kai-voice' },
1961
1990
  () => import('@kitn.ai/ui/elements/chat-workspace'),
1962
1991
  );