@kitn.ai/ui 0.25.2 → 0.27.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 (603) hide show
  1. package/README.md +17 -6
  2. package/bin/mcp.js +16 -3
  3. package/bin/route.js +23 -0
  4. package/bin/route.test.js +58 -0
  5. package/dist/{elements/chunks/Icon-b5A8hlHs.js → Icon-BnFKqqtY.js} +1 -1
  6. package/dist/action-icons-CBskfBMz.js +1 -0
  7. package/dist/arrow-down-Br0qtpsz.js +1 -0
  8. package/dist/arrow-left-Dj7xgE12.js +1 -0
  9. package/dist/artifact-CvXEm1lS.js +1 -0
  10. package/dist/assets/dev-5XzXYR21.js +91 -0
  11. package/dist/attachments-C43ZegEq.js +1 -0
  12. package/dist/audio-visualizer-B-79y1Tj.js +1 -0
  13. package/dist/badge-BpUbq8c0.js +1 -0
  14. package/dist/bash-InADTalH.js +1 -6
  15. package/dist/bell-sn17Ip9v.js +1 -0
  16. package/dist/{elements/chunks/button-B9okqG73.js → button-BH6rN0U-.js} +1 -1
  17. package/dist/card-renderer-Cb1gQmth.js +1 -0
  18. package/dist/card-routing-DifQgS7n.js +1 -0
  19. package/dist/check-DPeeMUYx.js +1 -0
  20. package/dist/checkbox-Dc9Yov_B.js +1 -0
  21. package/dist/checkbox-group-B1kDLLYk.js +1 -0
  22. package/dist/chevron-down-CHSWk7ZT.js +1 -0
  23. package/dist/chevron-right-B7l_fMgx.js +1 -0
  24. package/dist/choice-card-BT3c1S8g.js +1 -0
  25. package/dist/circle-Bb0yOpqM.js +1 -0
  26. package/dist/circle-check-BGZpCiz7.js +1 -0
  27. package/dist/circle-x-wobWkoSx.js +1 -0
  28. package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
  29. package/dist/code-block-CUQ5mtv0.js +1 -0
  30. package/dist/collapsible-CPJbf6FM.js +1 -0
  31. package/dist/components/attachment-types.d.ts +53 -1
  32. package/dist/components/attachments.d.ts +31 -0
  33. package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
  34. package/dist/components/audio-visualizer/index.d.ts +15 -1
  35. package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
  36. package/dist/components/card-renderer.d.ts +13 -0
  37. package/dist/components/card.d.ts +4 -0
  38. package/dist/components/chat-thread.d.ts +49 -42
  39. package/dist/components/code-block.d.ts +22 -0
  40. package/dist/components/conversation-item.d.ts +66 -1
  41. package/dist/components/conversation-list.d.ts +77 -0
  42. package/dist/components/form-widgets.d.ts +67 -2
  43. package/dist/components/form.d.ts +89 -0
  44. package/dist/components/message.d.ts +29 -0
  45. package/dist/components/reasoning.d.ts +6 -0
  46. package/dist/components/scroll-button.d.ts +11 -0
  47. package/dist/components/thread.d.ts +5 -0
  48. package/dist/components/toast.d.ts +2 -1
  49. package/dist/components/tool-types.d.ts +9 -0
  50. package/dist/components/voice-input.d.ts +8 -0
  51. package/dist/components/voice-output.d.ts +12 -1
  52. package/dist/components/workspace-shell.d.ts +87 -0
  53. package/dist/composer-CjngLzal.js +106 -0
  54. package/dist/confirm-card-DCx_A4bU.js +1 -0
  55. package/dist/construct-cli.es.js +1169 -0
  56. package/dist/context-BY8V-Nlp.js +1 -0
  57. package/dist/controllable-D43BKmtX.js +1 -0
  58. package/dist/conversation-list-D4lLU_yS.js +1 -0
  59. package/dist/copy-B6DO4PqB.js +1 -0
  60. package/dist/core-AYMC6_lb.js +12 -5874
  61. package/dist/{create-tween-CUzOlaMS.js → create-tween-BPzaefTp.js} +1 -1
  62. package/dist/{create-tween-B5Y4Im8G.js → create-tween-CnMHviKB.js} +1 -1
  63. package/dist/{create-tween-4z1XYLkR.js → create-tween-D1aiGZZh.js} +1 -1
  64. package/dist/{elements/chunks/create-tween-CUrM6D_o.js → create-tween-DUSQUKpr.js} +2 -2
  65. package/dist/css-M7EaDHN_.js +1 -6
  66. package/dist/custom-elements.json +3468 -1927
  67. package/dist/default-input-CucQEOqH.js +1 -0
  68. package/dist/define-CGGX-7Vg.js +1 -0
  69. package/dist/define.d.ts +4 -0
  70. package/dist/define.js +510 -0
  71. package/dist/define.server.d.ts +5 -0
  72. package/dist/define.server.js +506 -0
  73. package/dist/diagnostics/hook.d.ts +81 -0
  74. package/dist/diagnostics/index.d.ts +7 -0
  75. package/dist/diagnostics/report-request.d.ts +61 -0
  76. package/dist/diagnostics.d.ts +5 -0
  77. package/dist/diagnostics.js +209 -0
  78. package/dist/disclosure-CbLtajUQ.js +1 -0
  79. package/dist/dropdown-BwhViJFd.js +1 -0
  80. package/dist/elements/agent-card.js +1 -1
  81. package/dist/elements/artifact.js +1 -1
  82. package/dist/elements/attachments.js +1 -1
  83. package/dist/elements/audio-visualizer.js +1 -1
  84. package/dist/elements/autoloader.js +1 -1
  85. package/dist/elements/avatar.js +1 -1
  86. package/dist/elements/badge.js +1 -1
  87. package/dist/elements/button.js +1 -1
  88. package/dist/elements/card.js +1 -1
  89. package/dist/elements/cards.js +1 -1
  90. package/dist/elements/chain-of-thought.js +1 -1
  91. package/dist/elements/chat-scope-picker.js +1 -1
  92. package/dist/elements/chat-workspace.js +1 -1
  93. package/dist/elements/chat.js +1 -1
  94. package/dist/elements/checkbox-group.d.ts +1 -0
  95. package/dist/elements/checkbox-group.js +1 -0
  96. package/dist/elements/checkbox.d.ts +1 -0
  97. package/dist/elements/checkbox.js +1 -0
  98. package/dist/elements/checkpoint.js +1 -1
  99. package/dist/elements/choice.js +1 -1
  100. package/dist/elements/coachmark.js +1 -1
  101. package/dist/elements/code-block.js +1 -1
  102. package/dist/elements/command.js +1 -1
  103. package/dist/elements/compare.js +1 -1
  104. package/dist/elements/composer.js +1 -1
  105. package/dist/elements/confirm-card.js +1 -1
  106. package/dist/elements/context-meter.js +1 -1
  107. package/dist/elements/conversation-item.d.ts +1 -0
  108. package/dist/elements/conversation-item.js +1 -0
  109. package/dist/elements/conversation-list.js +1 -1
  110. package/dist/elements/default-input.d.ts +3 -3
  111. package/dist/elements/define-entry.d.ts +12 -0
  112. package/dist/elements/define.d.ts +27 -0
  113. package/dist/elements/diagnostic-events.d.ts +74 -0
  114. package/dist/elements/dialog.js +1 -1
  115. package/dist/elements/dock.d.ts +1 -0
  116. package/dist/elements/dock.js +243 -0
  117. package/dist/elements/dropdown.d.ts +1 -0
  118. package/dist/elements/dropdown.js +1 -0
  119. package/dist/elements/editable-label.js +1 -1
  120. package/dist/elements/element-data-types.d.ts +37 -0
  121. package/dist/elements/element-diagnostics.d.ts +81 -0
  122. package/dist/elements/embed.js +1 -1
  123. package/dist/elements/empty.js +1 -1
  124. package/dist/elements/feedback-bar.js +1 -1
  125. package/dist/elements/file-tree.js +1 -1
  126. package/dist/elements/file-upload.js +1 -1
  127. package/dist/elements/form.js +1 -1
  128. package/dist/elements/hover-card.js +1 -1
  129. package/dist/elements/icon.js +1 -1
  130. package/dist/elements/image.js +1 -1
  131. package/dist/elements/input.js +1 -1
  132. package/dist/elements/kbd.js +1 -1
  133. package/dist/elements/link-preview.js +1 -1
  134. package/dist/elements/loader.js +1 -1
  135. package/dist/elements/markdown.js +1 -1
  136. package/dist/elements/menu.js +1 -1
  137. package/dist/elements/message-skills.js +1 -1
  138. package/dist/elements/message.js +1 -1
  139. package/dist/elements/model-switcher.js +1 -1
  140. package/dist/elements/nav.js +1 -1
  141. package/dist/elements/notice.js +1 -1
  142. package/dist/elements/pane-grid.d.ts +1 -0
  143. package/dist/elements/pane-grid.js +1 -0
  144. package/dist/elements/pane-group.js +1 -1
  145. package/dist/elements/pane.js +1 -1
  146. package/dist/elements/popover.js +1 -1
  147. package/dist/elements/progress-bar.js +1 -1
  148. package/dist/elements/prompt-dock.js +1 -1
  149. package/dist/elements/prompt-input.js +1 -1
  150. package/dist/elements/prompt-suggestions.js +1 -1
  151. package/dist/elements/radio-group.d.ts +1 -0
  152. package/dist/elements/radio-group.js +1 -0
  153. package/dist/elements/reasoning.js +1 -1
  154. package/dist/elements/register.d.ts +2 -0
  155. package/dist/elements/remote.js +1 -1
  156. package/dist/elements/resizable.js +1 -1
  157. package/dist/elements/response-stream.js +3 -3
  158. package/dist/elements/screen.js +1 -1
  159. package/dist/elements/scroll-area.js +1 -1
  160. package/dist/elements/scroll-button.js +1 -1
  161. package/dist/elements/search.js +1 -1
  162. package/dist/elements/segmented.js +1 -1
  163. package/dist/elements/select.d.ts +1 -0
  164. package/dist/elements/select.js +1 -0
  165. package/dist/elements/separator.js +1 -1
  166. package/dist/elements/setting-item.js +1 -1
  167. package/dist/elements/settings-group.js +1 -1
  168. package/dist/elements/skeleton.js +1 -1
  169. package/dist/elements/slider.d.ts +1 -0
  170. package/dist/elements/slider.js +1 -0
  171. package/dist/elements/slots.d.ts +36 -4
  172. package/dist/elements/source.js +1 -1
  173. package/dist/elements/status.js +1 -1
  174. package/dist/elements/switch.js +1 -1
  175. package/dist/elements/tabs.js +1 -1
  176. package/dist/elements/tasks.js +1 -1
  177. package/dist/elements/text-shimmer.js +1 -1
  178. package/dist/elements/thinking-bar.js +1 -1
  179. package/dist/elements/thread.js +1 -1
  180. package/dist/elements/toast.js +1 -1
  181. package/dist/elements/tool.js +1 -1
  182. package/dist/elements/tooltip.js +1 -1
  183. package/dist/elements/voice-input.js +1 -1
  184. package/dist/elements/voice-output.js +1 -1
  185. package/dist/elements.d.ts +589 -167
  186. package/dist/{elements/chunks/ellipsis-CVxqfsDZ.js → ellipsis-DFr4Vqr3.js} +1 -1
  187. package/dist/embed-5s_vU4J0.js +1 -0
  188. package/dist/engine-javascript-vq0WuIJl.js +14 -2516
  189. package/dist/{elements/chunks/external-link-DG2sRdQL.js → external-link-u9d85ORQ.js} +1 -1
  190. package/dist/file-text-CX7_x42o.js +1 -0
  191. package/dist/{elements/chunks/file-tree-yGWNK0Js.js → file-tree-D3kBjXI5.js} +1 -1
  192. package/dist/folder-V-YdIL8f.js +1 -0
  193. package/dist/form-BRNUMCN2.js +1 -0
  194. package/dist/github-dark-dimmed-DUshB20C.js +1 -4
  195. package/dist/github-light-JYsPkUQd.js +1 -4
  196. package/dist/hover-card-DaeiYrTA.js +1 -0
  197. package/dist/html-CPZ3oZQ7.js +1 -10
  198. package/dist/icon-BpixdZNq.js +1 -0
  199. package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
  200. package/dist/index.d.ts +3 -1
  201. package/dist/index.js +8473 -6470
  202. package/dist/index.server.js +6495 -4958
  203. package/dist/info-8mFsIjS3.js +1 -0
  204. package/dist/input-d1Yuu-hz.js +1 -0
  205. package/dist/javascript-C25yR2R2.js +1 -6
  206. package/dist/json-DxJze_jm.js +1 -6
  207. package/dist/kai-provider.es.js +40 -40
  208. package/dist/kai.es.js +1 -1
  209. package/dist/kbd-961zMPFB.js +1 -0
  210. package/dist/link-DlZZBGaR.js +1 -0
  211. package/dist/{elements/chunks/link-preview-Cf5KOP-i.js → link-preview-DIIbV2Sd.js} +1 -1
  212. package/dist/loader-YQszHFaW.js +1 -0
  213. package/dist/{elements/chunks/markdown-DbozyYqa.js → markdown-CVk1MPsj.js} +1 -1
  214. package/dist/mcp.es.js +3873 -544
  215. package/dist/message-CwKVEdZg.js +1 -0
  216. package/dist/message-DS8lzHc1.js +1 -0
  217. package/dist/message-circle-Xf8Q-vZp.js +1 -0
  218. package/dist/message-square-Cxnwgkns.js +1 -0
  219. package/dist/{elements/chunks/minimize-2-SegJ_oku.js → minimize-2-UEZmP2QT.js} +1 -1
  220. package/dist/{elements/chunks/model-switcher-D7JrFFHp.js → model-switcher-Kk1jEQ5t.js} +1 -1
  221. package/dist/{elements/chunks/overlay-CV7z2YuX.js → overlay-C1od6LOz.js} +1 -1
  222. package/dist/panel-right-ryET0yyn.js +1 -0
  223. package/dist/paperclip-BDNoZFJP.js +1 -0
  224. package/dist/play-OFIvYXUQ.js +1 -0
  225. package/dist/primitives/card-data-types.d.ts +49 -0
  226. package/dist/primitives/card-routing.d.ts +1 -33
  227. package/dist/primitives/card-validate.d.ts +2 -2
  228. package/dist/primitives/chat-config.d.ts +29 -2
  229. package/dist/primitives/field-mask.d.ts +96 -0
  230. package/dist/primitives/field-semantics.d.ts +36 -0
  231. package/dist/primitives/input-mask.d.ts +46 -0
  232. package/dist/primitives/url-scheme-policy.d.ts +34 -0
  233. package/dist/primitives/use-resize-observer.d.ts +23 -0
  234. package/dist/primitives/use-speech-recognition.d.ts +8 -0
  235. package/dist/primitives/use-text-stream.d.ts +5 -0
  236. package/dist/progress-bar-BvYX0aoy.js +1 -0
  237. package/dist/prompt-suggestion-BRFu2lcu.js +1 -0
  238. package/dist/radio-DcL23cNJ.js +1 -0
  239. package/dist/react/index.d.ts +306 -283
  240. package/dist/react.js +309 -247
  241. package/dist/reasoning-Cackq4Rh.js +1 -0
  242. package/dist/register-impl-C7rENvPK.js +424 -0
  243. package/dist/{elements/chunks/resizable-Dpzjlvp4.js → resizable-Cp9HUYih.js} +1 -1
  244. package/dist/rotate-ccw-0DLRDHH5.js +1 -0
  245. package/dist/rotate-cw-DOB9IGcU.js +1 -0
  246. package/dist/schemas/form.schema.json +21 -1
  247. package/dist/schemas/index.d.ts +1 -1
  248. package/dist/schemas/tool-defs.d.ts +45 -0
  249. package/dist/schemas.js +398 -305
  250. package/dist/scroll-area-emVmWP4K.js +1 -0
  251. package/dist/scroll-button-CeP_gv1x.js +1 -0
  252. package/dist/select-CWmu00tS.js +1 -0
  253. package/dist/{elements/chunks/separator-DH2r_ZSZ.js → separator-CE6vly6z.js} +1 -1
  254. package/dist/{elements/chunks/settings-BFMOd6yB.js → settings-CE-78SvZ.js} +1 -1
  255. package/dist/{elements/chunks/settings-group-B3VZKIcz.js → settings-group-ZFWNxFQR.js} +1 -1
  256. package/dist/{elements/chunks/skeleton-N8BuWYmf.js → skeleton-BebdP4mf.js} +1 -1
  257. package/dist/slider-BAKRYUlz.js +1 -0
  258. package/dist/slots-DaNjX0rc.js +1 -0
  259. package/dist/{solid-BMuDmFo_.js → solid-BE5ui6sy.js} +10672 -8116
  260. package/dist/{solid-CGYNdLRR.js → solid-DFhsce3O.js} +8137 -6056
  261. package/dist/solid.d.ts +15 -0
  262. package/dist/solid.js +248 -235
  263. package/dist/solid.server.js +248 -235
  264. package/dist/source-B0FlguSx.js +1 -0
  265. package/dist/star-CBMZvLuN.js +1 -0
  266. package/dist/state/index.d.ts +5 -1
  267. package/dist/state/mock.d.ts +32 -2
  268. package/dist/state/persistence.d.ts +51 -0
  269. package/dist/state/stream.d.ts +50 -0
  270. package/dist/state/threads.d.ts +71 -0
  271. package/dist/state.js +297 -172
  272. package/dist/store-7eoadydQ.js +1 -0
  273. package/dist/svelte--5p79yCD.js +1 -15
  274. package/dist/switch-CViARZCy.js +1 -0
  275. package/dist/tasks-card-MjCcOhR_.js +1 -0
  276. package/dist/text-shimmer-DKlwRF2G.js +1 -0
  277. package/dist/textarea-3ay2Me2-.js +1 -0
  278. package/dist/theme.tokens.css +82 -13
  279. package/dist/{elements/chunks/thumbs-up-DQe0hvkZ.js → thumbs-up-DQcu2HMO.js} +1 -1
  280. package/dist/toast-store-C6yKOhbk.js +1 -0
  281. package/dist/{elements/chunks/tool-C1YtxwPu.js → tool-BCYNlfKy.js} +1 -1
  282. package/dist/{elements/chunks/tooltip-BqwnFWhn.js → tooltip-05zI4hjs.js} +1 -1
  283. package/dist/trash-2-BR1RxGky.js +1 -0
  284. package/dist/{elements/chunks/triangle-alert-B6or7F5u.js → triangle-alert-DHohDOCy.js} +1 -1
  285. package/dist/tsx-B8rCNbgL.js +1 -6
  286. package/dist/types.d.ts +4 -2
  287. package/dist/typescript-RycA9KXf.js +1 -6
  288. package/dist/ui/checkbox-group.d.ts +83 -0
  289. package/dist/ui/checkbox.d.ts +40 -0
  290. package/dist/ui/dock.d.ts +131 -0
  291. package/dist/ui/hover-card.d.ts +44 -0
  292. package/dist/ui/icon.d.ts +3 -0
  293. package/dist/ui/input.d.ts +48 -2
  294. package/dist/ui/radio.d.ts +85 -0
  295. package/dist/ui/select.d.ts +71 -0
  296. package/dist/ui/slider.d.ts +65 -0
  297. package/dist/ui/switch.d.ts +9 -2
  298. package/dist/upload-BbGW6A_u.js +1 -0
  299. package/dist/url-scheme-policy-DHpoTJwB.js +1 -0
  300. package/dist/use-card-resolution-CJW4grFa.js +1 -0
  301. package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-BUOVgPOB.js} +27 -27
  302. package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CUsUJvFI.js} +28 -28
  303. package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CW2i4bfr.js} +2 -2
  304. package/dist/{elements/chunks/variant-aurora-QXTZPyST.js → variant-aurora-xiMPty8f.js} +2 -2
  305. package/dist/variant-custom-BQtOnmeO.js +1 -0
  306. package/dist/{variant-custom-BhS9wIpU.js → variant-custom-CAm9L-E5.js} +65 -65
  307. package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-CAnzzppW.js} +40 -40
  308. package/dist/variant-custom-D91HjAKz.js +1 -0
  309. package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-Ca1Ls4_y.js} +21 -21
  310. package/dist/{variant-wave-CbVsmgwT.js → variant-wave-CxX39DKd.js} +25 -25
  311. package/dist/{variant-wave-BwzrHD1s.js → variant-wave-DYyzIIZv.js} +2 -2
  312. package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-uY5crU_K.js} +2 -2
  313. package/dist/vue-BmIZj4XD.js +1 -33
  314. package/dist/wire/chunk.d.ts +47 -0
  315. package/dist/wire/diagnostics.d.ts +575 -0
  316. package/dist/wire/encode-probe.d.ts +70 -0
  317. package/dist/wire/encode.d.ts +24 -0
  318. package/dist/wire/index.d.ts +2 -0
  319. package/dist/wire/sse.d.ts +10 -2
  320. package/dist/wire.js +917 -480
  321. package/dist/x-C5m1JFgi.js +1 -0
  322. package/frameworks/react/index.tsx +325 -108
  323. package/llms-full.txt +1354 -82
  324. package/llms.txt +6 -3
  325. package/package.json +39 -6
  326. package/src/agent-tooling/archetypes.ts +41 -9
  327. package/src/agent-tooling/catalog/README.md +676 -0
  328. package/src/agent-tooling/catalog/catalog-types.ts +231 -0
  329. package/src/agent-tooling/catalog/fabrications.ts +96 -0
  330. package/src/agent-tooling/catalog/invariants.ts +284 -0
  331. package/src/agent-tooling/catalog/labs-titles.ts +114 -0
  332. package/src/agent-tooling/catalog/scenarios.ts +87 -0
  333. package/src/agent-tooling/catalog/surfaces.ts +347 -0
  334. package/src/agent-tooling/construct/cli-entry.ts +8 -0
  335. package/src/agent-tooling/construct/cli.ts +131 -0
  336. package/src/agent-tooling/construct/codegen.ts +1353 -0
  337. package/src/agent-tooling/construct/construct.v1.schema.json +250 -0
  338. package/src/agent-tooling/construct/dev.ts +148 -0
  339. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +7 -0
  340. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +44 -0
  341. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +23 -0
  342. package/src/agent-tooling/construct/schema.ts +371 -0
  343. package/src/agent-tooling/integrations/anthropic.ts +7 -1
  344. package/src/agent-tooling/integrations/cloudflare.ts +43 -2
  345. package/src/agent-tooling/integrations/langgraph.ts +7 -1
  346. package/src/agent-tooling/integrations/mastra.ts +7 -1
  347. package/src/agent-tooling/integrations/mock.ts +92 -17
  348. package/src/agent-tooling/integrations/ollama.ts +7 -1
  349. package/src/agent-tooling/integrations/openai.ts +7 -1
  350. package/src/agent-tooling/integrations/openrouter.ts +7 -1
  351. package/src/agent-tooling/integrations/pi.ts +56 -1
  352. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
  353. package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
  354. package/src/agent-tooling/mcp/manifest.ts +100 -1
  355. package/src/agent-tooling/mcp/server.ts +63 -6
  356. package/src/agent-tooling/mcp/tools/construct.ts +130 -0
  357. package/src/agent-tooling/mcp/tools/debug.ts +126 -4
  358. package/src/agent-tooling/mcp/tools/reference.ts +542 -5
  359. package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
  360. package/src/agent-tooling/mcp/tools/theme.ts +146 -30
  361. package/src/agent-tooling/mcp/validate-args.ts +141 -0
  362. package/src/agent-tooling/recipes/composed-thread.ts +714 -0
  363. package/src/agent-tooling/recipes/index.ts +22 -0
  364. package/src/agent-tooling/recipes/types.ts +32 -0
  365. package/src/agent-tooling/registry.ts +24 -7
  366. package/src/agent-tooling/route-emit.ts +26 -2
  367. package/src/components/attachment-types.ts +54 -1
  368. package/src/components/attachments.tsx +169 -22
  369. package/src/components/audio-visualizer/fit-scale.ts +112 -0
  370. package/src/components/audio-visualizer/index.tsx +80 -3
  371. package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
  372. package/src/components/audio-visualizer/variant-bar.tsx +38 -6
  373. package/src/components/audio-visualizer/variant-custom.tsx +8 -2
  374. package/src/components/audio-visualizer/variant-grid.tsx +16 -11
  375. package/src/components/audio-visualizer/variant-radial.tsx +15 -10
  376. package/src/components/audio-visualizer/variant-wave.tsx +7 -2
  377. package/src/components/card-renderer.tsx +39 -8
  378. package/src/components/card.tsx +10 -2
  379. package/src/components/chat-container.tsx +4 -1
  380. package/src/components/chat-scope-picker.tsx +2 -2
  381. package/src/components/chat-thread.tsx +105 -13
  382. package/src/components/choice-card.tsx +102 -37
  383. package/src/components/coachmark.tsx +1 -1
  384. package/src/components/code-block.tsx +81 -5
  385. package/src/components/composer.tsx +89 -8
  386. package/src/components/confirm-card.tsx +20 -4
  387. package/src/components/conversation-item.tsx +138 -4
  388. package/src/components/conversation-list.tsx +230 -15
  389. package/src/components/embed.tsx +4 -0
  390. package/src/components/empty.tsx +14 -3
  391. package/src/components/file-tree.tsx +5 -1
  392. package/src/components/form-widgets.tsx +257 -195
  393. package/src/components/form.tsx +336 -21
  394. package/src/components/loader.tsx +12 -5
  395. package/src/components/message-skills.tsx +1 -1
  396. package/src/components/message.tsx +142 -12
  397. package/src/components/prompt-input.tsx +7 -1
  398. package/src/components/prompt-suggestion.tsx +4 -1
  399. package/src/components/reasoning.tsx +30 -3
  400. package/src/components/response-compare.tsx +2 -2
  401. package/src/components/response-stream.tsx +13 -7
  402. package/src/components/screen.tsx +5 -0
  403. package/src/components/scroll-button.tsx +63 -4
  404. package/src/components/source.tsx +6 -1
  405. package/src/components/tasks-card.tsx +58 -16
  406. package/src/components/thread.tsx +10 -1
  407. package/src/components/toast.tsx +11 -5
  408. package/src/components/tool-types.ts +9 -0
  409. package/src/components/voice-input.tsx +35 -3
  410. package/src/components/voice-output.tsx +46 -6
  411. package/src/components/workspace-shell.tsx +285 -0
  412. package/src/diagnostics/hook.ts +352 -0
  413. package/src/diagnostics/index.ts +82 -0
  414. package/src/diagnostics/report-request.ts +296 -0
  415. package/src/elements/attachments.tsx +9 -8
  416. package/src/elements/audio-visualizer.tsx +48 -4
  417. package/src/elements/chat-workspace.tsx +159 -287
  418. package/src/elements/chat.tsx +31 -10
  419. package/src/elements/checkbox-group.tsx +164 -0
  420. package/src/elements/checkbox.tsx +134 -0
  421. package/src/elements/code-block.tsx +19 -1
  422. package/src/elements/command.tsx +4 -1
  423. package/src/elements/compiled.css +1 -1
  424. package/src/elements/composer.tsx +12 -1
  425. package/src/elements/conversation-item.tsx +120 -0
  426. package/src/elements/conversation-list.tsx +60 -11
  427. package/src/elements/default-input.tsx +5 -5
  428. package/src/elements/define-entry.ts +12 -0
  429. package/src/elements/define.tsx +168 -8
  430. package/src/elements/diagnostic-events.ts +114 -0
  431. package/src/elements/dialog.tsx +47 -0
  432. package/src/elements/disclosure.ts +34 -12
  433. package/src/elements/dock.tsx +215 -0
  434. package/src/elements/dropdown.tsx +123 -0
  435. package/src/elements/element-data-types.ts +40 -0
  436. package/src/elements/element-diagnostics.ts +392 -0
  437. package/src/elements/element-manifest.json +36 -0
  438. package/src/elements/element-meta.json +1483 -560
  439. package/src/elements/element-nonscalar.json +185 -0
  440. package/src/elements/element-types.d.ts +589 -167
  441. package/src/elements/feedback-bar.tsx +5 -0
  442. package/src/elements/icon-names.json +29 -0
  443. package/src/elements/input.tsx +312 -23
  444. package/src/elements/menu.tsx +13 -0
  445. package/src/elements/message.tsx +2 -0
  446. package/src/elements/pane-grid.tsx +111 -0
  447. package/src/elements/prompt-dock.tsx +2 -1
  448. package/src/elements/prompt-input.tsx +16 -10
  449. package/src/elements/radio-group.tsx +129 -0
  450. package/src/elements/register-impl.ts +52 -0
  451. package/src/elements/register.ts +28 -0
  452. package/src/elements/resizable.tsx +52 -25
  453. package/src/elements/scroll-button.tsx +59 -6
  454. package/src/elements/select.tsx +165 -0
  455. package/src/elements/slider.tsx +171 -0
  456. package/src/elements/slots.ts +108 -13
  457. package/src/elements/styles.css +119 -9
  458. package/src/elements/thinking-bar.tsx +16 -7
  459. package/src/elements/thread.tsx +2 -0
  460. package/src/elements/toast.tsx +17 -1
  461. package/src/elements/tool.tsx +26 -5
  462. package/src/elements/voice-input.tsx +11 -2
  463. package/src/elements/voice-output.tsx +16 -3
  464. package/src/index.ts +4 -1
  465. package/src/primitives/card-data-types.ts +49 -0
  466. package/src/primitives/card-host.tsx +4 -2
  467. package/src/primitives/card-routing.ts +7 -56
  468. package/src/primitives/card-schemas/form.schema.json +21 -1
  469. package/src/primitives/card-validate.ts +10 -2
  470. package/src/primitives/chat-config.tsx +33 -6
  471. package/src/primitives/field-mask.ts +256 -0
  472. package/src/primitives/field-semantics.ts +115 -0
  473. package/src/primitives/input-mask.ts +853 -0
  474. package/src/primitives/toast-store.ts +66 -4
  475. package/src/primitives/url-scheme-policy.ts +70 -0
  476. package/src/primitives/use-resize-observer.ts +33 -0
  477. package/src/primitives/use-speech-recognition.ts +12 -1
  478. package/src/primitives/use-stick-to-bottom.ts +34 -2
  479. package/src/primitives/use-text-stream.ts +33 -2
  480. package/src/remote/provider-runtime.ts +6 -3
  481. package/src/schemas/index.ts +1 -0
  482. package/src/schemas/tool-defs.ts +307 -6
  483. package/src/solid.ts +15 -0
  484. package/src/state/index.ts +13 -1
  485. package/src/state/mock.ts +92 -6
  486. package/src/state/persistence.ts +180 -0
  487. package/src/state/stream.ts +71 -4
  488. package/src/state/threads.ts +142 -0
  489. package/src/types.ts +4 -2
  490. package/src/ui/agent-card.tsx +2 -2
  491. package/src/ui/avatar.tsx +1 -1
  492. package/src/ui/checkbox-group.tsx +153 -0
  493. package/src/ui/checkbox.tsx +63 -0
  494. package/src/ui/dialog.tsx +6 -0
  495. package/src/ui/dock.tsx +584 -0
  496. package/src/ui/dropdown.tsx +67 -23
  497. package/src/ui/hover-card.tsx +156 -6
  498. package/src/ui/icon.tsx +53 -0
  499. package/src/ui/input.tsx +275 -16
  500. package/src/ui/kbd.tsx +1 -1
  501. package/src/ui/nav.tsx +1 -1
  502. package/src/ui/pane-group.tsx +2 -2
  503. package/src/ui/radio.tsx +150 -0
  504. package/src/ui/resizable.tsx +11 -0
  505. package/src/ui/select.tsx +168 -0
  506. package/src/ui/slider.tsx +178 -0
  507. package/src/ui/switch.tsx +49 -18
  508. package/src/utils/cn.ts +11 -5
  509. package/src/wire/chunk.ts +47 -0
  510. package/src/wire/consume.ts +185 -26
  511. package/src/wire/diagnostics.ts +727 -0
  512. package/src/wire/encode-probe.ts +214 -0
  513. package/src/wire/encode.ts +267 -14
  514. package/src/wire/formats/anthropic.ts +8 -1
  515. package/src/wire/formats/openai.ts +5 -0
  516. package/src/wire/index.ts +22 -0
  517. package/src/wire/read.ts +250 -6
  518. package/src/wire/sse.ts +16 -3
  519. package/theme.css +84 -13
  520. package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
  521. package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
  522. package/dist/elements/chunks/artifact-BSuPYFHY.js +0 -1
  523. package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
  524. package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
  525. package/dist/elements/chunks/badge-TIMiJFKc.js +0 -1
  526. package/dist/elements/chunks/bash-InADTalH.js +0 -1
  527. package/dist/elements/chunks/card-renderer-CSoTL_e1.js +0 -1
  528. package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
  529. package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
  530. package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
  531. package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
  532. package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
  533. package/dist/elements/chunks/choice-card-CGMc3kek.js +0 -1
  534. package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
  535. package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
  536. package/dist/elements/chunks/circle-x-mhH7pOK2.js +0 -1
  537. package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
  538. package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
  539. package/dist/elements/chunks/composer-CZZmtYOT.js +0 -69
  540. package/dist/elements/chunks/confirm-card-BWjf2-xo.js +0 -1
  541. package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
  542. package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
  543. package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
  544. package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
  545. package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
  546. package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
  547. package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
  548. package/dist/elements/chunks/download-DnCyWFJE.js +0 -1
  549. package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
  550. package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
  551. package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
  552. package/dist/elements/chunks/file-text-D0J9F6M7.js +0 -1
  553. package/dist/elements/chunks/folder-NV1pi_ud.js +0 -1
  554. package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
  555. package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
  556. package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
  557. package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
  558. package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
  559. package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
  560. package/dist/elements/chunks/info-C8r5Q6cc.js +0 -1
  561. package/dist/elements/chunks/input-DrseEjhp.js +0 -1
  562. package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
  563. package/dist/elements/chunks/json-DxJze_jm.js +0 -1
  564. package/dist/elements/chunks/kbd-OGJDUT-O.js +0 -1
  565. package/dist/elements/chunks/link-BdsfLB7b.js +0 -1
  566. package/dist/elements/chunks/loader-B5QzK_8_.js +0 -1
  567. package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
  568. package/dist/elements/chunks/message-DtXKPqiR.js +0 -1
  569. package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
  570. package/dist/elements/chunks/paperclip-Bg0ITU3b.js +0 -1
  571. package/dist/elements/chunks/progress-bar-D1_rzt6N.js +0 -1
  572. package/dist/elements/chunks/prompt-suggestion-D5Sm8xF1.js +0 -1
  573. package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
  574. package/dist/elements/chunks/rotate-cw-DzVDJOA1.js +0 -1
  575. package/dist/elements/chunks/scroll-area-93A1bbeG.js +0 -1
  576. package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
  577. package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
  578. package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
  579. package/dist/elements/chunks/source-w9V0NnBn.js +0 -1
  580. package/dist/elements/chunks/star-DHvACxtm.js +0 -1
  581. package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
  582. package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
  583. package/dist/elements/chunks/tasks-card-lPxoodlA.js +0 -1
  584. package/dist/elements/chunks/text-shimmer-BY_rI3s5.js +0 -1
  585. package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
  586. package/dist/elements/chunks/toast-store-VUZZBhzH.js +0 -1
  587. package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
  588. package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
  589. package/dist/elements/chunks/use-card-resolution-DJg32jGH.js +0 -1
  590. package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
  591. package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
  592. package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
  593. package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
  594. package/dist/llms/llms-full.txt +0 -2834
  595. package/dist/llms/llms.txt +0 -156
  596. package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
  597. package/dist/register-impl-DGmGzrEM.js +0 -145
  598. package/dist/ui/stat.d.ts +0 -16
  599. package/dist/variant-custom-MkTNTycd.js +0 -1
  600. package/src/primitives/card-validate-generator.testlib.ts +0 -38
  601. package/src/ui/stat.tsx +0 -41
  602. /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
  603. /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
