@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
@@ -1,73 +1,72 @@
1
1
  // src/state/stream.ts
2
- import type { ChatMessage } from '../elements/chat-types';
2
+ import type { ChatMessage, MessagePart, Source } from '../elements/chat-types';
3
3
  import type { ToolPart } from '../components/tool-types';
4
+ import type { CardEnvelope } from '../primitives/card-contract';
5
+ import type { AttachmentData } from '../components/attachment-types';
6
+ import { appendReasoningPart, appendTextPart, upsertCardPart, upsertToolPart, type ReasoningOpts } from './parts';
4
7
 
5
8
  /** The one universal contract: a functional-updater setter (React setState shape). */
6
9
  export type SetMessages = (updater: (prev: ChatMessage[]) => ChatMessage[]) => void;
7
10
 
11
+ function newId(): string {
12
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID();
13
+ return 'kai-' + Math.random().toString(36).slice(2);
14
+ }
15
+
8
16
  /** A fluent builder for one in-flight assistant message. Owns no state. */
9
17
  export interface AssistantStream {
10
18
  readonly id: string;
11
19
  appendText(delta: string): AssistantStream;
12
- setText(content: string): AssistantStream;
13
- appendReasoning(delta: string, label?: string): AssistantStream;
14
- setReasoning(text: string, label?: string): AssistantStream;
15
- upsertTool(tool: ToolPart): AssistantStream;
16
- updateTool(toolCallId: string, patch: Partial<ToolPart>): AssistantStream;
17
- patch(patch: Partial<ChatMessage>): AssistantStream;
18
- done(final?: Partial<ChatMessage>): void;
20
+ appendReasoning(delta: string, opts?: ReasoningOpts): AssistantStream;
21
+ upsertTool(toolCallId: string, patch: Partial<ToolPart>): AssistantStream;
22
+ /** Adds a card, or REPLACES the existing one with the same `envelope.id`. A
23
+ * model that revises a card mid-turn re-sends the whole envelope, so a second
24
+ * call with a known id revises that card in place rather than rendering a
25
+ * second copy of it. See `upsertCardPart`. */
26
+ addCard(envelope: CardEnvelope): AssistantStream;
27
+ addSource(source: Source): AssistantStream;
28
+ addFile(attachment: AttachmentData): AssistantStream;
29
+ done(): void;
19
30
  abort(reason?: string): void;
20
31
  }
21
32
 
22
- function newId(): string {
23
- if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();
24
- return 'kai-' + Math.random().toString(36).slice(2);
25
- }
26
-
27
33
  /** Start an assistant message and drive it through `set`. New refs on every mutation. */
