@kitn.ai/ui 0.25.1 → 0.26.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 (409) hide show
  1. package/README.md +5 -7
  2. package/dist/components/attachment-types.d.ts +46 -1
  3. package/dist/components/attachments.d.ts +31 -0
  4. package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
  5. package/dist/components/audio-visualizer/index.d.ts +15 -1
  6. package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
  7. package/dist/components/chat-thread.d.ts +3 -41
  8. package/dist/components/code-block.d.ts +22 -0
  9. package/dist/components/conversation-item.d.ts +54 -1
  10. package/dist/components/conversation-list.d.ts +65 -0
  11. package/dist/components/form.d.ts +42 -0
  12. package/dist/components/message.d.ts +7 -0
  13. package/dist/components/toast.d.ts +2 -1
  14. package/dist/components/voice-input.d.ts +8 -0
  15. package/dist/components/voice-output.d.ts +12 -1
  16. package/dist/components/workspace-shell.d.ts +87 -0
  17. package/dist/{create-tween-B5Y4Im8G.js → create-tween-BFT6c-Y8.js} +1 -1
  18. package/dist/{create-tween-4z1XYLkR.js → create-tween-CJNlzoaO.js} +1 -1
  19. package/dist/{create-tween-CUzOlaMS.js → create-tween-CQED4T0g.js} +1 -1
  20. package/dist/custom-elements.json +2931 -2572
  21. package/dist/diagnostics/hook.d.ts +81 -0
  22. package/dist/diagnostics/index.d.ts +7 -0
  23. package/dist/diagnostics/report-request.d.ts +61 -0
  24. package/dist/diagnostics.d.ts +5 -0
  25. package/dist/diagnostics.js +209 -0
  26. package/dist/elements/agent-card.js +1 -1
  27. package/dist/elements/artifact.js +1 -1
  28. package/dist/elements/attachments.js +1 -1
  29. package/dist/elements/audio-visualizer.js +1 -1
  30. package/dist/elements/autoloader.js +1 -1
  31. package/dist/elements/avatar.js +1 -1
  32. package/dist/elements/badge.js +1 -1
  33. package/dist/elements/button.js +1 -1
  34. package/dist/elements/card.js +1 -1
  35. package/dist/elements/cards.js +1 -1
  36. package/dist/elements/chain-of-thought.js +1 -1
  37. package/dist/elements/chat-scope-picker.js +1 -1
  38. package/dist/elements/chat-workspace.js +1 -1
  39. package/dist/elements/chat.js +1 -1
  40. package/dist/elements/checkpoint.js +1 -1
  41. package/dist/elements/choice.js +1 -1
  42. package/dist/elements/chunks/{Icon-b5A8hlHs.js → Icon--Y8vsFal.js} +1 -1
  43. package/dist/elements/chunks/action-icons-D9u3OzYW.js +1 -0
  44. package/dist/elements/chunks/arrow-left-CVh1TeN7.js +1 -0
  45. package/dist/elements/chunks/{artifact-BSuPYFHY.js → artifact-BkYcfIlZ.js} +1 -1
  46. package/dist/elements/chunks/attachments-DwfNlubq.js +1 -0
  47. package/dist/elements/chunks/audio-visualizer-D7lB6mvR.js +1 -0
  48. package/dist/elements/chunks/{badge-TIMiJFKc.js → badge-Q0-Cmwzz.js} +1 -1
  49. package/dist/elements/chunks/{button-B9okqG73.js → button-flUbeufF.js} +1 -1
  50. package/dist/elements/chunks/{card-renderer-CSoTL_e1.js → card-renderer-3Dyl-FpN.js} +1 -1
  51. package/dist/elements/chunks/check-B5kBPKeo.js +1 -0
  52. package/dist/elements/chunks/chevron-down-DZ1GS39h.js +1 -0
  53. package/dist/elements/chunks/chevron-right-CvP7OUd2.js +1 -0
  54. package/dist/elements/chunks/{choice-card-CGMc3kek.js → choice-card-D4QUIOWZ.js} +1 -1
  55. package/dist/elements/chunks/circle-CDf9g6MQ.js +1 -0
  56. package/dist/elements/chunks/circle-check-CA47Nqbz.js +1 -0
  57. package/dist/elements/chunks/{circle-x-mhH7pOK2.js → circle-x-CJ_HVbC8.js} +1 -1
  58. package/dist/elements/chunks/code-block-BdLiTitd.js +1 -0
  59. package/dist/elements/chunks/collapsible-BzbXpPzr.js +1 -0
  60. package/dist/elements/chunks/{composer-CZZmtYOT.js → composer-Byve-n8K.js} +2 -2
  61. package/dist/elements/chunks/{confirm-card-BWjf2-xo.js → confirm-card-B0flE3MN.js} +1 -1
  62. package/dist/elements/chunks/context-VLIL3sJ-.js +1 -0
  63. package/dist/elements/chunks/controllable-DTwTIlwp.js +1 -0
  64. package/dist/elements/chunks/conversation-item-BDztezOG.js +1 -0
  65. package/dist/elements/chunks/copy-Nf-kqxXH.js +1 -0
  66. package/dist/elements/chunks/{create-tween-CUrM6D_o.js → create-tween-c4Z8TDYz.js} +2 -2
  67. package/dist/elements/chunks/default-input-C2iLFq0b.js +1 -0
  68. package/dist/elements/chunks/define-wjHR1MkU.js +1 -0
  69. package/dist/elements/chunks/disclosure-CcNbyLy0.js +1 -0
  70. package/dist/elements/chunks/{download-DnCyWFJE.js → download-C4V7tBdb.js} +1 -1
  71. package/dist/elements/chunks/dropdown-BgWTthUx.js +1 -0
  72. package/dist/elements/chunks/{ellipsis-CVxqfsDZ.js → ellipsis-7gU33mL2.js} +1 -1
  73. package/dist/elements/chunks/embed-D3KewsIJ.js +1 -0
  74. package/dist/elements/chunks/{external-link-DG2sRdQL.js → external-link-CSOEsNlx.js} +1 -1
  75. package/dist/elements/chunks/{file-text-D0J9F6M7.js → file-text-D1G8khle.js} +1 -1
  76. package/dist/elements/chunks/{file-tree-yGWNK0Js.js → file-tree-zvB2i7P9.js} +1 -1
  77. package/dist/elements/chunks/{folder-NV1pi_ud.js → folder-WW2LGLid.js} +1 -1
  78. package/dist/elements/chunks/form-CQirdC4W.js +1 -0
  79. package/dist/elements/chunks/hover-card-CJJkfHTK.js +1 -0
  80. package/dist/elements/chunks/icon-Cfgmf4fa.js +1 -0
  81. package/dist/elements/chunks/{info-C8r5Q6cc.js → info-DX3YMOt6.js} +1 -1
  82. package/dist/elements/chunks/input-BtW9U6Sq.js +1 -0
  83. package/dist/elements/chunks/{kbd-OGJDUT-O.js → kbd-LGXwuT_V.js} +1 -1
  84. package/dist/elements/chunks/{link-BdsfLB7b.js → link-2My69BqT.js} +1 -1
  85. package/dist/elements/chunks/{link-preview-Cf5KOP-i.js → link-preview-OQ9IEq0f.js} +1 -1
  86. package/dist/elements/chunks/{loader-B5QzK_8_.js → loader-iOxc_Tu-.js} +1 -1
  87. package/dist/elements/chunks/{markdown-DbozyYqa.js → markdown-DgBFaGAz.js} +1 -1
  88. package/dist/elements/chunks/{message-DtXKPqiR.js → message-VMZohrXx.js} +1 -1
  89. package/dist/elements/chunks/message-circle-CpXMM-_n.js +1 -0
  90. package/dist/elements/chunks/message-square-DxcWtETQ.js +1 -0
  91. package/dist/elements/chunks/message-tZmV2A3p.js +1 -0
  92. package/dist/elements/chunks/{minimize-2-SegJ_oku.js → minimize-2-DPIUKTrT.js} +1 -1
  93. package/dist/elements/chunks/{model-switcher-D7JrFFHp.js → model-switcher-DsT8tFB0.js} +1 -1
  94. package/dist/elements/chunks/{overlay-CV7z2YuX.js → overlay-DuiwdXjm.js} +1 -1
  95. package/dist/elements/chunks/{paperclip-Bg0ITU3b.js → paperclip-CRZVp4z_.js} +1 -1
  96. package/dist/elements/chunks/{progress-bar-D1_rzt6N.js → progress-bar-DNy66e_E.js} +1 -1
  97. package/dist/elements/chunks/{prompt-suggestion-D5Sm8xF1.js → prompt-suggestion-Bn64Nl7L.js} +1 -1
  98. package/dist/elements/chunks/reasoning-Emn9N4-T.js +1 -0
  99. package/dist/elements/chunks/{resizable-Dpzjlvp4.js → resizable-D181b4fM.js} +1 -1
  100. package/dist/elements/chunks/{rotate-cw-DzVDJOA1.js → rotate-cw-CPWe37D9.js} +1 -1
  101. package/dist/elements/chunks/{scroll-area-93A1bbeG.js → scroll-area-ClZkZxIk.js} +1 -1
  102. package/dist/elements/chunks/scroll-button-DPE-t3x_.js +1 -0
  103. package/dist/elements/chunks/{separator-DH2r_ZSZ.js → separator-CeJHQqLW.js} +1 -1
  104. package/dist/elements/chunks/{settings-BFMOd6yB.js → settings-CqaHgJF9.js} +1 -1
  105. package/dist/elements/chunks/{settings-group-B3VZKIcz.js → settings-group-CjqjLCOn.js} +1 -1
  106. package/dist/elements/chunks/share-CyfnNEqp.js +1 -0
  107. package/dist/elements/chunks/{skeleton-N8BuWYmf.js → skeleton-D8akBnKS.js} +1 -1
  108. package/dist/elements/chunks/slots-DaNjX0rc.js +1 -0
  109. package/dist/elements/chunks/{source-w9V0NnBn.js → source-UWCvmVak.js} +1 -1
  110. package/dist/elements/chunks/{star-DHvACxtm.js → star-DoHFAikQ.js} +1 -1
  111. package/dist/elements/chunks/store-Cjq0qwYN.js +1 -0
  112. package/dist/elements/chunks/{tasks-card-lPxoodlA.js → tasks-card-CmZ5xh6v.js} +1 -1
  113. package/dist/elements/chunks/{text-shimmer-BY_rI3s5.js → text-shimmer-DYn09zrz.js} +1 -1
  114. package/dist/elements/chunks/textarea-skiGHURM.js +1 -0
  115. package/dist/elements/chunks/{thumbs-up-DQe0hvkZ.js → thumbs-up-DX2Ijk3H.js} +1 -1
  116. package/dist/elements/chunks/{toast-store-VUZZBhzH.js → toast-store-CFnQpThX.js} +1 -1
  117. package/dist/elements/chunks/{tool-C1YtxwPu.js → tool-DKQ2D1DP.js} +1 -1
  118. package/dist/elements/chunks/{tooltip-BqwnFWhn.js → tooltip-B0G99y8w.js} +1 -1
  119. package/dist/elements/chunks/{triangle-alert-B6or7F5u.js → triangle-alert-F9cyUEyy.js} +1 -1
  120. package/dist/elements/chunks/{use-card-resolution-DJg32jGH.js → use-card-resolution-DoA2f_EU.js} +1 -1
  121. package/dist/elements/chunks/{variant-aurora-QXTZPyST.js → variant-aurora-qt6Zct8M.js} +2 -2
  122. package/dist/elements/chunks/variant-custom-tJp22_BQ.js +1 -0
  123. package/dist/{variant-wave-BwzrHD1s.js → elements/chunks/variant-wave-CaQ5ti39.js} +2 -2
  124. package/dist/elements/chunks/x-B6UnOiLw.js +1 -0
  125. package/dist/elements/coachmark.js +1 -1
  126. package/dist/elements/code-block.js +1 -1
  127. package/dist/elements/command.js +1 -1
  128. package/dist/elements/compare.js +1 -1
  129. package/dist/elements/composer.js +1 -1
  130. package/dist/elements/confirm-card.js +1 -1
  131. package/dist/elements/context-meter.js +1 -1
  132. package/dist/elements/conversation-item.d.ts +1 -0
  133. package/dist/elements/conversation-item.js +1 -0
  134. package/dist/elements/conversation-list.js +1 -1
  135. package/dist/elements/default-input.d.ts +3 -3
  136. package/dist/elements/define.d.ts +27 -0
  137. package/dist/elements/diagnostic-events.d.ts +74 -0
  138. package/dist/elements/dialog.js +1 -1
  139. package/dist/elements/dock.d.ts +1 -0
  140. package/dist/elements/dock.js +149 -0
  141. package/dist/elements/dropdown.d.ts +1 -0
  142. package/dist/elements/dropdown.js +1 -0
  143. package/dist/elements/editable-label.js +1 -1
  144. package/dist/elements/element-diagnostics.d.ts +81 -0
  145. package/dist/elements/embed.js +1 -1
  146. package/dist/elements/empty.js +1 -1
  147. package/dist/elements/feedback-bar.js +1 -1
  148. package/dist/elements/file-tree.js +1 -1
  149. package/dist/elements/file-upload.js +1 -1
  150. package/dist/elements/form.js +1 -1
  151. package/dist/elements/hover-card.js +1 -1
  152. package/dist/elements/icon.js +1 -1
  153. package/dist/elements/image.js +1 -1
  154. package/dist/elements/input.js +1 -1
  155. package/dist/elements/kbd.js +1 -1
  156. package/dist/elements/link-preview.js +1 -1
  157. package/dist/elements/loader.js +1 -1
  158. package/dist/elements/markdown.js +1 -1
  159. package/dist/elements/menu.js +1 -1
  160. package/dist/elements/message-skills.js +1 -1
  161. package/dist/elements/message.js +1 -1
  162. package/dist/elements/model-switcher.js +1 -1
  163. package/dist/elements/nav.js +1 -1
  164. package/dist/elements/notice.js +1 -1
  165. package/dist/elements/pane-group.js +1 -1
  166. package/dist/elements/pane.js +1 -1
  167. package/dist/elements/popover.js +1 -1
  168. package/dist/elements/progress-bar.js +1 -1
  169. package/dist/elements/prompt-dock.js +1 -1
  170. package/dist/elements/prompt-input.js +1 -1
  171. package/dist/elements/prompt-suggestions.js +1 -1
  172. package/dist/elements/reasoning.js +1 -1
  173. package/dist/elements/register.d.ts +2 -0
  174. package/dist/elements/remote.js +1 -1
  175. package/dist/elements/resizable.js +1 -1
  176. package/dist/elements/response-stream.js +3 -3
  177. package/dist/elements/screen.js +1 -1
  178. package/dist/elements/scroll-area.js +1 -1
  179. package/dist/elements/scroll-button.js +1 -1
  180. package/dist/elements/search.js +1 -1
  181. package/dist/elements/segmented.js +1 -1
  182. package/dist/elements/separator.js +1 -1
  183. package/dist/elements/setting-item.js +1 -1
  184. package/dist/elements/settings-group.js +1 -1
  185. package/dist/elements/skeleton.js +1 -1
  186. package/dist/elements/slots.d.ts +35 -3
  187. package/dist/elements/source.js +1 -1
  188. package/dist/elements/status.js +1 -1
  189. package/dist/elements/switch.js +1 -1
  190. package/dist/elements/tabs.js +1 -1
  191. package/dist/elements/tasks.js +1 -1
  192. package/dist/elements/text-shimmer.js +1 -1
  193. package/dist/elements/thinking-bar.js +1 -1
  194. package/dist/elements/thread.js +1 -1
  195. package/dist/elements/toast.js +1 -1
  196. package/dist/elements/tool.js +1 -1
  197. package/dist/elements/tooltip.js +1 -1
  198. package/dist/elements/voice-input.js +1 -1
  199. package/dist/elements/voice-output.js +1 -1
  200. package/dist/elements.d.ts +232 -148
  201. package/dist/index.d.ts +2 -0
  202. package/dist/index.js +5456 -4931
  203. package/dist/index.server.js +4142 -3669
  204. package/dist/kai-provider.es.js +40 -40
  205. package/dist/kai.es.js +1 -1
  206. package/dist/llms/llms-full.txt +184 -69
  207. package/dist/llms/llms.txt +3 -3
  208. package/dist/mcp.es.js +2669 -546
  209. package/dist/primitives/use-resize-observer.d.ts +23 -0
  210. package/dist/primitives/use-speech-recognition.d.ts +8 -0
  211. package/dist/primitives/use-text-stream.d.ts +5 -0
  212. package/dist/react/index.d.ts +115 -266
  213. package/dist/react.js +247 -221
  214. package/dist/register-impl-DpE7icIb.js +293 -0
  215. package/dist/schemas/index.d.ts +1 -1
  216. package/dist/schemas/tool-defs.d.ts +35 -0
  217. package/dist/schemas.js +403 -310
  218. package/dist/{solid-BMuDmFo_.js → solid-BtdqNZI7.js} +8435 -7394
  219. package/dist/{solid-CGYNdLRR.js → solid-CnavwBye.js} +5987 -5035
  220. package/dist/solid.d.ts +5 -0
  221. package/dist/solid.js +210 -203
  222. package/dist/solid.server.js +210 -203
  223. package/dist/state/index.d.ts +4 -0
  224. package/dist/state/persistence.d.ts +51 -0
  225. package/dist/state/stream.d.ts +50 -0
  226. package/dist/state/threads.d.ts +71 -0
  227. package/dist/state.js +269 -169
  228. package/dist/types.d.ts +4 -2
  229. package/dist/ui/dock.d.ts +109 -0
  230. package/dist/ui/hover-card.d.ts +44 -0
  231. package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-B8II3-I1.js} +27 -27
  232. package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CMNWOSJR.js} +28 -28
  233. package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CcuDMWwQ.js} +2 -2
  234. package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-BdvYC7af.js} +40 -40
  235. package/dist/{variant-custom-BhS9wIpU.js → variant-custom-C714mqKl.js} +65 -65
  236. package/dist/variant-custom-L16JLLZy.js +1 -0
  237. package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-2S4La2Ka.js} +2 -2
  238. package/dist/{variant-wave-CbVsmgwT.js → variant-wave-D7ruiA1W.js} +25 -25
  239. package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-ecwykeyL.js} +21 -21
  240. package/dist/wire/chunk.d.ts +47 -0
  241. package/dist/wire/diagnostics.d.ts +575 -0
  242. package/dist/wire/encode-probe.d.ts +70 -0
  243. package/dist/wire/encode.d.ts +24 -0
  244. package/dist/wire/index.d.ts +2 -0
  245. package/dist/wire/sse.d.ts +10 -2
  246. package/dist/wire.js +917 -480
  247. package/frameworks/react/index.tsx +132 -93
  248. package/llms-full.txt +184 -69
  249. package/llms.txt +3 -3
  250. package/package.json +27 -7
  251. package/src/agent-tooling/archetypes.ts +41 -9
  252. package/src/agent-tooling/catalog/README.md +676 -0
  253. package/src/agent-tooling/catalog/catalog-types.ts +231 -0
  254. package/src/agent-tooling/catalog/fabrications.ts +96 -0
  255. package/src/agent-tooling/catalog/invariants.ts +284 -0
  256. package/src/agent-tooling/catalog/labs-titles.ts +114 -0
  257. package/src/agent-tooling/catalog/scenarios.ts +87 -0
  258. package/src/agent-tooling/catalog/surfaces.ts +275 -0
  259. package/src/agent-tooling/integrations/anthropic.ts +7 -1
  260. package/src/agent-tooling/integrations/cloudflare.ts +43 -2
  261. package/src/agent-tooling/integrations/langgraph.ts +7 -1
  262. package/src/agent-tooling/integrations/mastra.ts +7 -1
  263. package/src/agent-tooling/integrations/mock.ts +92 -17
  264. package/src/agent-tooling/integrations/ollama.ts +7 -1
  265. package/src/agent-tooling/integrations/openai.ts +7 -1
  266. package/src/agent-tooling/integrations/openrouter.ts +7 -1
  267. package/src/agent-tooling/integrations/pi.ts +56 -1
  268. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
  269. package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
  270. package/src/agent-tooling/mcp/manifest.ts +100 -1
  271. package/src/agent-tooling/mcp/server.ts +61 -5
  272. package/src/agent-tooling/mcp/tools/reference.ts +440 -4
  273. package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
  274. package/src/agent-tooling/mcp/tools/theme.ts +146 -30
  275. package/src/agent-tooling/mcp/validate-args.ts +141 -0
  276. package/src/agent-tooling/registry.ts +19 -7
  277. package/src/agent-tooling/route-emit.ts +26 -2
  278. package/src/components/attachment-types.ts +47 -1
  279. package/src/components/attachments.tsx +169 -22
  280. package/src/components/audio-visualizer/fit-scale.ts +112 -0
  281. package/src/components/audio-visualizer/index.tsx +80 -3
  282. package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
  283. package/src/components/audio-visualizer/variant-bar.tsx +38 -6
  284. package/src/components/audio-visualizer/variant-custom.tsx +8 -2
  285. package/src/components/audio-visualizer/variant-grid.tsx +16 -11
  286. package/src/components/audio-visualizer/variant-radial.tsx +15 -10
  287. package/src/components/audio-visualizer/variant-wave.tsx +7 -2
  288. package/src/components/chat-container.tsx +4 -1
  289. package/src/components/chat-thread.tsx +36 -7
  290. package/src/components/code-block.tsx +79 -3
  291. package/src/components/composer.tsx +8 -1
  292. package/src/components/conversation-item.tsx +114 -4
  293. package/src/components/conversation-list.tsx +212 -12
  294. package/src/components/embed.tsx +4 -0
  295. package/src/components/form.tsx +41 -14
  296. package/src/components/message.tsx +75 -5
  297. package/src/components/response-stream.tsx +13 -7
  298. package/src/components/screen.tsx +5 -0
  299. package/src/components/scroll-button.tsx +7 -0
  300. package/src/components/toast.tsx +11 -5
  301. package/src/components/voice-input.tsx +35 -3
  302. package/src/components/voice-output.tsx +46 -6
  303. package/src/components/workspace-shell.tsx +285 -0
  304. package/src/diagnostics/hook.ts +352 -0
  305. package/src/diagnostics/index.ts +82 -0
  306. package/src/diagnostics/report-request.ts +296 -0
  307. package/src/elements/attachments.tsx +6 -7
  308. package/src/elements/audio-visualizer.tsx +48 -4
  309. package/src/elements/chat-workspace.tsx +159 -287
  310. package/src/elements/chat.tsx +12 -9
  311. package/src/elements/code-block.tsx +19 -1
  312. package/src/elements/command.tsx +4 -1
  313. package/src/elements/compiled.css +1 -1
  314. package/src/elements/conversation-item.tsx +80 -0
  315. package/src/elements/conversation-list.tsx +60 -11
  316. package/src/elements/default-input.tsx +5 -5
  317. package/src/elements/define.tsx +168 -8
  318. package/src/elements/diagnostic-events.ts +114 -0
  319. package/src/elements/dialog.tsx +47 -0
  320. package/src/elements/disclosure.ts +34 -12
  321. package/src/elements/dock.tsx +204 -0
  322. package/src/elements/dropdown.tsx +123 -0
  323. package/src/elements/element-diagnostics.ts +392 -0
  324. package/src/elements/element-manifest.json +12 -0
  325. package/src/elements/element-meta.json +672 -439
  326. package/src/elements/element-nonscalar.json +170 -0
  327. package/src/elements/element-types.d.ts +232 -148
  328. package/src/elements/menu.tsx +13 -0
  329. package/src/elements/prompt-dock.tsx +2 -1
  330. package/src/elements/prompt-input.tsx +8 -8
  331. package/src/elements/register-impl.ts +46 -0
  332. package/src/elements/register.ts +28 -0
  333. package/src/elements/resizable.tsx +52 -25
  334. package/src/elements/scroll-button.tsx +5 -0
  335. package/src/elements/slots.ts +107 -12
  336. package/src/elements/styles.css +30 -6
  337. package/src/elements/thinking-bar.tsx +16 -7
  338. package/src/elements/toast.tsx +3 -0
  339. package/src/elements/tool.tsx +26 -5
  340. package/src/elements/voice-input.tsx +11 -2
  341. package/src/elements/voice-output.tsx +16 -3
  342. package/src/index.ts +2 -0
  343. package/src/primitives/use-resize-observer.ts +33 -0
  344. package/src/primitives/use-speech-recognition.ts +12 -1
  345. package/src/primitives/use-stick-to-bottom.ts +34 -2
  346. package/src/primitives/use-text-stream.ts +33 -2
  347. package/src/remote/provider-runtime.ts +6 -3
  348. package/src/schemas/index.ts +1 -0
  349. package/src/schemas/tool-defs.ts +297 -6
  350. package/src/solid.ts +5 -0
  351. package/src/state/index.ts +12 -0
  352. package/src/state/persistence.ts +180 -0
  353. package/src/state/stream.ts +71 -4
  354. package/src/state/threads.ts +142 -0
  355. package/src/types.ts +4 -2
  356. package/src/ui/dialog.tsx +6 -0
  357. package/src/ui/dock.tsx +445 -0
  358. package/src/ui/dropdown.tsx +67 -23
  359. package/src/ui/hover-card.tsx +156 -6
  360. package/src/ui/input.tsx +29 -10
  361. package/src/ui/resizable.tsx +11 -0
  362. package/src/wire/chunk.ts +47 -0
  363. package/src/wire/consume.ts +185 -26
  364. package/src/wire/diagnostics.ts +727 -0
  365. package/src/wire/encode-probe.ts +214 -0
  366. package/src/wire/encode.ts +267 -14
  367. package/src/wire/formats/anthropic.ts +8 -1
  368. package/src/wire/formats/openai.ts +5 -0
  369. package/src/wire/index.ts +22 -0
  370. package/src/wire/read.ts +250 -6
  371. package/src/wire/sse.ts +16 -3
  372. package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
  373. package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
  374. package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
  375. package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
  376. package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
  377. package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
  378. package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
  379. package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
  380. package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
  381. package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
  382. package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
  383. package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
  384. package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
  385. package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
  386. package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
  387. package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
  388. package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
  389. package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
  390. package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
  391. package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
  392. package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
  393. package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
  394. package/dist/elements/chunks/input-DrseEjhp.js +0 -1
  395. package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
  396. package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
  397. package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
  398. package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
  399. package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
  400. package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
  401. package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
  402. package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
  403. package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
  404. package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
  405. package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
  406. package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
  407. package/dist/register-impl-DGmGzrEM.js +0 -145
  408. package/dist/variant-custom-MkTNTycd.js +0 -1
  409. package/src/primitives/card-validate-generator.testlib.ts +0 -38