@@ -1,148 +1,125 @@
1
- import { Show, createSignal, onMount, onCleanup } from 'solid-js';
1
+ import { createSignal, onMount, onCleanup, untrack } from 'solid-js';
2
2
  import { defineWebComponent } from './define';
3
- import { createControllableSignal } from '../primitives/controllable';
4
3
  import { readSlots, WORKSPACE_SLOTS } from './slots';
5
- import { ChatThread, type ChatThreadContextUsage, type ChatThreadController } from '../components/chat-thread';
6
- import { ConversationList, CollapsedRail } from '../components/conversation-list';
7
- import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../ui/resizable';
8
- import { cardComponentsFromTags } from './message';
9
- import { createMessagesGuard } from './validate-messages';
10
- import type { AttachmentData } from '../components/attachments';
11
- import type { TriggerDef } from '../components/composer';
12
- import type { ChatMessage } from './chat-types';
13
- import type { ProseSize } from '../primitives/chat-config';
14
- import type { ModelOption, ConversationGroup, ConversationSummary } from '../types';
4
+ import {
5
+ WorkspaceShell,
6
+ type WorkspaceShellController,
7
+ type WorkspaceAsideSide,
8
+ type WorkspaceAsideToggleDetail,
9
+ type WorkspaceAsideResizeDetail,
10
+ } from '../components/workspace-shell';
15
11
 
