@kitn.ai/ui 0.20.1 → 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 +5446 -4937
  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 +61 -8
  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
@@ -20,21 +20,29 @@ function useSourceContext() {
20
20
  // --- Source (Root) ---
21
21
 
22
22
  export interface SourceProps {
23
- href: string;
23
+ /** The citation's URL. OPTIONAL: every field of a model-produced citation is,
24
+ * so a source can arrive with a title and no url. In that case the chip
25
+ * renders as a plain, inert `<a>` with NO `href` attribute — which is valid
26
+ * HTML and simply not a link — rather than `<a href="">`, which would
27
+ * navigate to the current page. */
28
+ href?: string;
24
29
  children: JSX.Element;
25
30
  }
26
31
 
27
32
  function Source(props: SourceProps) {
33
+ const href = () => props.href ?? '';
28
34
  const domain = () => {
35
+ const h = href();
36
+ if (!h) return '';
29
37
  try {
30
- return new URL(props.href).hostname;
38
+ return new URL(h).hostname;
31
39
  } catch {
32
- return props.href.split('/').pop() || props.href;
40
+ return h.split('/').pop() || h;
33
41
  }
34
42
  };
35
43
 
36
44
  return (
37
- <SourceContext.Provider value={{ get href() { return props.href; }, get domain() { return domain(); } }}>
45
+ <SourceContext.Provider value={{ get href() { return href(); }, get domain() { return domain(); } }}>
38
46
  <HoverCardRoot openDelay={150}>
39
47
  {props.children}
40
48
  </HoverCardRoot>
@@ -57,7 +65,8 @@ function SourceTrigger(props: SourceTriggerProps) {
57
65
  return (
58
66
  <HoverCardTrigger>
59
67
  <a
60
- href={ctx.href}
68
+ // `undefined` OMITS the attribute — see SourceProps.href.
69
+ href={ctx.href || undefined}
61
70
  target="_blank"
62
71
  rel="noopener noreferrer"
63
72
  class={cn(
@@ -66,7 +75,8 @@ function SourceTrigger(props: SourceTriggerProps) {
66
75
  props.class
67
76
  )}
68
77
  >
69
- <Show when={props.showFavicon}>
78
+ {/* No url, no favicon to look up. */}
79
+ <Show when={props.showFavicon && ctx.href}>
70
80
  <img
71
81
  src={`https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(ctx.href)}`}
72
82
  alt="favicon"
@@ -94,27 +104,35 @@ function SourceContent(props: SourceContentProps) {
94
104
  return (
95
105
  <HoverCardContent class={cn('w-80 p-0 shadow-xs', props.class)}>
96
106
  <a
97
- href={ctx.href}
107
+ // `undefined` OMITS the attribute — see SourceProps.href.
108
+ href={ctx.href || undefined}
98
109
  target="_blank"
99
110
  rel="noopener noreferrer"
100
111
  class="flex flex-col gap-2 p-3"
101
112
  >
102
- <div class="flex items-center gap-1.5">
103
- <img
104
- src={`https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(ctx.href)}`}
105
- alt="favicon"
106
- class="size-4 rounded-full"
107
- width={16}
108
- height={16}
109
- />
110
- <div class="text-primary truncate text-sm">
111
- {ctx.domain.replace('www.', '')}
113
+ {/* The domain header row only means anything when there IS a url. */}
114
+ <Show when={ctx.href}>
115
+ <div class="flex items-center gap-1.5">
116
+ <img
117
+ src={`https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(ctx.href)}`}
118
+ alt="favicon"
119
+ class="size-4 rounded-full"
120
+ width={16}
121
+ height={16}
122
+ />
123
+ <div class="text-primary truncate text-sm">
124
+ {ctx.domain.replace('www.', '')}
125
+ </div>
112
126
  </div>
113
- </div>
114
- <div class="line-clamp-2 text-sm font-medium">{props.title}</div>
115
- <div class="text-muted-foreground line-clamp-2 text-sm">
116
- {props.description}
117
- </div>
127
+ </Show>
128
+ <Show when={props.title}>
129
+ <div class="line-clamp-2 text-sm font-medium">{props.title}</div>
130
+ </Show>
131
+ <Show when={props.description}>
132
+ <div class="text-muted-foreground line-clamp-2 text-sm">
133
+ {props.description}
134
+ </div>
135
+ </Show>
118
136
  </a>
119
137
  </HoverCardContent>
120
138
  );
@@ -122,8 +140,16 @@ function SourceContent(props: SourceContentProps) {
122
140
 
123
141
  // --- SourceList (convenience) ---
124
142
 
125
- function SourceList(props: { children: JSX.Element; class?: string }) {
126
- return <div class={cn('flex flex-wrap gap-1.5 mt-3', props.class)}>{props.children}</div>;
143
+ export interface SourceListProps {
144
+ children: JSX.Element;
145
+ class?: string;
146
+ /** `::part` name(s) exposed on the row. The message body passes `"citations"`
147
+ * so consumers can target the citation row from outside the shadow boundary. */
148
+ part?: string;
149
+ }
150
+
151
+ function SourceList(props: SourceListProps) {
152
+ return <div part={props.part} class={cn('flex flex-wrap gap-1.5 mt-3', props.class)}>{props.children}</div>;
127
153
  }
128
154
 
129
155
  export { Source, SourceTrigger, SourceContent, SourceList };
@@ -24,42 +24,19 @@ import { useCardHost } from '../primitives/card-host';
24
24
  import { Check, Circle, CircleCheck, X } from 'lucide-solid';
25
25
 
26
26
  // ─────────────────────────────────────────────────────────────────────────────
27
- // Types (tasks.schema.json) — see src/primitives/card-schemas/tasks.schema.json
27
+ // Types (tasks.schema.json) — AUTHORED IN ../primitives/card-data-types.ts.
28
+ // See the note in confirm-card.tsx, or that file's header, for why they left a
29
+ // `.tsx` and why they are `type` aliases. Re-exported here unchanged.
28
30
  // ─────────────────────────────────────────────────────────────────────────────
29
31
 
30
- export interface TasksTask {
31
- id: string;
32
- label: string;
33
- description?: string;
34
- checked?: boolean;
35
- disabled?: boolean;
36
- }
37
-
38
- export interface TasksCardData {
39
- /**
40
- * `select` (default) = checkbox rows + a confirm button that emits the contract
41
- * `submit`. `progress` = an onboarding/checklist look: a header `done / total`
42
- * count, circular indicators, per-item title + muted description, and NO confirm
43
- * button (checking a row is itself the terminal action). Both share the same
44
- * selection model (toggle by id, the `max` gate, `kai-value-change`); `progress`
45
- * is purely a presentational variant.
46
- */
47
- mode?: 'select' | 'progress';
48
- heading?: string;
49
- tasks: TasksTask[]; // >=1
50
- selectAll?: boolean;
51
- confirmLabel?: string;
52
- allowEmpty?: boolean;
53
- min?: number;
54
- max?: number;
55
- dismissible?: boolean; // show a close affordance that emits `dismiss`
56
- }
57
-
58
- export interface TasksCardResult {
59
- selected: string[];
60
- }
32
+ import type { TasksCardData, TasksCardResult, TasksTask } from '../primitives/card-data-types';
61
33
 
62
- export type TasksCardEnvelope = CardEnvelope<'tasks', TasksCardData>;
34
+ export type {
35
+ TasksCardData,
36
+ TasksCardEnvelope,
37
+ TasksCardResult,
38
+ TasksTask,
39
+ } from '../primitives/card-data-types';
63
40
 
64
41
  export const TASKS_CARD_TYPE = 'tasks' as const;
65
42
 
@@ -1,4 +1,4 @@
1
- import { For, Show, onMount, type JSX } from 'solid-js';
1
+ import { For, Show, createMemo, onMount, type JSX } from 'solid-js';
2
2
  import { ChatConfig, useChatConfig } from '../primitives/chat-config';
3
3
  import { ChatContainer, ChatContainerContent, ChatContainerScrollAnchor } from './chat-container';
4
4
  import { Message, MessageAvatar, MessageBody } from './message';
@@ -7,6 +7,8 @@ import { ScrollButton } from './scroll-button';
7
7
  import { Loader } from './loader';
8
8
  import type { ChatMessage } from '../elements/chat-types';
9
9
  import type { ProseSize } from '../primitives/chat-config';
10
+ import type { CardComponentMap } from '../primitives/card-registry';
11
+ import type { CardSchemaMap } from './card-renderer';
10
12
 
11
13
  /** Imperative handle exposed via `controllerRef` — the thread's scroll control,
12
14
  * forwarded onto `<kai-thread>` as the `scrollToBottom()` instance method. */
@@ -19,9 +21,19 @@ export interface ThreadProps {
19
21
  /** Extra classes for the thread root (e.g. `rounded-xl`). */
20
22
  class?: string;
21
23
  /** The full message thread to render, newest last. Each entry carries its role,
22
- * content, and optional reasoning/tools/attachments/actions/avatar. A new array
23
- * reference per streaming chunk re-renders (mutating in place does not). */
24
+ * ordered `parts`, and optional actions/avatar/feedback. A new array reference
25
+ * per streaming chunk re-renders (mutating in place does not). */
24
26
  messages: ChatMessage[];
27
+ /** Add/override card type -> component entries, forwarded to `CardRenderer`
28
+ * for `card` parts. */
29
+ cardTypes?: CardComponentMap;
30
+ /** JSON Schemas for the card types this app renders, keyed by envelope type,
31
+ * forwarded to `CardRenderer` for `card` parts. The companion of `cardTypes`:
32
+ * that says what DRAWS a card, this says what a VALID one looks like.
33
+ * `createCardRegistry(...).validationSchemas` is exactly this shape. Without it
34
+ * the kit checks its own seven built-ins and leaves your own card type
35
+ * unvalidated. A schema here WINS over a built-in of the same name. */
36
+ cardSchemas?: CardSchemaMap;
25
37
  /** Show a typing indicator on the pending assistant turn — use while awaiting
26
38
  * the assistant's reply. */
27
39
  loading?: boolean;
@@ -85,6 +97,11 @@ export function Thread(props: ThreadProps) {
85
97
  });
86
98
  const showScrollButton = () => props.scrollButton !== false;
87
99
  const showEmpty = () => props.messages.length === 0 && !props.loading;
100
+ // Keyed by message id, NOT by object reference: a streaming message is a new
101
+ // object every delta, and a reference-keyed <For> rebuilds the whole row for
102
+ // each one — which is why expanding a tool/reasoning panel mid-stream used to
103
+ // do nothing. Full rationale (and why not `<Index>`) in `chat-thread.tsx`.
104
+ const messageKeys = createMemo(() => props.messages.map((m) => m.id));
88
105
 
89
106
  // Hand the imperative controller to the facade once mounted (rootEl is set).
90
107
  onMount(() => {
@@ -116,46 +133,71 @@ export function Thread(props: ThreadProps) {
116
133
  {props.empty}
117
134
  </Show>
118
135
  </Show>
119
- <For each={props.messages}>
120
- {(m) => {
121
- const body = (
122
- <MessageBody
123
- content={m.content}
124
- reasoning={m.reasoning}
125
- tools={m.tools}
126
- attachments={m.attachments}
127
- isUser={m.role === 'user'}
128
- markdown={m.role === 'assistant'}
129
- actions={m.actions}
130
- actionsReveal={reveal()}
131
- activeFeedback={feedback.resolveFeedback(m)}
132
- copied={feedback.isCopied(m.id)}
133
- onAction={(action) => feedback.handleAction(m, action)}
134
- />
135
- );
136
- const rowGroup = reveal() === 'hover' ? 'group ' : '';
137
- return (
138
- <Show
139
- when={m.avatar}
140
- fallback={
141
- <Message class={`${rowGroup}${m.role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
142
- {body}
143
- </Message>
144
- }
145
- >
146
- {(av) => (
147
- <Message class={rowGroup}>
148
- <MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
149
- <div class={`flex min-w-0 flex-1 flex-col ${m.role === 'user' ? 'items-end' : 'items-start'}`}>
150
- {body}
151
- </div>
152
- </Message>
153
- )}
154
- </Show>
155
- );
156
- }}
136
+ <For each={messageKeys()}>
137
+ {(_id, i) => (
138
+ // Read the message through <For>'s index accessor, never through
139
+ // a captured value — the row outlives the delta that replaced its
140
+ // object. <Show> supplies the non-null accessor and covers the
141
+ // frame where a removal has shortened the array.
142
+ <Show when={props.messages[i()]}>
143
+ {(m) => {
144
+ const body = (
145
+ <MessageBody
146
+ parts={m().parts}
147
+ cardTypes={props.cardTypes}
148
+ cardSchemas={props.cardSchemas}
149
+ isUser={m().role === 'user'}
150
+ markdown={m().role === 'assistant'}
151
+ actions={m().actions}
152
+ actionsReveal={reveal()}
153
+ activeFeedback={feedback.resolveFeedback(m())}
154
+ copied={feedback.isCopied(m().id)}
155
+ onAction={(action) => feedback.handleAction(m(), action)}
156
+ />
157
+ );
158
+ const rowGroup = () => (reveal() === 'hover' ? 'group ' : '');
159
+ return (
160
+ // `role` is the SPEAKER, and it has to be forwarded on BOTH
161
+ // branches. `Message` turns it into `role="article"` + an
162
+ // `aria-label` naming the speaker; without it the row is a
163
+ // bare div that chromium prunes from the accessibility tree
164
+ // as "uninteresting", so a screen reader gets no speaker at
165
+ // all. Every other read of `m().role` here is cosmetic
166
+ // (alignment, markdown), which is exactly how it went
167
+ // missing: the value was in hand and used for styling while
168
+ // being dropped for semantics.
169
+ <Show
170
+ when={m().avatar}
171
+ fallback={
172
+ <Message role={m().role} class={`${rowGroup()}${m().role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
173
+ {body}
174
+ </Message>
175
+ }
176
+ >
177
+ {(av) => (
178
+ <Message role={m().role} class={rowGroup()}>
179
+ <MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
180
+ <div class={`flex min-w-0 flex-1 flex-col ${m().role === 'user' ? 'items-end' : 'items-start'}`}>
181
+ {body}
182
+ </div>
183
+ </Message>
184
+ )}
185
+ </Show>
186
+ );
187
+ }}
188
+ </Show>
189
+ )}
157
190
  </For>
158
- {/* Typing indicator on the pending assistant turn. */}
191
+ {/* Typing indicator on the pending assistant turn.
192
+ DELIBERATELY role-less, unlike the rows above — this is not an
193
+ oversight of the same kind. There is no message here yet, so
194
+ `role="assistant"` would announce an empty article named
195
+ "Assistant message". What a pending indicator needs instead is a
196
+ live region, so its ARRIVAL and departure are announced. The
197
+ Loader already carries an accessible name — an sr-only "Loading"
198
+ on all nine shape variants — and what it lacks is the
199
+ `role="status"` / aria-live wrapper around it. A real but
200
+ SEPARATE gap, and it lives in loader.tsx. Filed, not fixed here. */}
159
201
  <Show when={props.loading}>
160
202
  <Message class="flex-col items-start">
161
203
  <div class="rounded-lg px-1 py-2">
@@ -59,7 +59,7 @@ function usePrefersReducedMotion() {
59
59
 
60
60
  // ── Single toast pill ────────────────────────────────────────────────────────
61
61
 
62
- interface ToastProps {
62
+ export interface ToastProps {
63
63
  item: ToastItem;
64
64
  onDismiss: (reason: ToastDismissReason) => void;
65
65
  onAction?: (label: string) => void;
@@ -388,6 +388,12 @@ export function ToastRegion(props: ToastRegionProps) {
388
388
  createEffect(() => {
389
389
  const t = props.target;
390
390
  if (!t || typeof window === 'undefined') { setAnchor(null); return; }
391
+ // Captured at SETUP and closed over, never re-resolved as a global inside
392
+ // `onCleanup`: cleanup can run after the host removed the DOM globals (a
393
+ // `kai-*` release is deferred one microtask past detachment, so an
394
+ // environment teardown gets in between), and a bare `window` there throws.
395
+ // See tests/components/teardown-without-dom-globals.test.tsx.
396
+ const win = window;
391
397
  const update = () => {
392
398
  const r = t.getBoundingClientRect();
393
399
  setAnchor({ top: r.top, left: r.left, right: r.right, bottom: r.bottom, width: r.width });
@@ -395,12 +401,12 @@ export function ToastRegion(props: ToastRegionProps) {
395
401
  update();
396
402
  const ro = new ResizeObserver(update);
397
403
  ro.observe(t);
398
- window.addEventListener('scroll', update, true);
399
- window.addEventListener('resize', update);
404
+ win.addEventListener('scroll', update, true);
405
+ win.addEventListener('resize', update);
400
406
  onCleanup(() => {
401
407
  ro.disconnect();
402
- window.removeEventListener('scroll', update, true);
403
- window.removeEventListener('resize', update);
408
+ win.removeEventListener('scroll', update, true);
409
+ win.removeEventListener('resize', update);
404
410
  });
405
411
  });
406
412
 
@@ -0,0 +1,26 @@
1
+ /** Semantic classification of a tool call, used to pick a rendering. Derived from
2
+ * the provider-chosen tool NAME, which is arbitrary, so this stays conservative and
3
+ * prefers 'generic' over a confident wrong answer. */
4
+ export type ToolKind =
5
+ | 'command'
6
+ | 'file-change'
7
+ | 'search'
8
+ | 'fetch'
9
+ | 'mcp'
10
+ | 'image'
11
+ | 'generic';
12
+
13
+ /** Total, deterministic, side-effect free. ALWAYS terminates in 'generic' so an
14
+ * unrecognized tool still renders a panel instead of a blank. Order matters:
15
+ * 'search' is tested before 'fetch' so `web_search` classifies as a search. */
16
+ export function classifyTool(name: string): ToolKind {
17
+ const n = name.toLowerCase();
18
+ if (!n) return 'generic';
19
+ if (n.includes('bash') || n.includes('command') || n.includes('shell') || n.includes('terminal') || n.includes('exec')) return 'command';
20
+ if (n.includes('edit') || n.includes('write') || n.includes('patch') || n.includes('replace') || n.includes('delete')) return 'file-change';
21
+ if (n.includes('search') || n.includes('grep') || n.includes('glob') || n.includes('find')) return 'search';
22
+ if (n.includes('fetch') || n.includes('http') || n.includes('browse') || n.includes('crawl')) return 'fetch';
23
+ if (n.includes('mcp')) return 'mcp';
24
+ if (n.includes('image') || n.includes('screenshot') || n.includes('vision')) return 'image';
25
+ return 'generic';
26
+ }
@@ -1,10 +1,40 @@
1
+ import type { ToolKind } from './tool-classify';
2
+
3
+ /** The untranslated provider payload a part was normalized from.
4
+ *
5
+ * Optional in the type but REQUIRED in practice for round-trip fidelity. Anthropic
6
+ * returns a 400 invalid_request_error if `thinking` blocks are modified, reordered,
7
+ * filtered or RECONSTRUCTED, so an encoder must send `raw.payload` back verbatim
8
+ * rather than rebuilding a block from `text` + `signature`. */
9
+ export interface RawOrigin {
10
+ /** Tagged origin, e.g. 'anthropic.content_block', 'openai.delta', `custom.${string}`. */
11
+ source: string;
12
+ payload: unknown;
13
+ }
14
+
1
15
  /** A tool-call part rendered by <Tool>. Pure type — kept JSX-free so it can be
2
- * imported by the framework-neutral state core and the React typecheck pass. */
16
+ * imported by the framework-neutral state core and the React typecheck pass.
17
+ *
18
+ * Adding a field here also requires adding it to `TOOL_KEYS` (and a comparator
19
+ * in `TOOL_COMPARATORS`) in `state/parts.ts`, or `tsc` fails to compile: those
20
+ * drive `upsertToolPart`'s dedupe check, and a field missing from them would
21
+ * silently make that check ignore the new field, keeping a stale array
22
+ * reference alive when only that field changed. */
3
23
  export interface ToolPart {
24
+ /** The tool name exactly as the provider reported it. */
4
25
  type: string;
26
+ /** Semantic classification for rendering. Derive with classifyTool(type). */
27
+ kind?: ToolKind;
5
28
  state: 'input-streaming' | 'input-available' | 'output-available' | 'output-error';
29
+ /** Last VALID parsed snapshot, fingerprint-deduped. The primary channel: this is
30
+ * what the kit renders. */
6
31
  input?: Record<string, unknown>;
32
+ /** Raw accumulated argument fragments, for consumers wanting character-level
33
+ * streaming. Most consumers should read `input` instead. */
34
+ rawInput?: string;
7
35
  output?: Record<string, unknown>;
8
36
  toolCallId?: string;
9
37
  errorText?: string;
38
+ /** The untranslated provider payload this was normalized from. */
39
+ raw?: RawOrigin;
10
40
  }
@@ -2,26 +2,26 @@ import { defineWebComponent } from './define';
2
2
  import { AgentCard, type AgentStatus } from '../ui/agent-card';
3
3
 
4
4
  interface Props extends Record<string, unknown> {
5
- /** The agent's name the primary label. Attribute: `name`. */
5
+ /** The agent's name, the primary label. Attribute: `name`. */
6
6
  name?: string;
7
7
  /** Selected / focused state: highlighted border + surface. Attribute: `active`. */
8
8
  active?: boolean;
9
- /** Raise a prominent "Needs you" pill plus a glowing amber edge — the
10
- * attention-routing signal that pulls focus to this agent. Attribute:
11
- * `needs-attention`. */
9
+ /** Raise a prominent "Needs you" pill plus a glowing amber edge. This
10
+ * is the attention-routing signal that pulls focus to this agent.
11
+ * Attribute: `needs-attention`. */
12
12
  needsAttention?: boolean;
13
- /** Run status a JS PROPERTY (object), not an attribute. Shape:
14
- * `{ tone, label?, pulse? }`, where `tone` is one of `working` | `idle` |
15
- * `done` | `error` | `blocked` (maps to the kit's tool hues), `label` is an
16
- * optional short string beside the dot, and `pulse` animates the dot. Set it
17
- * with `el.status = { tone: 'working', label: 'Working', pulse: true }`. */
13
+ /** Run status. A JS PROPERTY (object), not an attribute. Shape: `{ tone,
14
+ * label?, pulse? }`, where `tone` is one of `working` | `idle` | `done` |
15
+ * `error` | `blocked` (maps to the kit's tool hues), `label` is an optional
16
+ * short string beside the dot, and `pulse` animates the dot. Set it with
17
+ * `el.status = { tone: 'working', label: 'Working', pulse: true }`. */
18
18
  status?: AgentStatus;
19
19
  }
20
20
 
21
21
  /** Events fired by `<kai-agent-card>`. */
22
22
  interface Events {
23
- /** The card was activated clicked, or Enter / Space while focused. Promote
24
- * this agent back to focus. */
23
+ /** The card was activated by a click, or by Enter / Space while focused.
24
+ * Promote this agent back to focus. */
25
25
  'kai-activate': void;
26
26
  /** The trailing "..." kebab was clicked. The consumer opens its own menu; the
27
27
  * card only surfaces the affordance (the click does not also activate the card). */
@@ -5,8 +5,10 @@ import { Artifact, type ArtifactController, type ArtifactFile, type ArtifactTab
5
5
  interface Props extends Record<string, unknown> {
6
6
  /** URL the preview iframe frames. Consumer-controlled. */
7
7
  src?: string;
8
- /** Files for the Code tab tree + each file's preview `url`. Set as a JS property (array). */
9
- files: ArtifactFile[];
8
+ /** Files for the Code tab tree + each file's preview `url`. Omit for a
9
+ * preview-only artifact (the Code tab then has nothing to show; pair it with
10
+ * `no-tabs` to hide the toggle). Set as a JS property (array). */
11
+ files?: ArtifactFile[];
10
12
  /** Controlled active tab: `preview` or `code`. When set, the artifact follows it
11
13
  * (re-asserted on change). Leave unset for an uncontrolled tab (see `defaultTab`). */
12
14
  tab?: ArtifactTab;
@@ -14,7 +16,7 @@ interface Props extends Record<string, unknown> {
14
16
  * Seeds the starting tab; the user can then switch freely without the consumer
15
17
  * re-asserting a controlled `tab`. */
16
18
  defaultTab?: ArtifactTab;
17
- /** Selected file path syncs the tree highlight, Code source, and preview. */
19
+ /** Selected file path. Syncs the tree highlight, Code source, and preview. */
18
20
  activeFile?: string;
19
21
  /** iframe `sandbox` override. Secure default `allow-scripts allow-forms` (NOT `allow-same-origin`). */
20
22
  sandbox?: string;
@@ -56,6 +58,12 @@ interface Events extends Record<string, unknown> {
56
58
  'kai-file-select': { path: string };
57
59
  /** Artifact's own maximize button toggled (consumer-observable; non-bubbling). */
58
60
  'kai-maximize-change': { maximized: boolean };
61
+ /** The maximize PROTOCOL intent, raised as a raw bubbling + composed CustomEvent
62
+ * (not through `dispatch`) so an enclosing `<kai-resizable>` can catch it and
63
+ * maximize the containing panel. Declared here so it is typed and reaches the
64
+ * generated API. Listen for it to drive maximize from your own chrome, or
65
+ * re-emit it to trigger one. */
66
+ 'kai-maximize-intent': { requested: boolean };
59
67
  }
60
68
 
61
69
  /**
@@ -106,17 +114,17 @@ defineWebComponent<Props, Events>('kai-artifact', {
106
114
  reload: () => controller?.reload(),
107
115
  /** Navigate to the `src` home url (no-op when there's no `src`). */
108
116
  home: () => controller?.home(),
109
- /** Push + load a url in the preview the path-field submit path (fires kai-navigate). */
117
+ /** Push + load a url in the preview, the path-field submit path (fires kai-navigate). */
110
118
  navigate: (url: string) => controller?.navigate(url),
111
119
  /** Select a file by path: highlights the tree, shows its source, navigates the
112
120
  * preview (fires kai-file-select + kai-navigate). Named selectFile to avoid the
113
121
  * `activeFile` prop. */
114
122
  selectFile: (path: string) => controller?.selectFile(path),
115
123
  /** Open the current url in a new browser tab (no-op when there's no concrete url).
116
- * Named openExternal, NOT openInTab that's a prop (toolbar button visibility). */
124
+ * Named openExternal, NOT openInTab, which is a prop (toolbar button visibility). */
117
125
  openExternal: () => controller?.openExternal(),
118
126
  /** Enter the maximized view-state (fires kai-maximize-change{maximized:true}).
119
- * Named maximize, NOT maximized that's a prop. */
127
+ * Named maximize, NOT maximized, which is a prop. */
120
128
  maximize: () => controller?.maximize(),
121
129
  /** Exit the maximized view-state (fires kai-maximize-change{maximized:false}). */
122
130
  restore: () => controller?.restore(),
@@ -157,7 +165,7 @@ defineWebComponent<Props, Events>('kai-artifact', {
157
165
  >
158
166
  <Artifact
159
167
  src={props.src}
160
- files={props.files}
168
+ files={props.files ?? []}
161
169
  tab={props.tab}
162
170
  defaultTab={props.defaultTab}
163
171
  activeFile={props.activeFile}
@@ -17,8 +17,10 @@ import {
17
17
  } from '../components/attachments';
18
18
 
19
19
  interface Props extends Record<string, unknown> {
20
- /** The attachments to render. Set as a JS property (array). */
21
- items: AttachmentData[];
20
+ /** The attachments to render. Omit (or pass an empty array) for the empty
21
+ * state, which shows `emptyText` if set and nothing otherwise. Set as a JS
22
+ * property (array). */
23
+ items?: AttachmentData[];
22
24
  /** Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. */
23
25
  variant?: AttachmentVariant;
24
26
  /** Wrap each item in a hover card that previews its details. */
@@ -67,11 +69,11 @@ defineWebComponent<Props, Events>('kai-attachments', {
67
69
 
68
70
  return (
69
71
  <Show
70
- when={props.items.length}
72
+ when={props.items?.length}
71
73
  fallback={<Show when={props.emptyText}><AttachmentEmpty>{props.emptyText}</AttachmentEmpty></Show>}
72
74
  >
73
75
  <Attachments variant={variant()}>
74
- <For each={props.items}>
76
+ <For each={props.items ?? []}>
75
77
  {(item) => (
76
78
  <Attachment
77
79
  data={item}
@@ -6,7 +6,7 @@ interface Props extends Record<string, unknown> {
6
6
  src?: string;
7
7
  /** Alt text for the image. Defaults to `fallback`. */
8
8
  alt?: string;
9
- /** Short text shown when there's no image usually initials (e.g. "JD", "AI"). */
9
+ /** Short text shown when there's no image, usually initials (e.g. "JD", "AI"). */
10
10
  fallback?: string;
11
11
  /** Size token: `sm` | `md` (default) | `lg`. */
12
12
  size?: 'sm' | 'md' | 'lg';
@@ -4,7 +4,7 @@ import { renderIcon } from '../ui/icon';
4
4
  import { defineWebComponent } from './define';
5
5
 
6
6
  interface Props extends Record<string, unknown> {
7
- /** Visual style. `default` (filled), `subtle` (muted text, hover tint the
7
+ /** Visual style. `default` (filled), `subtle` (muted text, hover tint, the
8
8
  * toolbar icon look), `ghost` (transparent, hover fill), `outline`, or
9
9
  * `destructive`. Defaults to `default`. */
10
10
  variant?: 'default' | 'subtle' | 'ghost' | 'outline' | 'destructive';
@@ -21,7 +21,7 @@ interface Props extends Record<string, unknown> {
21
21
  label?: string;
22
22
  /** Disable the button (non-interactive, dimmed). */
23
23
  disabled?: boolean;
24
- /** Stretch the button to the full width of its container (a block button)
24
+ /** Stretch the button to the full width of its container (a block button),
25
25
  * e.g. a card CTA or a stacked action. Attribute: `full`. */
26
26
  full?: boolean;
27
27
  /** Justify the button's content: `start`, `center` (default), or `end`.
@@ -82,7 +82,7 @@ defineWebComponent<Props, Events>('kai-button', {
82
82
  element.shadowRoot?.querySelector('button')?.focus(options),
83
83
  /** Blur the inner `<button>`. */
84
84
  blur: () => element.shadowRoot?.querySelector('button')?.blur(),
85
- /** Programmatically activate the button runs the same path as a user
85
+ /** Programmatically activate the button. Runs the same path as a user
86
86
  * click and fires kai-click. Forwarding to the inner button means
87
87
  * `disabled` is respected automatically. */
88
88
  click: () => element.shadowRoot?.querySelector('button')?.click(),
@@ -7,8 +7,8 @@ interface Props extends Record<string, unknown> {
7
7
  * Attribute: `appearance`. */
8
8
  appearance?: CardAppearance;
9
9
  /** `vertical` (default, media on top) | `horizontal` (media at the start) |
10
- * `responsive` (horizontal when the card's container is wide enough, else
11
- * vertical a container query on the card's own width). Attribute: `orientation`. */
10
+ * `responsive` (horizontal when the card's container is wide enough, else vertical,
11
+ * via a container query on the card's own width). Attribute: `orientation`. */
12
12
  orientation?: CardOrientation;
13
13
  /** The card width below which a `responsive` card collapses to vertical and the
14
14
  * footer actions stack. A CSS length; default `28rem`. Attribute: `collapse`. */