@@ -26,8 +26,15 @@ export interface VoiceOutputProps {
26
26
  /** TTS model seam: given text, return an audio Blob to play. When set, the
27
27
  * native speechSynthesis path is bypassed. Mirrors VoiceInput's `onTranscribe`. */
28
28
  onSynthesize?: (text: string) => Promise<Blob>;
29
- /** Fires whenever playback starts or stops. */
29
+ /** Fires whenever playback starts or stops. `speaking: true` means audio has
30
+ * actually started (utterance.onstart on the native path; audio.play()
31
+ * resolving on the model path), not that speak() was called. */
30
32
  onSpeakingChange?: (speaking: boolean) => void;
33
+ /** Synthesis failed: a native utterance error, a rejecting `onSynthesize`, or
34
+ * audio playback failing to start. `error` is the platform error code or the
35
+ * exception's name. Deliberate cancellation (stop(), a new speak()) is not a
36
+ * failure and does not fire. The facade maps this to kai-voice-error. */
37
+ onError?: (detail: { source: 'synthesis'; error: string; message: string }) => void;
31
38
  /** Fires once the model path resolves audio (model path only). */
32
39
  onSynthesized?: (blob: Blob) => void;
33
40
  disabled?: boolean;
@@ -68,13 +75,30 @@ export function VoiceOutput(props: VoiceOutputProps) {
68
75
  }
69
76
 
70
77
  // Native path: speechSynthesis.speak(new SpeechSynthesisUtterance(text)).
78
+ // isSpeaking waits for utterance.onstart, so onSpeakingChange(true) means the
79
+ // audio actually began. It used to flip optimistically before speak(), which
80
+ // made "speaking" mean "speak() was called" and raced consumers watching for
81
+ // playback to start (W4 symptom 3).
71
82
  function speakNative() {
72
83
  if (!hasSpeechSynthesis() || !local.text) return;
73
84
  window.speechSynthesis.cancel();
74
85
  utterance = new SpeechSynthesisUtterance(local.text);
86
+ utterance.onstart = () => setIsSpeaking(true);
75
87
  utterance.onend = () => setIsSpeaking(false);
76
- utterance.onerror = () => setIsSpeaking(false);
77
- setIsSpeaking(true);
88
+ utterance.onerror = (event) => {
89
+ setIsSpeaking(false);
90
+ const code = event?.error ?? 'unknown';
91
+ // `canceled`/`interrupted` are what the platform reports when the app
92
+ // itself cancels (stop(), or a new speak() pre-empting): deliberate, not
93
+ // a failure. Everything else surfaces (W4 traced a `not-allowed` here
94
+ // that vanished without a word).
95
+ if (code === 'canceled' || code === 'interrupted') return;
96
+ props.onError?.({
97
+ source: 'synthesis',
98
+ error: code,
99
+ message: `Speech synthesis error: ${code}`,
100
+ });
101
+ };
78
102
  window.speechSynthesis.speak(utterance);
79
103
  }
80
104
 
@@ -90,11 +114,27 @@ export function VoiceOutput(props: VoiceOutputProps) {
90
114
  audio ??= new Audio();
91
115
  audio.src = objectUrl;
92
116
  audio.onended = () => setIsSpeaking(false);
93
- audio.onerror = () => setIsSpeaking(false);
94
- setIsSpeaking(true);
117
+ audio.onerror = () => {
118
+ setIsSpeaking(false);
119
+ props.onError?.({
120
+ source: 'synthesis',
121
+ error: 'playback-failed',
122
+ message: 'The synthesized audio failed to play',
123
+ });
124
+ };
95
125
  await audio.play();
96
- } catch {
126
+ // play() resolving is this path's "audio actually started" (the model
127
+ // path's counterpart of utterance.onstart), so isSpeaking flips only now.
128
+ setIsSpeaking(true);
129
+ } catch (err) {
130
+ // onSynthesize rejected, or play() did (e.g. NotAllowedError under an
131
+ // autoplay policy). Either way the reply is silent: say so.
97
132
  setIsSpeaking(false);
133
+ props.onError?.({
134
+ source: 'synthesis',
135
+ error: err instanceof Error ? err.name : 'unknown',
136
+ message: err instanceof Error ? err.message : String(err),
137
+ });
98
138
  } finally {
99
139
  setIsLoading(false);
100
140
  }
@@ -0,0 +1,285 @@
1
+ import { Show, createSignal, createMemo, onMount, onCleanup, type JSX } from 'solid-js';
2
+ import { createControllableSignal } from '../primitives/controllable';
3
+ import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../ui/resizable';
4
+ import { cn } from '../utils/cn';
5
+
6
+ /** The two aside columns of the shell, named logically (`start` follows the
7
+ * writing direction; on an RTL page it is the right column). */
8
+ export type WorkspaceAsideSide = 'start' | 'end';
9
+
10
+ /** Detail of an aside collapse/expand, however it happened (a method, the
11
+ * breakpoint, the drawer's Escape). */
12
+ export interface WorkspaceAsideToggleDetail {
13
+ side: WorkspaceAsideSide;
14
+ collapsed: boolean;
15
+ }
16
+
17
+ /** Detail of an aside resize (fires per drag step, keyboard nudge, or a handle double-click reset), width in px. */
18
+ export interface WorkspaceAsideResizeDetail {
19
+ side: WorkspaceAsideSide;
20
+ width: number;
21
+ }
22
+
23
+ /** Imperative surface exposed through `controllerRef` (the facade forwards it
24
+ * as element methods). */
25
+ export interface WorkspaceShellController {
26
+ /** Collapse/expand one aside (reports through onAsideToggle). */
27
+ toggleAside(side: WorkspaceAsideSide): void;
28
+ /** Force one aside collapsed (reports through onAsideToggle). */
29
+ collapseAside(side: WorkspaceAsideSide): void;
30
+ /** Force one aside expanded (reports through onAsideToggle). */
31
+ expandAside(side: WorkspaceAsideSide): void;
32
+ }
33
+
34
+ export interface WorkspaceShellProps {
35
+ /** Header band content. The region renders only when this is provided. */
36
+ header?: JSX.Element;
37
+ /** Start aside content (the inline-start column: a rail, a nav, a file tree).
38
+ * The region renders only when this is provided. */
39
+ start?: JSX.Element;
40
+ /** End aside content (the inline-end column: inspector, notes, preview).
41
+ * The region renders only when this is provided. */
42
+ end?: JSX.Element;
43
+ /** Footer band content. The region renders only when this is provided. */
44
+ footer?: JSX.Element;
45
+ /** Main region content. Always rendered. */
46
+ children?: JSX.Element;
47
+
48
+ /** Controlled collapsed state of the start aside. Omit for uncontrolled. */
49
+ startCollapsed?: boolean;
50
+ /** Initial collapsed state of the start aside when uncontrolled (default false). */
51
+ defaultStartCollapsed?: boolean;
52
+ /** Controlled collapsed state of the end aside. Omit for uncontrolled. */
53
+ endCollapsed?: boolean;
54
+ /** Initial collapsed state of the end aside when uncontrolled (default false). */
55
+ defaultEndCollapsed?: boolean;
56
+
57
+ /** Start aside default width in px (default 280). */
58
+ startWidth?: number;
59
+ /** Start aside minimum width in px during resize (default 200). */
60
+ startMinWidth?: number;
61
+ /** Start aside maximum width in px during resize (default 480). */
62
+ startMaxWidth?: number;
63
+ /** End aside default width in px (default 320). */
64
+ endWidth?: number;
65
+ /** End aside minimum width in px during resize (default 200). */
66
+ endMinWidth?: number;
67
+ /** End aside maximum width in px during resize (default 480). */
68
+ endMaxWidth?: number;
69
+
70
+ /** Auto-collapse both asides when the shell's own width drops below this many
71
+ * px, and re-expand when it grows back above. Applies to uncontrolled asides
72
+ * only (it never fights an app-driven collapsed prop); omit to disable. */
73
+ collapseBelow?: number;
74
+ /** Below this shell width in px, an expanded aside renders as an overlay
75
+ * drawer over the main region instead of a column beside it. Escape inside
76
+ * the drawer closes it and returns focus to the element focused before it
77
+ * opened. Omit to disable. */
78
+ drawerBelow?: number;
79
+ /** Density hint. Reflected as a `data-compact` hook on the root (and as the
80
+ * `compact` attribute on the element) for your CSS and slotted content; the
81
+ * shell itself keeps no other opinion about density. */
82
+ compact?: boolean;
83
+
84
+ /** An aside collapsed or expanded (any path: method, breakpoint, drawer Escape). */
85
+ onAsideToggle?: (detail: WorkspaceAsideToggleDetail) => void;
86
+ /** The aside was resized (fires per drag step, keyboard nudge, or a handle double-click reset), width in px. */
87
+ onAsideResize?: (detail: WorkspaceAsideResizeDetail) => void;
88
+
89
+ /** Receives the imperative controller once on mount. */
90
+ controllerRef?: (controller: WorkspaceShellController) => void;
91
+ class?: string;
92
+ }
93
+
94
+ /**
95
+ * The chat-agnostic workspace layout shell: five regions (header · start aside ·
96
+ * main · end aside · footer) with resize handles between the columns, per-aside
97
+ * controlled/uncontrolled collapse, collapse-below-breakpoint, and a mobile
98
+ * drawer mode for the asides. It knows nothing about chat: a file tree in
99
+ * `start` is as valid as a conversation rail.
100
+ */
101
+ export function WorkspaceShell(props: WorkspaceShellProps) {
102
+ let rootEl!: HTMLDivElement;
103
+
104
+ // --- host width (drives collapseBelow + drawerBelow) ---
105
+ const [hostWidth, setHostWidth] = createSignal<number | undefined>(undefined);
106
+
107
+ // --- per-aside collapse: controlled wins, otherwise internal state ---
108
+ const [startCollapsed, setStartCollapsed] = createControllableSignal(
109
+ () => props.startCollapsed,
110
+ props.defaultStartCollapsed ?? false,
111
+ );
112
+ const [endCollapsed, setEndCollapsed] = createControllableSignal(
113
+ () => props.endCollapsed,
114
+ props.defaultEndCollapsed ?? false,
115
+ );
116
+ const collapsed = (side: WorkspaceAsideSide) => (side === 'start' ? startCollapsed() : endCollapsed());
117
+ const isControlled = (side: WorkspaceAsideSide) =>
118
+ (side === 'start' ? props.startCollapsed : props.endCollapsed) !== undefined;
119
+
120
+ const setCollapsedTo = (side: WorkspaceAsideSide, next: boolean) => {
121
+ if (side === 'start') setStartCollapsed(next); else setEndCollapsed(next);
122
+ if (next) restoreDrawerFocus(side);
123
+ props.onAsideToggle?.({ side, collapsed: next });
124
+ };
125
+
126
+ // --- drawer mode + focus return ---
127
+ const drawerMode = createMemo(() => {
128
+ const below = props.drawerBelow;
129
+ const width = hostWidth();
130
+ return below != null && width != null && width < below;
131
+ });
132
+ // The element focused when a drawer opened, restored on close. Per side, so a
133
+ // start drawer closing never steals focus a later end drawer captured.
134
+ const drawerOpeners: Partial<Record<WorkspaceAsideSide, HTMLElement>> = {};
135
+ const captureDrawerFocus = (side: WorkspaceAsideSide) => {
136
+ if (!drawerMode()) return;
137
+ const active = document.activeElement;
138
+ if (active instanceof HTMLElement) drawerOpeners[side] = active;
139
+ };
140
+ const restoreDrawerFocus = (side: WorkspaceAsideSide) => {
141
+ const opener = drawerOpeners[side];
142
+ delete drawerOpeners[side];
143
+ if (drawerMode() && opener && opener.isConnected) opener.focus();
144
+ };
145
+
146
+ const expand = (side: WorkspaceAsideSide) => {
147
+ captureDrawerFocus(side);
148
+ setCollapsedTo(side, false);
149
+ };
150
+ const controller: WorkspaceShellController = {
151
+ toggleAside: (side) => (collapsed(side) ? expand(side) : setCollapsedTo(side, true)),
152
+ collapseAside: (side) => setCollapsedTo(side, true),
153
+ expandAside: (side) => expand(side),
154
+ };
155
+ props.controllerRef?.(controller);
156
+
157
+ // --- collapse-below-breakpoint (uncontrolled asides only) ---
158
+ // `autoCollapsed` tracks whether WE collapsed a side, so crossing back above
159
+ // the breakpoint never expands an aside the user collapsed themselves.
160
+ const autoCollapsed: Record<WorkspaceAsideSide, boolean> = { start: false, end: false };
161
+ const applyBreakpoint = (width: number) => {
162
+ const below = props.collapseBelow;
163
+ if (below == null) return;
164
+ const isBelow = width < below;
165
+ for (const side of ['start', 'end'] as const) {
166
+ // A side with no content has nothing to collapse; reporting a toggle for
167
+ // a region that does not exist would be noise, not loudness.
168
+ if (!asideContent(side)) continue;
169
+ if (isControlled(side)) continue;
170
+ if (isBelow && !collapsed(side)) {
171
+ autoCollapsed[side] = true;
172
+ setCollapsedTo(side, true);
173
+ } else if (!isBelow && collapsed(side) && autoCollapsed[side]) {
174
+ autoCollapsed[side] = false;
175
+ setCollapsedTo(side, false);
176
+ }
177
+ }
178
+ };
179
+
180
+ onMount(() => {
181
+ if (typeof ResizeObserver === 'undefined') return;
182
+ const ro = new ResizeObserver((entries) => {
183
+ const width = entries[0]?.contentRect.width ?? rootEl.clientWidth;
184
+ setHostWidth(width);
185
+ applyBreakpoint(width);
186
+ });
187
+ ro.observe(rootEl);
188
+ onCleanup(() => ro.disconnect());
189
+ });
190
+
191
+ // --- widths ---
192
+ const widths = (side: WorkspaceAsideSide) =>
193
+ side === 'start'
194
+ ? {
195
+ size: props.startWidth ?? 280,
196
+ min: props.startMinWidth ?? 200,
197
+ max: props.startMaxWidth ?? 480,
198
+ }
199
+ : {
200
+ size: props.endWidth ?? 320,
201
+ min: props.endMinWidth ?? 200,
202
+ max: props.endMaxWidth ?? 480,
203
+ };
204
+
205
+ // --- drawer Escape: scoped to the drawer (never a document listener, never
206
+ // swallowed — the kai-dock rule at page scale) ---
207
+ const onDrawerKeyDown = (side: WorkspaceAsideSide) => (event: KeyboardEvent) => {
208
+ if (event.key !== 'Escape') return;
209
+ setCollapsedTo(side, true);
210
+ };
211
+
212
+ const asideRefs: Partial<Record<WorkspaceAsideSide, HTMLElement>> = {};
213
+ const emitResize = (side: WorkspaceAsideSide) => {
214
+ const el = asideRefs[side];
215
+ if (!el) return;
216
+ props.onAsideResize?.({ side, width: el.getBoundingClientRect().width });
217
+ };
218
+
219
+ const asideContent = (side: WorkspaceAsideSide) => (side === 'start' ? props.start : props.end);
220
+
221
+ /** An aside as a resizable column (desktop mode). */
222
+ const asideColumn = (side: WorkspaceAsideSide) => {
223
+ const w = widths(side);
224
+ return (
225
+ <ResizablePanel
226
+ defaultSize={`${w.size}px`}
227
+ minSize={`${w.min}px`}
228
+ maxSize={`${w.max}px`}
229
+ part={side === 'start' ? 'aside start' : 'aside end'}
230
+ ref={(el: HTMLElement) => (asideRefs[side] = el)}
231
+ class="bg-surface"
232
+ >
233
+ {asideContent(side)}
234
+ </ResizablePanel>
235
+ );
236
+ };
237
+
238
+ /** An aside as an overlay drawer (mobile mode). */
239
+ const asideDrawer = (side: WorkspaceAsideSide) => (
240
+ <div
241
+ part={side === 'start' ? 'aside start' : 'aside end'}
242
+ data-drawer=""
243
+ class={cn(
244
+ 'absolute inset-y-0 z-20 max-w-[85%] overflow-auto border-border bg-surface shadow-lg',
245
+ side === 'start' ? 'start-0 border-e' : 'end-0 border-s',
246
+ )}
247
+ style={{ width: `${widths(side).size}px` }}
248
+ onKeyDown={onDrawerKeyDown(side)}
249
+ >
250
+ {asideContent(side)}
251
+ </div>
252
+ );
253
+
254
+ const showAside = (side: WorkspaceAsideSide) => !!asideContent(side) && !collapsed(side);
255
+
256
+ return (
257
+ <div
258
+ ref={rootEl}
259
+ class={cn('flex h-full w-full flex-col overflow-hidden bg-background', props.class)}
260
+ data-compact={props.compact ? '' : undefined}
261
+ >
262
+ <Show when={props.header}>
263
+ <div part="header" class="shrink-0 border-b border-border">{props.header}</div>
264
+ </Show>
265
+ <div class="relative min-h-0 flex-1">
266
+ <ResizablePanelGroup orientation="horizontal">
267
+ <Show when={showAside('start') && !drawerMode()}>
268
+ {asideColumn('start')}
269
+ <ResizableHandle onPanelResize={() => emitResize('start')} />
270
+ </Show>
271
+ <ResizablePanel part="main">{props.children}</ResizablePanel>
272
+ <Show when={showAside('end') && !drawerMode()}>
273
+ <ResizableHandle onPanelResize={() => emitResize('end')} />
274
+ {asideColumn('end')}
275
+ </Show>
276
+ </ResizablePanelGroup>
277
+ <Show when={showAside('start') && drawerMode()}>{asideDrawer('start')}</Show>
278
+ <Show when={showAside('end') && drawerMode()}>{asideDrawer('end')}</Show>
279
+ </div>
280
+ <Show when={props.footer}>
281
+ <div part="footer" class="shrink-0 border-t border-border">{props.footer}</div>
282
+ </Show>
283
+ </div>
284
+ );
285
+ }