16
12
  interface Props extends Record<string, unknown> {
17
- /** The sidebar's section headers, rendered in array order. A group carries no
18
- * conversations of its own; it is matched against `conversations` by id, so
19
- * the two props are complementary rather than alternatives. Omit for an
20
- * ungrouped sidebar. Set as a JS property. */
21
- groups?: ConversationGroup[];
22
- /** Every conversation in the sidebar, flat. Each one is filed under the group
23
- * whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId`
24
- * matching no entry in `groups`, falls into a trailing ungrouped section
25
- * (headerless when `compact`), so nothing you pass in is ever dropped. There is
26
- * no recency bucketing. Set as a JS property. Omit for an empty sidebar, or
27
- * when `no-conversations` replaces the built-in list with your own
28
- * `sidebar-header` content. */
29
- conversations?: ConversationSummary[];
30
- /** Id of the open conversation, highlighted in the sidebar. */
31
- activeId?: string;
32
- /** The active conversation's message thread, newest last. Set as a JS property
33
- * (`el.messages = [...]`); a NEW array reference per streaming chunk
34
- * re-renders (mutating in place does not). Omit for an empty thread. */
35
- messages?: ChatMessage[];
36
- value?: string;
37
- placeholder?: string;
38
- loading?: boolean;
39
- suggestions?: string[];
40
- suggestionMode?: 'submit' | 'fill';
41
- proseSize?: ProseSize;
42
- codeTheme?: string;
43
- codeHighlight?: boolean;
44
- chatTitle?: string;
45
- models?: ModelOption[];
46
- currentModel?: string;
47
- context?: ChatThreadContextUsage;
48
- scrollButton?: boolean;
49
- search?: boolean;
50
- voice?: boolean;
51
- /** Rich entity triggers (`/` skills, `@` agents/plugins) forwarded to the input. */
52
- triggers?: TriggerDef[];
53
- /** Default icon per entity kind (kind → image src) forwarded to the input. */
54
- kindIcons?: Record<string, string>;
55
- /** Sidebar default width as a percent of the workspace (default 26). */
56
- sidebarWidth?: number;
57
- /** Sidebar min width in px (default 240). */
58
- sidebarMinWidth?: number;
59
- /** Sidebar max width in px (default 420). */
60
- sidebarMaxWidth?: number;
61
- /** Controlled collapsed state. Set this as a JS property (`el.sidebarCollapsed
62
- * = true`) to drive the sidebar from your app, updating it in response to the
63
- * `kai-sidebar-toggle` event. Omit for uncontrolled (the element manages it). */
64
- sidebarCollapsed?: boolean;
65
- /** Initial collapsed state when uncontrolled (default false). Use the
66
- * `default-sidebar-collapsed` attribute to start collapsed in plain HTML. */
67
- defaultSidebarCollapsed?: boolean;
68
- /** Auto-collapse the rail when the workspace's own width drops below this many
69
- * px, and re-expand when it grows back above. Uncontrolled only (it never
70
- * fights an app-driven `sidebarCollapsed`); omit to disable. Fires
71
- * `kai-sidebar-toggle`. Attribute: `collapse-below`. */
13
+ /** Controlled collapsed state of the start aside. Set this as a JS property
14
+ * (`el.startCollapsed = true`) to drive the aside from your app, updating it
15
+ * in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
16
+ * element manages it). */
17
+ startCollapsed?: boolean;
18
+ /** Initial collapsed state of the start aside when uncontrolled (default
19
+ * false). Use the `default-start-collapsed` attribute to start collapsed in
20
+ * plain HTML. */
21
+ defaultStartCollapsed?: boolean;
22
+ /** Controlled collapsed state of the end aside. Set this as a JS property
23
+ * (`el.endCollapsed = true`) to drive the aside from your app, updating it
24
+ * in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
25
+ * element manages it). */
26
+ endCollapsed?: boolean;
27
+ /** Initial collapsed state of the end aside when uncontrolled (default
28
+ * false). Use the `default-end-collapsed` attribute to start collapsed in
29
+ * plain HTML. */
30
+ defaultEndCollapsed?: boolean;
31
+ /** Auto-collapse both asides when the shell's own width drops below this many
32
+ * px, and re-expand when it grows back above. Applies to uncontrolled asides
33
+ * only (it never fights an app-driven collapsed prop); omit to disable.
34
+ * Fires `kai-aside-toggle`. Attribute: `collapse-below`. */
72
35
  collapseBelow?: number;
73
- /** Render Recents as dense single-line rows (a leading dot + title, no count). */
36
+ /** Below this shell width in px, an expanded aside renders as an overlay
37
+ * drawer over the main region instead of a column beside it. Escape inside
38
+ * the drawer closes it and returns focus to the element focused before it
39
+ * opened. Omit to disable. Attribute: `drawer-below`. */
40
+ drawerBelow?: number;
41
+ /** Density hint. Reflected as a `data-compact` hook on the root (and as the
42
+ * `compact` attribute on the element) for your CSS and slotted content; the
43
+ * shell itself keeps no other opinion about density. */
74
44
  compact?: boolean;
75
- /** Suppress the built-in ConversationList so the `sidebar-header` slot owns the
76
- * whole rail flex region (for apps that supply their own rail nav). Default
77
- * false. Attribute: `no-conversations`. */
78
- noConversations?: boolean;
79
- /** Optional card type -> custom-element tag overrides/additions for `card`
80
- * parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a
81
- * plain string map (not the `CardTagMap` alias) so the generated React
82
- * wrapper inlines it instead of emitting an unresolved named type. */
83
- cardTypes?: Record<string, string>;
84
- /** JSON Schemas for the card types this app renders, keyed by envelope type. The
85
- * companion of `cardTypes`, which says what DRAWS a card while this says what a
86
- * VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas
87
- * = { 'pricing-table': pricingSchema }`, never an attribute.
88
- * `createCardRegistry(...).validationSchemas` is exactly this shape.
89
- *
90
- * Without it the kit validates its own seven built-ins and leaves your own card
91
- * type, the one your app actually cares about, as the only unchecked thing on
92
- * screen. A schema here WINS over a built-in of the same name.
93
- *
94
- * Typed `Record<string, object>` rather than `Record<string, JsonSchema>`
95
- * deliberately: an imported `.json` schema widens `"type"` to `string`, and an
96
- * authored one carries `$schema`/`title`/`description`/`additionalProperties`,
97
- * so the tighter type would reject both of the normal ways to supply one. */
98
- cardSchemas?: Record<string, object>;
99
45
  }