28
- export function createAssistantStream(set: SetMessages, init: Partial<ChatMessage> = {}): AssistantStream {
34
+ export function createAssistantStream(
35
+ set: SetMessages,
36
+ init: Partial<ChatMessage> = {},
37
+ ): AssistantStream {
29
38
  const id = init.id ?? newId();
30
- const seed: ChatMessage = { id, role: 'assistant', content: '', ...init };
31
- set((prev) => [...prev, seed]);
39
+ let settled = false;
40
+
41
+ set((prev) => [...prev, { id, role: 'assistant', parts: [], ...init }]);
32
42
 
33
- const mutate = (fn: (m: ChatMessage) => ChatMessage) =>
34
- set((prev) => prev.map((m) => (m.id === id ? fn(m) : m)));
43
+ const mutate = (fn: (parts: MessagePart[]) => MessagePart[]) => {
44
+ if (settled) return;
45
+ set((prev) => {
46
+ const i = prev.findIndex((m) => m.id === id);
47
+ if (i < 0) return prev;
48
+ const next = fn(prev[i].parts);
49
+ if (next === prev[i].parts) return prev;
50
+ return [...prev.slice(0, i), { ...prev[i], parts: next }, ...prev.slice(i + 1)];
51
+ });
52
+ };
35
53
 
36
54
  const stream: AssistantStream = {
37
55
  id,
38
- appendText(delta) { mutate((m) => ({ ...m, content: m.content + delta })); return stream; },
39
- setText(content) { mutate((m) => ({ ...m, content })); return stream; },
40
- appendReasoning(delta, label) {
41
- mutate((m) => ({ ...m, reasoning: { text: (m.reasoning?.text ?? '') + delta, label: label ?? m.reasoning?.label } }));
42
- return stream;
43
- },
44
- setReasoning(text, label) {
45
- mutate((m) => ({ ...m, reasoning: { text, label: label ?? m.reasoning?.label } }));
46
- return stream;
47
- },
48
- upsertTool(tool) {
49
- mutate((m) => {
50
- const tools = m.tools ? m.tools.slice() : [];
51
- const i = tool.toolCallId != null
52
- ? tools.findIndex((t) => t.toolCallId === tool.toolCallId)
53
- : tools.findIndex((t) => t.type === tool.type);
54
- if (i === -1) tools.push(tool); else tools[i] = tool;
55
- return { ...m, tools };
56
- });
57
- return stream;
58
- },
59
- updateTool(toolCallId, patch) {
60
- mutate((m) => ({ ...m, tools: (m.tools ?? []).map((t) => (t.toolCallId === toolCallId ? { ...t, ...patch } : t)) }));
61
- return stream;
62
- },
63
- patch(patch) { mutate((m) => ({ ...m, ...patch })); return stream; },
64
- done(final) { if (final) mutate((m) => ({ ...m, ...final })); },
56
+ appendText(delta) { mutate((p) => appendTextPart(p, delta)); return stream; },
57
+ appendReasoning(delta, opts) { mutate((p) => appendReasoningPart(p, delta, opts)); return stream; },
58
+ upsertTool(toolCallId, patch) { mutate((p) => upsertToolPart(p, toolCallId, patch)); return stream; },
59
+ // Upsert, not append: keyed on envelope.id so a revised card replaces itself.
60
+ addCard(envelope) { mutate((p) => upsertCardPart(p, envelope)); return stream; },
61
+ addSource(source) { mutate((p) => [...p, { type: 'source', source }]); return stream; },
62
+ addFile(attachment) { mutate((p) => [...p, { type: 'file', attachment }]); return stream; },
63
+ done() { settled = true; },
65
64
  abort(reason) {
66
- if (reason) {
67
- mutate((m) => ({ ...m, tools: (m.tools ?? []).map((t) => ({ ...t, state: 'output-error' as const, errorText: reason })) }));
68
- } else {
69
- set((prev) => prev.filter((m) => m.id !== id));
70
- }
65
+ mutate((p) => p.map((part) =>
66
+ part.type === 'tool' && part.tool.state !== 'output-available'
67
+ ? { ...part, tool: { ...part.tool, state: 'output-error' as const, errorText: reason } }
68
+ : part));
69
+ settled = true;
71
70
  },
72
71
  };
73
72
  return stream;
@@ -78,14 +77,13 @@ export function createAssistantStream(set: SetMessages, init: Partial<ChatMessag
78
77
  export function onStreamSettled(inner: AssistantStream, onSettle: () => void): AssistantStream {
79
78
  const wrapper: AssistantStream = {
80
79
  id: inner.id,
81
- appendText(d) { inner.appendText(d); return wrapper; },
82
- setText(c) { inner.setText(c); return wrapper; },
83
- appendReasoning(d, l) { inner.appendReasoning(d, l); return wrapper; },
84
- setReasoning(t, l) { inner.setReasoning(t, l); return wrapper; },
85
- upsertTool(t) { inner.upsertTool(t); return wrapper; },
86
- updateTool(tcId, p) { inner.updateTool(tcId, p); return wrapper; },
87
- patch(p) { inner.patch(p); return wrapper; },
88
- done(final) { inner.done(final); onSettle(); },
80
+ appendText(delta) { inner.appendText(delta); return wrapper; },
81
+ appendReasoning(delta, opts) { inner.appendReasoning(delta, opts); return wrapper; },
82
+ upsertTool(toolCallId, patch) { inner.upsertTool(toolCallId, patch); return wrapper; },
83
+ addCard(envelope) { inner.addCard(envelope); return wrapper; },
84
+ addSource(source) { inner.addSource(source); return wrapper; },
85
+ addFile(attachment) { inner.addFile(attachment); return wrapper; },
86
+ done() { inner.done(); onSettle(); },
89
87
  abort(reason) { inner.abort(reason); onSettle(); },
90
88
  };
91
89
  return wrapper;
@@ -39,7 +39,7 @@ const useCollapsible = () => {
39
39
  * (no `open` prop); in controlled mode the parent already owns the state. */
40
40
  export interface CollapsibleController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
41
41
 
42
- export function Collapsible(props: {
42
+ export interface CollapsibleProps {
43
43
  open?: boolean;
44
44
  defaultOpen?: boolean;
45
45
  onOpenChange?: (open: boolean) => void;
@@ -51,7 +51,9 @@ export function Collapsible(props: {
51
51
  controllerRef?: (api: CollapsibleController) => void;
52
52
  children: JSX.Element;
53
53
  class?: string;
54
- }) {
54
+ }
55
+
56
+ export function Collapsible(props: CollapsibleProps) {
55
57
  const [local, rest] = splitProps(props, ['open', 'defaultOpen', 'onOpenChange', 'disabled', 'controllerRef', 'children', 'class']);
56
58
  const [uncontrolled, setUncontrolled] = createSignal(local.defaultOpen ?? false);
57
59
  const isControlled = () => local.open !== undefined;
@@ -88,13 +90,16 @@ export function Collapsible(props: {
88
90
  );
89
91
  }
90
92
 
91
- export function CollapsibleTrigger(props: {
93
+ export interface CollapsibleTriggerProps {
92
94
  children?: JSX.Element;
93
95
  class?: string;
94
96
  as?: (props: Record<string, any>) => JSX.Element;
95
97
  onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>;
98
+ /** Remaining attributes are spread onto the rendered trigger. */
96
99
  [k: string]: any;
97
- }) {
100
+ }
101
+
102
+ export function CollapsibleTrigger(props: CollapsibleTriggerProps) {
98
103
  const ctx = useCollapsible();
99
104
  const [local, rest] = splitProps(props, ['children', 'class', 'as', 'onClick']);
100
105
 
@@ -130,7 +135,14 @@ export function CollapsibleTrigger(props: {
130
135
  );
131
136
  }
132
137
 
133
- export function CollapsibleContent(props: { children?: JSX.Element; class?: string; [k: string]: any }) {
138
+ export interface CollapsibleContentProps {
139
+ children?: JSX.Element;
140
+ class?: string;
141
+ /** Remaining attributes are spread onto the rendered panel. */
142
+ [k: string]: any;
143
+ }
144
+
145
+ export function CollapsibleContent(props: CollapsibleContentProps) {
134
146
  const ctx = useCollapsible();
135
147
  const [local, rest] = splitProps(props, ['children', 'class']);
136
148
  return (
@@ -41,7 +41,7 @@ const ITEM_SELECTOR = '[role="menuitem"]:not([aria-disabled="true"]), [role="men
41
41
  * `controllerRef` so it can drive/observe the Dropdown's open state. */
42
42
  export interface DropdownController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
43
43
 
44
- export function Dropdown(props: {
44
+ export interface DropdownProps {
45
45
  children: JSX.Element;
46
46
  /** Initial open state (uncontrolled seed). */
47
47
  defaultOpen?: boolean;
@@ -49,7 +49,41 @@ export function Dropdown(props: {
49
49
  disabled?: boolean;
50
50
  /** Receive the open controller (open accessor + setOpen) once mounted. */
51
51
  controllerRef?: (api: DropdownController) => void;
52
- }) {
52
+ }
53
+
54
+ export interface DropdownTriggerProps {
55
+ /** Render as a different tag/component; defaults to a button. */
56
+ as?: AsTag;
57
+ children?: JSX.Element;
58
+ class?: string;
59
+ /** Remaining attributes are spread onto the rendered trigger. */
60
+ [k: string]: unknown;
61
+ }
62
+
63
+ export interface DropdownContentProps { children: JSX.Element; class?: string }
64
+
65
+ export interface DropdownItemProps {
66
+ children: JSX.Element;
67
+ class?: string;
68
+ onSelect?: () => void;
69
+ disabled?: boolean;
70
+ }
71
+
72
+ export interface DropdownSeparatorProps { class?: string }
73
+
74
+ export interface DropdownLabelProps { children: JSX.Element; class?: string }
75
+
76
+ export interface DropdownCheckboxItemProps extends DropdownItemProps { checked?: boolean }
77
+
78
+ export interface DropdownRadioItemProps extends DropdownItemProps { checked?: boolean }
79
+
80
+ export interface DropdownSubProps { children: JSX.Element }
81
+
82
+ export interface DropdownSubTriggerProps { children: JSX.Element; class?: string }
83
+
84
+ export interface DropdownSubContentProps { children: JSX.Element; class?: string }
85
+
86
+ export function Dropdown(props: DropdownProps) {
53
87
  const [open, setOpenSig] = createSignal(props.defaultOpen ?? false);
54
88
  const [viaKb, setViaKb] = createSignal(false);
55
89
  const [trigger, setTrigger] = createSignal<HTMLElement>();
@@ -95,7 +129,7 @@ export function Dropdown(props: {
95
129
  );
96
130
  }
97
131
 
98
- export function DropdownTrigger(props: { as?: AsTag; children?: JSX.Element; class?: string; [k: string]: any }) {
132
+ export function DropdownTrigger(props: DropdownTriggerProps) {
99
133
  const ctx = useDropdown();
100
134
  // Forward extra attributes (e.g. aria-label for an icon-only trigger). The
101
135
  // controlled wiring below (id/aria-*/onClick/onKeyDown/class/type) is applied
@@ -126,7 +160,7 @@ export function DropdownTrigger(props: { as?: AsTag; children?: JSX.Element; cla
126
160
  );
127
161
  }
128
162
 
129
- export function DropdownContent(props: { children: JSX.Element; class?: string }) {
163
+ export function DropdownContent(props: DropdownContentProps) {
130
164
  const ctx = useDropdown();
131
165
  const config = useChatConfig();
132
166
  const presence = createPresence(ctx.open);
@@ -221,7 +255,7 @@ export function DropdownContent(props: { children: JSX.Element; class?: string }
221
255
  );
222
256
  }
223
257
 
224
- export function DropdownItem(props: { children: JSX.Element; class?: string; onSelect?: () => void; disabled?: boolean }) {
258
+ export function DropdownItem(props: DropdownItemProps) {
225
259
  const ctx = useDropdown();
226
260
  const activate = () => {
227
261
  if (props.disabled) return;
@@ -253,7 +287,7 @@ export function DropdownItem(props: { children: JSX.Element; class?: string; onS
253
287
  * a11y: `role="separator"` — exposed to AT as a group boundary; not in the
254
288
  * roving-focus tab order (the `[role="menuitem"]` query skips it).
255
289
  */
256
- export function DropdownSeparator(props: { class?: string }) {
290
+ export function DropdownSeparator(props: DropdownSeparatorProps) {
257
291
  return <div role="separator" class={cn('-mx-1 my-1 h-px bg-border', props.class)} />;
258
292
  }
259
293
 
@@ -262,7 +296,7 @@ export function DropdownSeparator(props: { class?: string }) {
262
296
  * a11y: a plain muted label — NOT a menuitem and NOT focusable, so roving focus
263
297
  * skips it; it labels the items that follow visually only (`select-none`).
264
298
  */
265
- export function DropdownLabel(props: { children: JSX.Element; class?: string }) {
299
+ export function DropdownLabel(props: DropdownLabelProps) {
266
300
  return (
267
301
  <div class={cn('select-none px-2 py-1.5 text-xs font-medium text-muted-foreground', props.class)}>
268
302
  {props.children}
@@ -278,7 +312,7 @@ export function DropdownLabel(props: { children: JSX.Element; class?: string })
278
312
  * present — aligns with the plain items above it instead of being pushed in by a
279
313
  * reserved leading check column.
280
314
  */
281
- export function DropdownCheckboxItem(props: { children: JSX.Element; class?: string; checked?: boolean; onSelect?: () => void; disabled?: boolean }) {
315
+ export function DropdownCheckboxItem(props: DropdownCheckboxItemProps) {
282
316
  const activate = () => {
283
317
  if (props.disabled) return;
284
318
  props.onSelect?.(); /* stay open — consumer owns `checked` */
@@ -315,7 +349,7 @@ export function DropdownCheckboxItem(props: { children: JSX.Element; class?: str
315
349
  * content aligns with plain items. Group membership is the consumer's concern;
316
350
  * this primitive just renders the selected state and reports the click.
317
351
  */
318
- export function DropdownRadioItem(props: { children: JSX.Element; class?: string; checked?: boolean; onSelect?: () => void; disabled?: boolean }) {
352
+ export function DropdownRadioItem(props: DropdownRadioItemProps) {
319
353
  const activate = () => {
320
354
  if (props.disabled) return;
321
355
  props.onSelect?.(); /* stay open — consumer owns the group selection */
@@ -377,7 +411,7 @@ const useDropdownSub = () => {
377
411
  * (Escape/outside-click/select), `useDismiss` on the parent unmounts the whole
378
412
  * content tree, which tears this provider down and drops the sub with it.
379
413
  */
380
- export function DropdownSub(props: { children: JSX.Element }) {
414
+ export function DropdownSub(props: DropdownSubProps) {
381
415
  const [open, setOpenSig] = createSignal(false);
382
416
  const [viaKb, setViaKb] = createSignal(false);
383
417
  const [trigger, setTrigger] = createSignal<HTMLElement>();
@@ -422,7 +456,7 @@ export function DropdownSub(props: { children: JSX.Element }) {
422
456
  * keyboard-open also moves focus into the sub's first item. ArrowRight/Enter are
423
457
  * swallowed so the parent menu doesn't also act on them.
424
458
  */
425
- export function DropdownSubTrigger(props: { children: JSX.Element; class?: string }) {
459
+ export function DropdownSubTrigger(props: DropdownSubTriggerProps) {
426
460
  const sub = useDropdownSub();
427
461
  const onKeyDown = (e: KeyboardEvent) => {
428
462
  if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {
@@ -465,7 +499,7 @@ export function DropdownSubTrigger(props: { children: JSX.Element; class?: strin
465
499
  * ArrowUp/Down/Home/End rove within; typeahead included (matches DropdownContent).
466
500
  * Keyboard-open focuses the first item.
467
501
  */
468
- export function DropdownSubContent(props: { children: JSX.Element; class?: string }) {
502
+ export function DropdownSubContent(props: DropdownSubContentProps) {
469
503
  const sub = useDropdownSub();
470
504
  const parent = useDropdown();
471
505
  const config = useChatConfig();
@@ -261,11 +261,17 @@ export function useDismiss(opts: UseDismissOptions) {
261
261
  const inside = opts.refs().some((el) => el && el.contains(target));
262
262
  if (!inside) opts.onDismiss('outside');
263
263
  };
264
- document.addEventListener('keydown', onKey);
265
- document.addEventListener('pointerdown', onPointer, true);
264
+ // Captured at SETUP and closed over, never re-resolved as a global inside
265
+ // `onCleanup`: cleanup can run after the host removed the DOM globals (a
266
+ // `kai-*` release is deferred one microtask past detachment, so an
267
+ // environment teardown gets in between), and a bare `document` there throws.
268
+ // See tests/components/teardown-without-dom-globals.test.tsx.
269
+ const doc = document;
270
+ doc.addEventListener('keydown', onKey);
271
+ doc.addEventListener('pointerdown', onPointer, true);
266
272
  onCleanup(() => {
267
- document.removeEventListener('keydown', onKey);
268
- document.removeEventListener('pointerdown', onPointer, true);
273
+ doc.removeEventListener('keydown', onKey);
274
+ doc.removeEventListener('pointerdown', onPointer, true);
269
275
  });
270
276
  });
271
277
  }
@@ -0,0 +1,201 @@
1
+ // The provider-neutral chunk surface. Everything the adapter needs out of one
2
+ // streaming chunk, and nothing else. A WireFormat maps a decoded provider frame
3
+ // onto these; nothing below this line knows a provider exists.
4
+ import type { RawOrigin, ToolPart } from '../components/tool-types';
5
+ import type { MessagePart, MessageSource } from '../elements/chat-types';
6
+ import type { ReasoningOpts } from '../state/parts';
7
+
8
+ /** One fragment of a tool call. */
9
+ export interface ModelToolCallDelta {
10
+ /**
11
+ * The ONLY thing correlating fragments, and its NAMESPACE IS FORMAT-DEFINED.
12
+ * `openaiChatFormat` uses the position in `delta.tool_calls`;
13
+ * `anthropicMessagesFormat` uses the content-block index. Both are correct and
14
+ * both are stable within one stream, but they are not the same number, so a
15
+ * third-party format must pick one and stay consistent with itself.
16
+ */
17
+ index: number;
18
+ id?: string;
19
+ /** Usually whole on the first fragment; a few providers split it. */
20
+ name?: string;
21
+ /** A FRAGMENT of the JSON arguments string, not valid JSON on its own. */
22
+ arguments?: string;
23
+ /** A result the PROVIDER executed (Anthropic web_search_tool_result, an OpenAI
24
+ * built-in). Completes the panel with no host work. */
25
+ output?: Record<string, unknown>;
26
+ /** A provider-executed tool that failed. */
27
+ outputError?: string;
28
+ }
29
+
30
+ /** Field names are deliberately provider-neutral. OpenAI says prompt/completion,
31
+ * Anthropic says input/output; input/output is the one that reads correctly for
32
+ * both. */
33
+ export interface ModelUsage {
34
+ inputTokens?: number;
35
+ outputTokens?: number;
36
+ totalTokens?: number;
37
+ /** Non-zero proves the model reasoned even when no reasoning text streamed. */
38
+ reasoningTokens?: number;
39
+ cachedInputTokens?: number;
40
+ costUsd?: number;
41
+ }
42
+
43
+ export interface ModelStreamChunk {
44
+ text?: string;
45
+ /**
46
+ * Reasoning delta. `''` is MEANINGFUL, not a no-op: a redacted block has no
47
+ * readable text but still carries a payload that must round-trip, and a format
48
+ * uses an empty delta to OPEN a reasoning part at the right position in the
49
+ * stream so block order survives into `parts`.
50
+ */
51
+ reasoning?: string;
52
+ /** The provider's BLOCK index. Keeps parallel reasoning blocks distinct.
53
+ * Omitted means block 0, the single-block case every provider degrades to. */
54
+ reasoningIndex?: number;
55
+ /**
56
+ * The UNTRANSLATED provider payload for this reasoning block. Valid on a chunk
57
+ * with NO reasoning text at all, which is the whole point: Anthropic returns
58
+ * 400 if a `thinking` block is modified, reordered or RECONSTRUCTED, so an
59
+ * encoder has to echo the original block rather than rebuild one from `text`
60
+ * plus `signature`.
61
+ */
62
+ reasoningRaw?: RawOrigin;
63
+ /** Informational. `reasoningRaw` is the round-trip channel, not this. */
64
+ reasoningSignature?: string;
65
+ toolCalls?: ModelToolCallDelta[];
66
+ /** Citations the model produced. A run of consecutive `source` parts renders
67
+ * as one citation row (`part="citations"`), outside the message bubble. */
68
+ sources?: MessageSource[];
69
+ /** Provider VERBATIM: 'stop' | 'tool_calls' | 'end_turn' | 'max_tokens' | ...
70
+ * Normalizing in place would destroy information consumers branch on. */
71
+ finishReason?: string | null;
72
+ usage?: ModelUsage;
73
+ /** An in-band provider error (the HTTP response was already 200). */
74
+ error?: { code?: string | number; message: string };
75
+ }
76
+
77
+ /** One vocabulary across formats, for code that has to BRANCH. `finishReason`
78
+ * stays beside it, verbatim, for code that has to REPORT. */
79
+ export type StopReason = 'stop' | 'length' | 'tool-calls' | 'content-filter' | 'error' | 'other';
80
+
81
+ const STOP_REASONS: Record<string, StopReason> = {
82
+ // OpenAI chat completions
83
+ stop: 'stop',
84
+ length: 'length',
85
+ tool_calls: 'tool-calls',
86
+ function_call: 'tool-calls',
87
+ content_filter: 'content-filter',
88
+ error: 'error',
89
+ // Anthropic Messages
90
+ end_turn: 'stop',
91
+ stop_sequence: 'stop',
92
+ max_tokens: 'length',
93
+ tool_use: 'tool-calls',
94
+ refusal: 'content-filter',
95
+ pause_turn: 'other',
96
+ };
97
+
98
+ /** Unknown reasons degrade to 'other' rather than throwing: providers add stop
99
+ * reasons without warning and a new one must not take a turn down. */
100
+ export function normalizeStopReason(
101
+ finishReason: string | null | undefined,
102
+ ): StopReason | undefined {
103
+ if (!finishReason) return undefined;
104
+ return STOP_REASONS[finishReason] ?? 'other';
105
+ }
106
+
107
+ /**
108
+ * The subset of the kit's `AssistantStream` the adapter drives. Declared
109
+ * STRUCTURALLY so the adapter has no runtime dependency on a stream
110
+ * implementation and can be tested against a recorder. The kit's real
111
+ * `AssistantStream` satisfies it as-is: same method names, same arities, and its
112
+ * `AssistantStream` returns are assignable to `unknown`.
113
+ *
114
+ * `addSource` is optional so a hand-rolled three-method sink still compiles.
115
+ */
116
+ export interface AssistantStreamSink {
117
+ appendText(delta: string): unknown;
118
+ appendReasoning(delta: string, opts?: ReasoningOpts): unknown;
119
+ /** Create-or-merge. There is no separate "announce" call: handing a patch for
120
+ * an unknown `toolCallId` creates the ToolPart, and every later patch merges. */
121
+ upsertTool(toolCallId: string, patch: Partial<ToolPart>): unknown;
122
+ addSource?(source: MessageSource): unknown;
123
+ }
124
+
125
+ /** One tool call reassembled out of the stream's fragments. */
126
+ export interface ModelToolCall {
127
+ /** The delta index that correlated this call's fragments. */
128
+ index: number;
129
+ /** Provider call id (synthesised as `call_<index>` if the provider omits it). */
130
+ id: string;
131
+ name: string;
132
+ /** The RAW accumulated argument fragments. Echo THIS back on the next turn,
133
+ * not a re-stringified parse. */
134
+ argumentsText: string;
135
+ /** Parsed arguments: present only when `argumentsText` was a valid JSON object. */
136
+ input?: Record<string, unknown>;
137
+ /** Present only for a call the PROVIDER executed. */
138
+ output?: Record<string, unknown>;
139
+ /** True when the provider ran the tool and returned its result in-stream. The
140
+ * host must NOT execute these. */
141
+ providerExecuted?: boolean;
142
+ /** Why this call is unusable (malformed or truncated args, missing name). */
143
+ error?: string;
144
+ }
145
+
146
+ /** Everything one assistant turn produced. */
147
+ export interface ModelTurn {
148
+ /** The turn as ORDERED MESSAGE PARTS, built with the kit's own part builders,
149
+ * so it is exactly what the sink was driven with. Covers this turn only. */
150
+ parts: MessagePart[];
151
+ /** Flat concatenation of the text deltas. The provider wire format is a flat
152
+ * string, so this is kept for encoders. Not the content model. */
153
+ text: string;
154
+ /** Flat concatenation of the reasoning deltas, for the same reason. */
155
+ reasoning: string;
156
+ toolCalls: ModelToolCall[];
157
+ sources: MessageSource[];
158
+ /** The provider's own word for why it stopped. Never normalized. */
159
+ finishReason: string | null;
160
+ /** The same fact in one vocabulary. Branch on this. */
161
+ stopReason?: StopReason;
162
+ error?: { code?: string | number; message: string };
163
+ usage?: ModelUsage;
164
+ /** How many chunks carried a NON-EMPTY reasoning delta. Zero with a non-zero
165
+ * `usage.reasoningTokens` means the provider hid the thinking text. */
166
+ reasoningChunks: number;
167
+ chunks: number;
168
+ }
169
+
170
+ export interface ConsumeOptions {
171
+ /** Label for the reasoning disclosure. Defaults to 'Thinking'. */
172
+ reasoningLabel?: string;
173
+ /** Fires once per tool call the moment its arguments parse cleanly. This is
174
+ * the hook a host's tool loop waits on. There is deliberately no
175
+ * per-fragment callback: `ToolPart.rawInput` is written on every fragment,
176
+ * so the streaming text is already on the part. */
177
+ onToolCallReady?: (call: ModelToolCall) => void;
178
+ }
179
+
180
+ /** Per-stream state for one format. */
181
+ export interface WireFormatReader {
182
+ /**
183
+ * Map one decoded frame onto zero or more neutral chunks. Returns an ARRAY
184
+ * because the mapping is not one-to-one: an Anthropic `message_start` yields
185
+ * usage, a `content_block_start` for `tool_use` yields an id-plus-name delta,
186
+ * a `ping` yields nothing.
187
+ *
188
+ * MUST NOT throw on an unrecognized frame. Return `[]` instead: providers add
189
+ * event types without warning.
190
+ */
191
+ push(frame: unknown): ModelStreamChunk[];
192
+ }
193
+
194
+ /** A pluggable wire format. Values, not a flag, so a third party can add one
195
+ * without a PR to this repo. */
196
+ export interface WireFormat {
197
+ readonly id: string;
198
+ /** Called once per stream so a format can hold per-stream state. Two calls
199
+ * must share NOTHING. */
200
+ open(): WireFormatReader;
201
+ }