100
46
 
47
+ /** Events fired by `<kai-workspace>`. Layout only: every chat event now belongs
48
+ * to the part that fires it, inside your own markup. */
101
49
  interface Events {
102
- /** A conversation was selected in the sidebar. */
103
- 'kai-conversation-select': { id: string };
104
- /** The "New chat" button was clicked. */
105
- 'kai-new-chat': Record<string, never>;
106
- /** The sidebar was collapsed or expanded. */
107
- 'kai-sidebar-toggle': { collapsed: boolean };
108
- /** User submitted a message. */
109
- 'kai-submit': { value: string; attachments: AttachmentData[] };
110
- /** Fired on every input change. */
111
- 'kai-value-change': { value: string };
112
- /** The header model switcher changed. */
113
- 'kai-model-change': { modelId: string };
114
- /** An action button on a message was clicked. `state` is present only for the
115
- * toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when
116
- * re-tapped to clear. */
117
- 'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
118
- /** The Search button was clicked. */
119
- 'kai-search': Record<string, never>;
120
- /** The Mic / voice button was clicked. */
121
- 'kai-voice': Record<string, never>;
122
- /** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
123
- 'kai-suggestion-click': { value: string };
50
+ /** An aside collapsed or expanded (a method, the breakpoint, the drawer's Escape). */
51
+ 'kai-aside-toggle': WorkspaceAsideToggleDetail;
52
+ /** The aside was resized (fires per drag step, keyboard nudge, or a handle double-click reset), width in px. */
53
+ 'kai-aside-resize': WorkspaceAsideResizeDetail;
124
54
  }
125
55
 
56
+ /**
57
+ * `<kai-workspace>` — the chat-agnostic layout shell: five slots (`header` ·
58
+ * `start` · `main` · `end` · `footer`), resize handles between the columns,
59
+ * per-aside collapse, collapse-below-breakpoint, and a mobile drawer mode for
60
+ * the asides. It knows nothing about chat: a file tree in `start` is as valid
61
+ * as `<kai-conversations>`, and the workspace app slots `<kai-conversations>`
62
+ * and `<kai-chat>` into it.
63
+ *
64
+ * ```html
65
+ * <kai-workspace collapse-below="720" drawer-below="640">
66
+ * <kai-conversations slot="start"></kai-conversations>
67
+ * <kai-chat></kai-chat>
68
+ * </kai-workspace>
69
+ * ```
70
+ *
71
+ * Aside geometry is CSS custom properties, not props (the `kai-dock` rule):
72
+ * `--kai-workspace-start-width` (280px) · `--kai-workspace-start-min-width`
73
+ * (200px) · `--kai-workspace-start-max-width` (480px) · `--kai-workspace-end-width`
74
+ * (320px) · `--kai-workspace-end-min-width` (200px) · `--kai-workspace-end-max-width`
75
+ * (480px). Read once at upgrade. Parts: `header` · `start` · `main` · `end` ·
76
+ * `footer` (the asides also match `::part(aside)`).
77
+ *
78
+ * **BREAKING (0.24):** this element was a chat
79
+ * preset; it is now a layout shell, and everything chat-shaped is gone from its
80
+ * surface. Where each removed prop went:
81
+ *
82
+ * - `conversations` / `activeId` / `groups` / `noConversations`: set them on your
83
+ * own `<kai-conversations slot="start">`.
84
+ * - `messages` / `loading` / `proseSize` / `codeTheme` / `codeHighlight` /
85
+ * `chatTitle` / `scrollButton` / `cardTypes` / `cardSchemas`: set them on your
86
+ * own `<kai-chat>` in the main region.
87
+ * - `value` / `placeholder` / `suggestions` / `suggestionMode` / `voice` /
88
+ * `triggers` / `kindIcons` and the renamed `webSearch` (was `search`): the
89
+ * composer surface on `<kai-chat>` or `<kai-prompt-input>`.
90
+ * - `models` / `currentModel` / `context`: header chrome you slot (a model
91
+ * picker is a part in a slot, not three orchestrator props).
92
+ * - `sidebarWidth` / `sidebarMinWidth` / `sidebarMaxWidth`: the
93
+ * `--kai-workspace-start-*` custom properties above.
94
+ * - `sidebarCollapsed` / `defaultSidebarCollapsed`: `startCollapsed` /
95
+ * `defaultStartCollapsed` (per-aside; the end aside has its own pair).
96
+ * - `collapseBelow`: kept, now collapsing both asides.
97
+ * - `compact`: kept as a reflected density hint; the rail's row density is
98
+ * `<kai-conversations>`' own `compact`.
99
+ * - Chat events (`kai-submit`, `kai-conversation-select`, `kai-message-action`,
100
+ * `kai-model-change`, `kai-search`, `kai-voice`, `kai-value-change`,
101
+ * `kai-suggestion-click`): listen on the part that fires them.
102
+ * `kai-sidebar-toggle` is now `kai-aside-toggle` with a `side`.
103
+ * - Methods: `toggleSidebar()` / `collapseSidebar()` / `expandSidebar()` are now
104
+ * `toggleAside(side)` / `collapseAside(side)` / `expandAside(side)`; the
105
+ * thread methods (`focus`/`clear`/`send`/`scrollToBottom`) live on your
106
+ * `<kai-chat>`.
107
+ *
108
+ * The migration path for a full app is the `workspace` block scaffold (the kai
109
+ * MCP `scaffold` tool), which emits this composition wired.
110
+ */
126
111
  defineWebComponent<Props, Events>('kai-workspace', {
127
- groups: [], conversations: [], activeId: undefined, messages: [],
128
- value: undefined, placeholder: 'Send a message...', loading: false,
129
- suggestions: undefined, suggestionMode: 'submit', proseSize: 'sm',
130
- codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
131
- models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
132
- search: false, voice: false, triggers: undefined, kindIcons: undefined,
133
- sidebarWidth: 26, sidebarMinWidth: 240, sidebarMaxWidth: 420,
134
- sidebarCollapsed: undefined, defaultSidebarCollapsed: undefined, collapseBelow: undefined, compact: undefined,
135
- noConversations: undefined, cardTypes: undefined, cardSchemas: undefined,
136
- }, (props, { dispatch, flag, expose, element }) => {
137
- // `messages` is an untyped boundary: a consumer can hand it anything at
138
- // runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
139
- // the invalid entries rather than let `groupMessageParts` throw deep inside a
140
- // render pass, which would blank the whole workspace instead of one message.
141
- const validMessages = createMessagesGuard('kai-workspace');
142
-
143
- // Which injection slots the consumer has filled. A bare <slot> is always a
144
- // truthy JSX node, so we render each region wrapper ONLY when readSlots reports
145
- // projected light-DOM content (re-read on childList mutation).
112
+ startCollapsed: undefined,
113
+ defaultStartCollapsed: undefined,
114
+ endCollapsed: undefined,
115
+ defaultEndCollapsed: undefined,
116
+ collapseBelow: undefined,
117
+ drawerBelow: undefined,
118
+ compact: undefined,
119
+ }, (props, { dispatch, flag, expose, element, reflectFlag }) => {
120
+ // Which slots the consumer has filled. A bare <slot> is always a truthy JSX
121
+ // node, so each optional region renders ONLY when readSlots reports projected
122
+ // light-DOM content (re-read on childList mutation). Main always renders.
146
123
  const [slots, setSlots] = createSignal<Record<string, boolean>>({});
147
124
  onMount(() => {
148
125
  const read = () => setSlots(readSlots(element, WORKSPACE_SLOTS));
@@ -152,165 +129,60 @@ defineWebComponent<Props, Events>('kai-workspace', {
152
129
  onCleanup(() => observer.disconnect());
153
130
  });
154
131
 
155
- // Controlled/uncontrolled collapse: `sidebarCollapsed` (when set) wins;
156
- // otherwise the element manages its own state, seeded from
157
- // `defaultSidebarCollapsed`. `setCollapsedTo` always writes the internal value (a
158
- // no-op visually while controlled) and emits `kai-sidebar-toggle` so a controlling
159
- // app can update its own state.
160
- const [collapsed, setCollapsed] = createControllableSignal(
161
- () => props.sidebarCollapsed as boolean | undefined,
162
- flag('defaultSidebarCollapsed'),
163
- );
164
- const setCollapsedTo = (next: boolean) => { setCollapsed(next); dispatch('kai-sidebar-toggle', { collapsed: next }); };
165
- const toggle = () => setCollapsedTo(!collapsed());
132
+ // Reflect the read-back flags (the G-05 rule: a bare attribute parses to
133
+ // `undefined`, so without this the property would contradict the attribute).
134
+ reflectFlag('compact');
135
+ reflectFlag('defaultStartCollapsed');
136
+ reflectFlag('defaultEndCollapsed');
166
137
 
167
- // Responsive auto-collapse. When `collapseBelow` is set, a ResizeObserver on the
168
- // workspace root collapses the rail once the workspace's own width drops below
169
- // it and re-expands above it. Uncontrolled only — bail while `sidebarCollapsed`
170
- // is set so we never fight an app-driven collapse. `autoCollapsed` tracks whether
171
- // WE collapsed it, so a user's manual expand isn't auto-undone on the next tick.
172
- let rootEl!: HTMLDivElement;
173
- let autoCollapsed = false;
174
- onMount(() => {
175
- if (typeof ResizeObserver === 'undefined') return;
176
- const ro = new ResizeObserver((entries) => {
177
- const below = props.collapseBelow as number | undefined;
178
- if (below == null || props.sidebarCollapsed !== undefined) return;
179
- const width = entries[0]?.contentRect.width ?? rootEl.clientWidth;
180
- const isBelow = width < below;
181
- if (isBelow && !collapsed()) {
182
- autoCollapsed = true;
183
- setCollapsedTo(true);
184
- } else if (!isBelow && collapsed() && autoCollapsed) {
185
- autoCollapsed = false;
186
- setCollapsedTo(false);
187
- }
188
- });
189
- ro.observe(rootEl);
190
- onCleanup(() => ro.disconnect());
191
- });
138
+ // Aside geometry from the element's CSS custom properties, read once at
139
+ // upgrade (inline style first so jsdom, which does not resolve custom
140
+ // properties through getComputedStyle, still honors a direct set).
141
+ const readVar = (name: string, fallback: number): number => {
142
+ const inline = element.style.getPropertyValue(name).trim();
143
+ const computed = inline || getComputedStyle(element).getPropertyValue(name).trim();
144
+ const n = parseFloat(computed);
145
+ return Number.isFinite(n) ? n : fallback;
146
+ };
147
+ const geometry = untrack(() => ({
148
+ startWidth: readVar('--kai-workspace-start-width', 280),
149
+ startMinWidth: readVar('--kai-workspace-start-min-width', 200),
150
+ startMaxWidth: readVar('--kai-workspace-start-max-width', 480),
151
+ endWidth: readVar('--kai-workspace-end-width', 320),
152
+ endMinWidth: readVar('--kai-workspace-end-min-width', 200),
153
+ endMaxWidth: readVar('--kai-workspace-end-max-width', 480),
154
+ }));
192
155
 
193
- // Imperative method API. The sidebar methods drive the same collapse path as the
194
- // in-UI toggle (named *Sidebar to avoid the `sidebarCollapsed` prop accessor).
195
- // The thread methods delegate to the embedded ChatThread's controller, captured
196
- // once below — the thread node is shared across both <Show> branches, so a single
197
- // controllerRef is stable across collapse/expand.
198
- let controller: ChatThreadController | undefined;
156
+ let controller: WorkspaceShellController | undefined;
199
157
  expose({
200
- /** Collapse/expand the conversation sidebar and fire `kai-sidebar-toggle`. */
201
- toggleSidebar: () => toggle(),
202
- /** Force the conversation sidebar collapsed (fires `kai-sidebar-toggle`). */
203
- collapseSidebar: () => setCollapsedTo(true),
204
- /** Force the conversation sidebar expanded (fires `kai-sidebar-toggle`). */
205
- expandSidebar: () => setCollapsedTo(false),
206
- /** Focus the thread's composer. */
207
- focus: (options?: FocusOptions) => controller?.focus(options),
208
- /** Clear the thread draft + staged attachments. */
209
- clear: () => controller?.clear(),
210
- /** Submit the current thread draft programmatically (fires `kai-submit`). */
211
- send: () => controller?.send(),
212
- /** Scroll the thread to the newest message. */
213
- scrollToBottom: (behavior?: ScrollBehavior) => controller?.scrollToBottom(behavior),
158
+ /** Collapse/expand one aside (fires `kai-aside-toggle`). */
159
+ toggleAside: (side: WorkspaceAsideSide) => controller?.toggleAside(side),
160
+ /** Force one aside collapsed (fires `kai-aside-toggle`). */
161
+ collapseAside: (side: WorkspaceAsideSide) => controller?.collapseAside(side),
162
+ /** Force one aside expanded (fires `kai-aside-toggle`). */
163
+ expandAside: (side: WorkspaceAsideSide) => controller?.expandAside(side),
214
164
  });
215
165
 
216
- // Create the thread ONCE and reference the same node in both <Show> branches.
217
- // It's owned by this component root (not by a Show branch), so toggling the
218
- // sidebar moves the node between branches without disposing it — the thread's
219
- // own state (e.g. an uncontrolled draft) survives the collapse/expand.
220
- const threadEl = (
221
- <ChatThread
222
- messages={validMessages(props.messages)} value={props.value as string | undefined} placeholder={props.placeholder as string}
223
- loading={flag('loading')} suggestions={props.suggestions as string[] | undefined}
224
- suggestionMode={props.suggestionMode as 'submit' | 'fill'} proseSize={props.proseSize as ProseSize}
225
- codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
226
- chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
227
- currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
228
- scrollButton={props.scrollButton !== false} search={flag('search')} voice={flag('voice')}
229
- triggers={props.triggers as TriggerDef[] | undefined}
230
- kindIcons={props.kindIcons as Record<string, string> | undefined}
231
- cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
232
- cardSchemas={props.cardSchemas as Record<string, object> | undefined}
233
- onValueChange={(value) => dispatch('kai-value-change', { value })}
234
- onSubmit={(detail) => dispatch('kai-submit', detail)}
235
- onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
236
- onModelChange={(modelId) => dispatch('kai-model-change', { modelId })}
237
- onMessageAction={(detail) => dispatch('kai-message-action', detail)}
238
- onSearch={() => dispatch('kai-search', {})}
239
- onVoice={() => dispatch('kai-voice', {})}
240
- controllerRef={(c) => (controller = c)}
241
- />
242
- );
243
-
244
- // The main region: an optional top-placed `main-header` band above the thread.
245
- // Shared across both collapse branches (the thread node is the same instance).
246
- const mainRegion = (
247
- <div class="flex h-full flex-col overflow-hidden">
248
- <Show when={slots()['main-header']}>
249
- <div class="shrink-0 border-b border-border"><slot name="main-header" /></div>
250
- </Show>
251
- <div class="min-h-0 flex-1">
252
- <Show when={slots()['main']} fallback={threadEl}>
253
- <slot name="main" />
254
- </Show>
255
- </div>
256
- </div>
257
- );
258
-
259
166
  return (
260
- <div ref={rootEl} class="h-full w-full overflow-hidden bg-background">
261
- <Show
262
- when={!collapsed()}
263
- fallback={
264
- <div class="flex h-full">
265
- {/* Collapsed: the reopen control lives in its OWN thin rail column
266
- (matching the sidebar's bg-surface) rather than floating over the
267
- content. The previous `absolute` overlay sat on top of a
268
- `main-header`'s leading title — see the t3code/codex/chatgpt apps,
269
- all of which fill that slot — so it both overlapped the header and
270
- competed with any in-header toggle. A dedicated column never
271
- overlaps and reads as a collapsed sidebar. */}
272
- <div class="flex w-11 shrink-0 flex-col items-center border-r border-border bg-surface pt-2.5">
273
- <CollapsedRail onExpand={toggle} class="bg-transparent shadow-none backdrop-blur-none" />
274
- </div>
275
- <div class="min-w-0 flex-1">{mainRegion}</div>
276
- </div>
277
- }
278
- >
279
- <ResizablePanelGroup orientation="horizontal">
280
- <ResizablePanel defaultSize={props.sidebarWidth as number} data-min-size={String(props.sidebarMinWidth)} data-max-size={String(props.sidebarMaxWidth)}>
281
- {/* The rail: an optional injected header above the list and footer
282
- below it (upgrade card / Design trigger / user menu). Carries a
283
- subtle, theme-aware default background (bg-surface), exposed as
284
- ::part(sidebar) so a consumer can override it. The inner list is
285
- made transparent so the part background reads uniformly. */}
286
- <div part="sidebar" class="flex h-full flex-col overflow-hidden bg-surface">
287
- <Show when={slots()['sidebar-header']}>
288
- {/* When `no-conversations` suppresses the built-in list, the
289
- projected header owns the whole rail flex region; otherwise it
290
- sits as a fixed band above the list. */}
291
- <div class={flag('noConversations') ? 'min-h-0 flex-1' : 'shrink-0'}><slot name="sidebar-header" /></div>
292
- </Show>
293
- <Show when={!flag('noConversations')}>
294
- <div class="min-h-0 flex-1">
295
- <ConversationList
296
- class="bg-transparent"
297
- groups={props.groups ?? []} conversations={props.conversations ?? []} activeId={props.activeId as string | undefined}
298
- compact={flag('compact')}
299
- onSelect={(id) => dispatch('kai-conversation-select', { id })}
300
- onNewChat={() => dispatch('kai-new-chat', {})}
301
- onToggleSidebar={toggle}
302
- />
303
- </div>
304
- </Show>
305
- <Show when={slots()['sidebar-footer']}>
306
- <div class="shrink-0"><slot name="sidebar-footer" /></div>
307
- </Show>
308
- </div>
309
- </ResizablePanel>
310
- <ResizableHandle />
311
- <ResizablePanel>{mainRegion}</ResizablePanel>
312
- </ResizablePanelGroup>
313
- </Show>
314
- </div>
167
+ <WorkspaceShell
168
+ header={slots()['header'] ? <slot name="header" /> : undefined}
169
+ start={slots()['start'] ? <slot name="start" /> : undefined}
170
+ end={slots()['end'] ? <slot name="end" /> : undefined}
171
+ footer={slots()['footer'] ? <slot name="footer" /> : undefined}
172
+ startCollapsed={props.startCollapsed as boolean | undefined}
173
+ defaultStartCollapsed={flag('defaultStartCollapsed')}
174
+ endCollapsed={props.endCollapsed as boolean | undefined}
175
+ defaultEndCollapsed={flag('defaultEndCollapsed')}
176
+ collapseBelow={props.collapseBelow as number | undefined}
177
+ drawerBelow={props.drawerBelow as number | undefined}
178
+ compact={flag('compact')}
179
+ {...geometry}
180
+ onAsideToggle={(detail) => dispatch('kai-aside-toggle', detail)}
181
+ onAsideResize={(detail) => dispatch('kai-aside-resize', detail)}
182
+ controllerRef={(c) => (controller = c)}
183
+ >
184
+ <slot name="main" />
185
+ <slot />
186
+ </WorkspaceShell>
315
187
  );
316
188
  });
@@ -1,4 +1,4 @@
1
- import { createEffect, createSignal, onCleanup, onMount } from 'solid-js';
1
+ import { createSignal, onCleanup, onMount } from 'solid-js';
2
2
  import { defineWebComponent } from './define';
3
3
  import { CHAT_SLOTS, readSlots } from './slots';
4
4
  import { ChatThread, type ChatThreadProps, type ChatThreadContextUsage, type ChatThreadController } from '../components/chat-thread';
@@ -14,8 +14,20 @@ import type { ModelOption } from '../types';
14
14
 
15
15
  type Props = Omit<ChatThreadProps,
16
16
  'class' | 'onValueChange' | 'onSubmit' | 'onAttachmentsChange' | 'onSuggestionClick' | 'onModelChange'
17
- | 'onMessageAction' | 'onSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'messages'
18
- | 'accept' | 'onAttachmentsRejected'> & Record<string, unknown> & {
17
+ | 'onMessageAction' | 'onWebSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'cardHostElement' | 'messages'
18
+ | 'accept' | 'onAttachmentsRejected'
19
+ // `headerEndContent`/`emptyContent` are JSX.Element escape hatches for a caller
20
+ // composing `ChatThread` directly as a Solid component (see their doc comments in
21
+ // chat-thread.tsx — the construct-engine's emitted App is the motivating case).
22
+ // `<kai-chat>` is the OPPOSITE shape: a custom element crossing the shadow-DOM
23
+ // boundary, where a `JSX.Element` value cannot exist for a consumer to construct
24
+ // (React/Vue/plain HTML have no such type) and the facade already has its own
25
+ // working mechanism for both regions — `slot="header-end"` and `slot="empty"`.
26
+ // Omitted here rather than left to flow through `Omit`'s default pass-through:
27
+ // without this, `gen-element-api.mjs` picked them up and put a JSX.Element type
28
+ // (which it stringifies as Solid's internal array-like union — meaningless to a
29
+ // web-component consumer) into `<kai-chat>`'s public prop surface and docs.
30
+ | 'headerEndContent' | 'emptyContent'> & Record<string, unknown> & {
19
31
  /** Which attachment media types the user may stage, in HTML `accept` syntax:
20
32
  * `<kai-chat accept="image/*,application/pdf">`. A plain string, so unlike
21
33
  * `messages` it DOES work as an attribute. Omitted means no filter.
@@ -86,8 +98,8 @@ interface Events {
86
98
  'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
87
99
  /** The header model switcher changed. */
88
100
  'kai-model-change': { modelId: string };
89
- /** The Search button was clicked. */
90
- 'kai-search': Record<string, never>;
101
+ /** The web-search (Globe) toolbar button was clicked. */
102
+ 'kai-web-search': Record<string, never>;
91
103
  /** The Mic / voice button was clicked. */
92
104
  'kai-voice': Record<string, never>;
93
105
  }
@@ -97,9 +109,10 @@ defineWebComponent<Props, Events>('kai-chat', {
97
109
  suggestions: undefined, suggestionMode: 'submit', persistSuggestions: false, proseSize: 'sm',
98
110
  codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
99
111
  models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
100
- search: false, voice: false, triggers: undefined, kindIcons: undefined,
112
+ attach: true, webSearch: false, voice: false, triggers: undefined, kindIcons: undefined,
101
113
  actionsReveal: 'always', cardTypes: undefined, cardSchemas: undefined, accept: undefined,
102
- }, (props, { dispatch, flag, element, expose }) => {
114
+ reasoning: undefined, reasoningOpen: undefined,
115
+ }, (props, { dispatch, flag, reflectFlag, element, expose }) => {
103
116
  // `messages` is an untyped boundary: a consumer can hand it anything at
104
117
  // runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
105
118
  // the invalid entries rather than let `groupMessageParts` throw deep inside a
@@ -120,7 +133,10 @@ defineWebComponent<Props, Events>('kai-chat', {
120
133
 
121
134
  // Reflect streaming state to a host attribute so slotted composer/notice CSS
122
135
  // can react without reading internals (e.g. :host([loading]) ::slotted(...)).
123
- createEffect(() => { element.toggleAttribute('loading', flag('loading')); });
136
+ // reflectFlag, not a hand-rolled toggleAttribute effect: the reflection is what
137
+ // makes the property read back `undefined`, so the two belong in one call. See
138
+ // WebComponentContext.reflectFlag.
139
+ reflectFlag('loading');
124
140
 
125
141
  // Imperative method API — forward the chat-thread controller onto the host
126
142
  // (focus the composer, clear it, send programmatically, scroll the thread).
@@ -161,12 +177,17 @@ defineWebComponent<Props, Events>('kai-chat', {
161
177
  codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
162
178
  chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
163
179
  currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
164
- scrollButton={props.scrollButton !== false} search={flag('search')} voice={flag('voice')}
180
+ scrollButton={props.scrollButton !== false} attach={flag('attach')} webSearch={flag('webSearch')} voice={flag('voice')}
181
+ reasoning={props.reasoning as 'full' | 'compact' | 'off' | undefined}
182
+ reasoningOpen={flag('reasoningOpen')}
165
183
  triggers={props.triggers as TriggerDef[] | undefined}
166
184
  kindIcons={props.kindIcons as Record<string, string> | undefined}
167
185
  actionsReveal={props.actionsReveal as 'always' | 'hover'}
168
186
  cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
169
187
  cardSchemas={props.cardSchemas as Record<string, object> | undefined}
188
+ /* F-26: card parts emit off THIS element as the bubbling `kai-card` event,
189
+ so `listenForCardEvents(el)` / addEventListener('kai-card') work. */
190
+ cardHostElement={element}
170
191
  onValueChange={(value) => dispatch('kai-value-change', { value })}
171
192
  onSubmit={(detail) => dispatch('kai-submit', detail)}
172
193
  accept={props.accept as string | undefined}
@@ -175,7 +196,7 @@ defineWebComponent<Props, Events>('kai-chat', {
175
196
  onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
176
197
  onModelChange={(modelId) => dispatch('kai-model-change', { modelId })}
177
198
  onMessageAction={(detail) => dispatch('kai-message-action', detail)}
178
- onSearch={() => dispatch('kai-search', {})}
199
+ onWebSearch={() => dispatch('kai-web-search', {})}
179
200
  onVoice={() => dispatch('kai-voice', {})}
180
201
  controllerRef={(c) => (controller = c)}
181
202
  headerStart={slot('header-start')}