@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
@@ -27,9 +27,14 @@
27
27
  // `format: "uri"` (link/embed/artifact), `minimum` (tasks/embed/artifact),
28
28
  // `maxItems` (confirm/artifact), `pattern` (embed), `if`/`then` (embed), `oneOf`
29
29
  // (artifact), a free-form object (form) and untyped `payload`/`allowOther` members
30
- // (confirm/choice). Non-strict is therefore not merely the default, it is currently
31
- // the only working mode, and it is also the mode the five-configuration conformance
32
- // spike actually proved cards in.
30
+ // (confirm/choice). Non-strict is therefore the default and the mode the
31
+ // five-configuration conformance spike actually proved cards in but since F-20 it
32
+ // is no longer a raw pass-through either: a root combinator (`anyOf` on artifact,
33
+ // `allOf` on embed) gets HTTP 400 from OpenAI and Anthropic even non-strict, so the
34
+ // non-strict projection relaxes those root combinators LOUDLY (constraint restated in
35
+ // the description, console.warn names the relaxation, registry.validate still
36
+ // enforces at render time). The jsonschema projection stays byte-faithful to the
37
+ // authored schema.
33
38
  //
34
39
  // The alternative was to silently drop the offending keywords. That is rejected for
35
40
  // the reason the plan gives: a dropped `maxItems: 4` means the model emits six
@@ -126,6 +131,52 @@ export interface CardToolOptions<P extends ToolProvider = ToolProvider> {
126
131
  * When it throws it names the card, the path and the keyword.
127
132
  */
128
133
  readonly strict?: boolean;
134
+ /**
135
+ * Narrow the DERIVED tool schema per card type, after projection.
136
+ *
137
+ * A card's authored schema is deliberately permissive — `files` is optional on an
138
+ * artifact, its items need only a `path` — because the card CONTRACT must accept
139
+ * what a host may legitimately render. A model filling the tool in, though, is
140
+ * often better served by a tighter tool: requiring `code` on every file, or at
141
+ * least one file at all, moves a class of failures from render time (a card the
142
+ * registry rejects) to generation time (the model literally cannot emit one).
143
+ *
144
+ * This narrows the WIRE projection only — the authored schema and
145
+ * `registry.validate()` are untouched, so a hand-built envelope still validates.
146
+ * Applied for every provider, `jsonschema` included, and merged loudly: an
147
+ * unknown path or a required name the node has no property for is a TypeError
148
+ * naming the card, the path and the field, because a tool that can never be
149
+ * satisfied must not ship quietly.
150
+ *
151
+ * IT CANNOT REACH A FORM CARD'S FIELDS, and that is a known limitation rather
152
+ * than an oversight. The form
153
+ * card's payload IS a JSON Schema, so `form.schema.json` describes `properties`
154
+ * as a map of field definitions and there is no node at `properties.ticketId`
155
+ * for a rule to land on — `require: { form: [{ path: 'properties.ticketId' }] }`
156
+ * raises the TypeError above, correctly. So an app cannot pin
157
+ * `x-kai-format: 'custom'` onto one field of a form the model authors. The
158
+ * enum on that hint is what makes a small model pick a valid token; an app that
159
+ * needs a guarantee checks the envelope when it arrives.
160
+ */
161
+ readonly require?: Readonly<Record<string, readonly CardRequireRule[]>>;
162
+ }
163
+
164
+ /**
165
+ * One narrowing instruction for one node of one card's projected schema.
166
+ *
167
+ * `path` is a dot-path from the envelope-data root through `properties` keys
168
+ * (`''` names the root node itself). On an ARRAY node, `required` narrows
169
+ * `items.required` and `minItems` lands on the array; on an object node,
170
+ * `required` lands on the node's own `required`. Existing requirements merge,
171
+ * never replace.
172
+ */
173
+ export interface CardRequireRule {
174
+ /** Dot-path from the envelope-data root to a schema node, e.g. 'files'. */
175
+ readonly path: string;
176
+ /** Property names to require. On an ARRAY node this narrows `items.required`; on an object node, the node's own `required`. */
177
+ readonly required?: readonly string[];
178
+ /** Sets `minItems` (array nodes only). */
179
+ readonly minItems?: number;
129
180
  }
130
181
 
131
182
  /**
@@ -225,7 +276,7 @@ function formatUnsupported(subset: ProviderSubset, cards: readonly UnsupportedCa
225
276
  lines.push('');
226
277
  lines.push(` subset source: ${subset.source} (read ${subset.checkedOn})`);
227
278
  lines.push(
228
- ' Fix: drop `strict: true`. Non-strict is the default and is the mode the kit\'s cards are proven in; both providers accept a loose schema there and ignore what they do not compile. Rewriting a built-in card schema to fit a strict subset would change what a valid card IS, which is a card-contract change, not a projection setting.',
279
+ ' Fix: drop `strict: true`. Non-strict mode projects a provider-valid schema (root combinators are relaxed with the constraint restated in the description and still enforced by card validation). Rewriting a built-in card schema to fit a strict subset would change what a valid card IS, which is a card-contract change, not a projection setting.',
229
280
  );
230
281
  return lines.join('\n');
231
282
  }
@@ -237,6 +288,227 @@ function formatUnsupported(subset: ProviderSubset, cards: readonly UnsupportedCa
237
288
  const isRecord = (v: unknown): v is Record<string, unknown> =>
238
289
  typeof v === 'object' && v !== null && !Array.isArray(v);
239
290
 
291
+ /**
292
+ * Root combinators the two largest providers refuse on a tool schema's root node
293
+ * (measured: OpenAI and Anthropic 400 before the model runs — findings F-20;
294
+ * DeepSeek's OpenAI-compatible route requires the same workaround). The AUTHORED
295
+ * schemas keep them — card validation keeps every constraint. Only the WIRE
296
+ * projection relaxes, loudly: the constraint is restated in the description the
297
+ * model reads, a console.warn names the relaxation, and a violating envelope
298
+ * still fails registry.validate() at render time with a hard diagnostic.
299
+ */
300
+ const ROOT_RELAXATIONS: Readonly<Record<string, string>> = {
301
+ artifact:
302
+ 'Provide `src` (a preview URL) or `files` — at least one. An envelope with neither is rejected.',
303
+ embed:
304
+ "For provider 'generic', include `url`. For 'youtube'/'vimeo', include `id` or `url`.",
305
+ };
306
+
307
+ /** Strip a banned combinator key from the projected ROOT node only (nested
308
+ * combinators are accepted by every provider measured and stay). Returns the
309
+ * relaxation note to restate in the TOOL description the model reads. Two
310
+ * distinct no-note return paths: `undefined` when NOTHING was banned (the wire
311
+ * projection is faithful, nothing was widened), and GENERIC_NOTE when something
312
+ * WAS banned but no curated copy exists (a custom card) — that path still
313
+ * restates the relaxation, because deleting a combinator without telling the
314
+ * model would be a silent widening. */
315
+ const GENERIC_RELAXATION_NOTE =
316
+ 'The root constraint of this schema was relaxed for this provider; consult the card registry for what a valid payload is.';
317
+
318
+ const BANNED_ROOT_KEYS = ['anyOf', 'allOf', 'oneOf', 'not', 'enum', 'const'] as const;
319
+
320
+ /**
321
+ * The object shape a literal `enum` / `const` VALUE implies.
322
+ *
323
+ * `const: { op: 'ping' }` is a whole-instance constraint, which a provider refuses
324
+ * at the root exactly like a combinator. The instance it admits is an object, so
325
+ * the shape survives the relaxation as `properties: { op: { const: 'ping' } }` with
326
+ * `op` required — nothing widened that the branch did not already allow.
327
+ */
328
+ function branchFromLiteral(value: unknown): Record<string, unknown> | null {
329
+ if (!isRecord(value)) return null;
330
+ const properties: Record<string, unknown> = {};
331
+ for (const [key, member] of Object.entries(value)) properties[key] = { const: member };
332
+ return { type: 'object', properties, required: Object.keys(value) };
333
+ }
334
+
335
+ /** The branch schemas one banned root keyword contributes, or `[]` for one that has none. */
336
+ function branchesOfRootKeyword(keyword: string, value: unknown): Record<string, unknown>[] {
337
+ if (keyword === 'anyOf' || keyword === 'oneOf' || keyword === 'allOf') {
338
+ return Array.isArray(value) ? value.filter(isRecord) : [];
339
+ }
340
+ if (keyword === 'const') return [branchFromLiteral(value)].filter((b): b is Record<string, unknown> => b !== null);
341
+ if (keyword === 'enum') {
342
+ return Array.isArray(value)
343
+ ? value.map(branchFromLiteral).filter((b): b is Record<string, unknown> => b !== null)
344
+ : [];
345
+ }
346
+ // `not` is a NEGATIVE constraint: nothing it says is a property the instance may
347
+ // carry, so there is nothing sound to merge back. It is dropped and restated in
348
+ // the description like every other relaxation.
349
+ return [];
350
+ }
351
+
352
+ /**
353
+ * Fold a root combinator's branches back into the object root that replaces it.
354
+ *
355
+ * The two built-ins showed the shape of the rule and this generalises it rather
356
+ * than special-casing them. `artifact`'s root `anyOf` is `[{required:['src']},
357
+ * {required:['files']}]`: a DISJUNCTION guarantees only what EVERY branch
358
+ * guarantees, so the intersection is empty and `required` stays absent — which is
359
+ * exactly what the artifact projection already did. `embed`'s root `allOf` is two
360
+ * `if`/`then` pairs: a CONJUNCTION guarantees every branch's own top-level
361
+ * `required`, and an `if`/`then` branch declares none, so again nothing is added.
362
+ * A consumer card whose branches carry real `properties` is the case neither
363
+ * built-in reaches, and the one this exists for.
364
+ *
365
+ * Properties are UNIONed (each branch's shape must remain expressible — dropping
366
+ * one is the silent narrowing the whole F-20 fix exists to avoid); a name already
367
+ * on the root keeps the root's definition. `required` is the intersection for
368
+ * `anyOf`/`oneOf`/`enum`/`const` and the union for `allOf`, unioned in turn with
369
+ * whatever the root already required, and filtered to names the merged
370
+ * `properties` actually carries so the tool can never be unsatisfiable.
371
+ */
372
+ function mergeBranchesIntoRoot(parameters: Record<string, unknown>, banned: readonly string[]): void {
373
+ const properties: Record<string, unknown> = isRecord(parameters.properties)
374
+ ? { ...parameters.properties }
375
+ : {};
376
+ const guaranteed = new Set<string>(
377
+ Array.isArray(parameters.required) ? parameters.required.map(String) : [],
378
+ );
379
+
380
+ for (const keyword of banned) {
381
+ const branches = branchesOfRootKeyword(keyword, parameters[keyword]);
382
+ if (branches.length === 0) continue;
383
+
384
+ for (const branch of branches) {
385
+ if (!isRecord(branch.properties)) continue;
386
+ for (const [name, sub] of Object.entries(branch.properties)) {
387
+ if (!(name in properties)) properties[name] = sub;
388
+ }
389
+ }
390
+
391
+ const perBranch = branches.map(
392
+ (branch) => new Set(Array.isArray(branch.required) ? branch.required.map(String) : []),
393
+ );
394
+ if (keyword === 'allOf') {
395
+ for (const set of perBranch) for (const name of set) guaranteed.add(name);
396
+ } else {
397
+ // Disjunction: keep only what every branch requires.
398
+ const [first, ...rest] = perBranch;
399
+ for (const name of first) {
400
+ if (rest.every((set) => set.has(name))) guaranteed.add(name);
401
+ }
402
+ }
403
+ }
404
+
405
+ if (Object.keys(properties).length > 0) parameters.properties = properties;
406
+ const required = [...guaranteed].filter((name) => name in properties);
407
+ if (required.length > 0) parameters.required = required;
408
+ }
409
+
410
+ /**
411
+ * Make the projected ROOT the object shape every provider demands.
412
+ *
413
+ * Deleting a root combinator is only half of F-20. A schema whose root was NOTHING
414
+ * BUT the combinator projects to `{"title":…,"description":…}` once it is gone —
415
+ * accepted by no provider (measured: OpenAI 400, "schema must be a JSON Schema of
416
+ * type \"object\"") and unfillable by any model. Every built-in declares
417
+ * `type: "object"` at its root, so nothing in the suite reached this until a
418
+ * consumer card did.
419
+ *
420
+ * A root that declares a NON-object type cannot be a tool schema at all, and
421
+ * asserting `type: "object"` over it would be a lie about the card. That refuses,
422
+ * naming the card.
423
+ */
424
+ function ensureObjectRoot(parameters: Record<string, unknown>, cardType: string): void {
425
+ const declared = parameters.type;
426
+ if (declared !== undefined && declared !== 'object') {
427
+ throw new TypeError(
428
+ `cardTools: the '${cardType}' card schema declares root type '${String(declared)}', but a provider tool ` +
429
+ `schema root must be an object (OpenAI and Anthropic reject anything else with HTTP 400). ` +
430
+ `Wrap the payload in an object, or project this card with provider 'jsonschema'.`,
431
+ );
432
+ }
433
+ parameters.type = 'object';
434
+ }
435
+
436
+ function relaxRootCombinators(parameters: Record<string, unknown>, cardType: string): string | undefined {
437
+ const note = ROOT_RELAXATIONS[cardType];
438
+ const banned = BANNED_ROOT_KEYS.filter((k) => k in parameters);
439
+ // The object-root guarantee holds for EVERY provider projection, banned keys or
440
+ // not: it is what the provider requires, not what the relaxation broke.
441
+ ensureObjectRoot(parameters, cardType);
442
+ if (banned.length === 0) return undefined;
443
+ mergeBranchesIntoRoot(parameters, banned);
444
+ for (const k of banned) delete parameters[k];
445
+ // eslint-disable-next-line no-console
446
+ console.warn(
447
+ `[kai-card-tools] relaxed root ${banned.join('/')} on the projected '${toolNameForCardType(cardType)}' tool schema ` +
448
+ `for this provider (it would be refused with HTTP 400); the constraint now lives in the ` +
449
+ `description and is still enforced by card validation.`,
450
+ );
451
+ return note ?? GENERIC_RELAXATION_NOTE;
452
+ }
453
+
454
+ /**
455
+ * Apply one card's `require` rules to its PROJECTED parameters.
456
+ *
457
+ * Runs after `project()` and `relaxRootCombinators()`, on the copy the projection
458
+ * built — never on the authored schema, which `registry.validate()` keeps reading.
459
+ * Merges into whatever `required` already exists rather than replacing it, so a
460
+ * rule can only ever NARROW what the model may emit, never widen it.
461
+ */
462
+ function applyRequire(
463
+ parameters: Record<string, unknown>,
464
+ cardType: string,
465
+ rules: readonly CardRequireRule[],
466
+ ): void {
467
+ for (const rule of rules) {
468
+ // Resolve the dot-path through `properties` keys. `''` names the root node;
469
+ // every other segment must name a property of the node reached so far.
470
+ let node: Record<string, unknown> = parameters;
471
+ if (rule.path !== '') {
472
+ for (const segment of rule.path.split('.')) {
473
+ const props = isRecord(node.properties) ? node.properties : undefined;
474
+ const next = props?.[segment];
475
+ if (!isRecord(next)) {
476
+ throw new TypeError(
477
+ `cardTools: require on '${cardType}': path '${rule.path}' does not resolve in the schema`,
478
+ );
479
+ }
480
+ node = next;
481
+ }
482
+ }
483
+
484
+ const isArrayNode = node.type === 'array' || (node.type === undefined && 'items' in node);
485
+ if (isArrayNode && rule.minItems !== undefined) node.minItems = rule.minItems;
486
+ if (!isArrayNode && rule.minItems !== undefined) {
487
+ throw new TypeError(
488
+ `cardTools: minItems at require path '${rule.path}' applies to array nodes only, ` +
489
+ `but '${rule.path}' in the '${cardType}' schema is not one`,
490
+ );
491
+ }
492
+
493
+ if (rule.required !== undefined) {
494
+ // On an array node the requirement lives on the ITEMS (each element must carry
495
+ // the field), not on the array itself.
496
+ const target = isArrayNode && isRecord(node.items) ? node.items : node;
497
+ const props = isRecord(target.properties) ? target.properties : undefined;
498
+ for (const field of rule.required) {
499
+ if (!props || !(field in props)) {
500
+ throw new TypeError(
501
+ `cardTools: require on '${cardType}' at path '${rule.path}': '${field}' is not a property of that node — ` +
502
+ `a required name with no property would make the tool unsatisfiable`,
503
+ );
504
+ }
505
+ }
506
+ const existing = Array.isArray(target.required) ? target.required.map(String) : [];
507
+ target.required = [...new Set([...existing, ...rule.required])];
508
+ }
509
+ }
510
+ }
511
+
240
512
  /**
241
513
  * Keywords stripped from every projection, strict or not.
242
514
  *
@@ -430,11 +702,40 @@ export function cardTools(a: CardToolInput | CardToolOptions, b?: CardToolOption
430
702
  const defs: ToolDef[] = [];
431
703
  const failures: UnsupportedCardTool[] = [];
432
704
 
705
+ // A `require` key naming a card the call does not carry is a typo, and a typo here
706
+ // would otherwise narrow NOTHING while looking like it narrowed something — the
707
+ // same decide-loudly class as an unknown dot-path below.
708
+ if (opts.require !== undefined) {
709
+ for (const key of Object.keys(opts.require)) {
710
+ if (!(key in schemas)) {
711
+ throw new TypeError(
712
+ `cardTools: require names card type '${key}', which this call does not carry ` +
713
+ `(carries: ${Object.keys(schemas).join(', ') || 'none'})`,
714
+ );
715
+ }
716
+ }
717
+ }
718
+
433
719
  for (const [cardType, schema] of Object.entries(schemas)) {
434
720
  const name = toolNameForCardType(cardType);
435
721
  const description = describe(cardType, schema, descriptions);
436
722
  const parameters = project(schema, projectOptions) as ToolParameters;
437
723
 
724
+ // F-20: non-strict only. Strict mode already refuses these cards with the full
725
+ // subset check, so the relaxation must never mask it. The note is restated in the
726
+ // TOOL description — the envelope field the model reads when choosing the tool.
727
+ const relaxedNote =
728
+ subset === null && opts.provider !== 'jsonschema'
729
+ ? relaxRootCombinators(parameters as Record<string, unknown>, cardType)
730
+ : undefined;
731
+ const wireDescription = relaxedNote ? `${description} ${relaxedNote}` : description;
732
+
733
+ // F-23: every provider, jsonschema included — a consumer handing the bare schema
734
+ // to the Vercel AI SDK narrows their tool the same way. Runs BEFORE the strict
735
+ // subset check so that check judges the schema that actually ships.
736
+ const requireRules = opts.require?.[cardType];
737
+ if (requireRules !== undefined) applyRequire(parameters as Record<string, unknown>, cardType, requireRules);
738
+
438
739
  if (subset) {
439
740
  const violations = checkProviderSubset(parameters, subset);
440
741
  if (violations.length > 0) {
@@ -444,9 +745,9 @@ export function cardTools(a: CardToolInput | CardToolOptions, b?: CardToolOption
444
745
  }
445
746
 
446
747
  if (opts.provider === 'openai') {
447
- defs.push({ type: 'function', function: { name, description, parameters, ...(strict ? { strict: true as const } : {}) } });
748
+ defs.push({ type: 'function', function: { name, description: wireDescription, parameters, ...(strict ? { strict: true as const } : {}) } });
448
749
  } else if (opts.provider === 'anthropic') {
449
- defs.push({ name, description, input_schema: parameters, ...(strict ? { strict: true as const } : {}) });
750
+ defs.push({ name, description: wireDescription, input_schema: parameters, ...(strict ? { strict: true as const } : {}) });
450
751
  } else {
451
752
  defs.push({ name, description, schema: parameters });
452
753
  }
package/src/solid.ts CHANGED
@@ -53,8 +53,18 @@ export { Input } from './ui/input';
53
53
  export type { InputProps } from './ui/input';
54
54
  export { Kbd } from './ui/kbd';
55
55
  export type { KbdProps, KbdPlatform } from './ui/kbd';
56
+ export { Checkbox } from './ui/checkbox';
57
+ export type { CheckboxProps } from './ui/checkbox';
58
+ export { Radio, RadioGroup } from './ui/radio';
59
+ export type { RadioProps, RadioGroupProps, RadioOption } from './ui/radio';
60
+ export { CheckboxGroup } from './ui/checkbox-group';
61
+ export type { CheckboxGroupProps, CheckboxOption } from './ui/checkbox-group';
56
62
  export { Switch } from './ui/switch';
57
63
  export type { SwitchProps } from './ui/switch';
64
+ export { Slider } from './ui/slider';
65
+ export type { SliderProps } from './ui/slider';
66
+ export { Select } from './ui/select';
67
+ export type { SelectProps, SelectOption } from './ui/select';
58
68
  export { Tabs } from './ui/tabs';
59
69
  export type { TabsProps, TabsVariant, KaiTabItem } from './ui/tabs';
60
70
  export { Segmented } from './ui/segmented';
@@ -69,6 +79,8 @@ export { EditableLabel } from './ui/editable-label';
69
79
  export type { EditableLabelProps } from './ui/editable-label';
70
80
  export { Dialog } from './ui/dialog';
71
81
  export type { DialogProps, DialogController } from './ui/dialog';
82
+ export { Dock, DockLauncherGlyph, DockCloseGlyph } from './ui/dock';
83
+ export type { DockProps, DockController, DockPosition, DockFocusOnOpen } from './ui/dock';
72
84
  export { Popover } from './ui/popover';
73
85
  export type { PopoverProps, PopoverController } from './ui/popover';
74
86
  export { Nav } from './ui/nav';
@@ -148,3 +160,6 @@ export type {
148
160
  AudioVisualizerProps, VisualizerVariant, ShaderSpec, ShaderVariantProps,
149
161
  } from './components/audio-visualizer';
150
162
  export type { VisualizerSize } from './components/audio-visualizer/sizes';
163
+ export { WorkspaceShell, type WorkspaceShellProps, type WorkspaceShellController, type WorkspaceAsideSide, type WorkspaceAsideToggleDetail, type WorkspaceAsideResizeDetail } from './components/workspace-shell';
164
+ export { createConversationItemsController, readConversationItemId } from './components/conversation-list';
165
+ export type { ConversationItemsController, ConversationItemsControllerOptions } from './components/conversation-list';
@@ -7,11 +7,23 @@ export type { SetMessages, AssistantStream } from './stream';
7
7
  export { appendTextPart, appendReasoningPart, upsertToolPart, upsertCardPart, fingerprint } from './parts';
8
8
  export type { ReasoningOpts } from './parts';
9
9
 
10
+ // Multi-thread mechanics (the workspace recast, spec §3b): the id-bound
11
+ // SetMessages fold + the in-flight-turn bookkeeping. The consumer's record
12
+ // shape and every persistence/retention decision stay outside — see ./threads.
13
+ export { updateThreadMessages, bindThreadMessages, createThreadSessions } from './threads';
14
+ export type { ThreadLike, SetThreads, BindThreadOptions, ThreadSessions } from './threads';
15
+
16
+ // The persistence SEAM, not persistence: the stored-thread validator (F-18,
17
+ // variant list derived from the MessagePart union) and the debounce/flush
18
+ // shape. No storage backend, no default delay — policy is the consumer's.
19
+ export { parseStoredThread, createSaveScheduler } from './persistence';
20
+ export type { ParsedThread, DroppedStored, SaveScheduler, SaveSchedulerOptions } from './persistence';
21
+
10
22
  // The zero-config mock. Produces SSE frames rather than folding parts directly,
11
23
  // so the no-backend preview runs through the SAME parser a real provider does —
12
24
  // and is deliberately impossible to mistake for one. See ./mock.
13
25
  export { createMockResponder, DEFAULT_MOCK_REPLIES, MOCK_BANNER, MOCK_MARKER, MOCK_MARKER_KEY, MOCK_MODEL_ID } from './mock';
14
- export type { MockResponder, MockResponderOptions } from './mock';
26
+ export type { MockReply, MockResponder, MockResponderOptions, MockToolCall, MockTurn } from './mock';
15
27
 
16
28
  // The content-model types every signature above mentions. Without these a
17
29
  // consumer importing only from '@kitn.ai/ui/state' cannot annotate the very
package/src/state/mock.ts CHANGED
@@ -96,9 +96,42 @@ export const DEFAULT_MOCK_REPLIES: readonly string[] = [
96
96
  'Mock again. Every frame I send is tagged `_kai_mock` and my usage reports zero tokens, so nothing here can be mistaken for a real turn.',
97
97
  ];
98
98
 
99
+ /** One scripted tool call for a mock turn. Framed exactly the way the OpenAI
100
+ * chat-completions wire frames a real one — an announce fragment carrying
101
+ * `id`/`function.name`, then the argument JSON streamed in fragments — so the
102
+ * kit's own reader (`readOpenAIStream`) reassembles it through the same path a
103
+ * real provider's call takes. */
104
+ export interface MockToolCall {
105
+ /** The tool name, e.g. `'get_weather'` or a card tool like `'kai_confirm'`. */
106
+ name: string;
107
+ /** The call's arguments. Serialized with `JSON.stringify` and streamed as
108
+ * fragments, like a real provider. Defaults to `{}`. */
109
+ arguments?: unknown;
110
+ /** Explicit tool-call id. Defaults to `call_kai-mock-<turn>-<n>`, which keeps
111
+ * the mock's naming tell (see tell 3): no provider issues ids in that shape. */
112
+ id?: string;
113
+ }
114
+
115
+ /** A scripted mock turn: optional text, then optional tool calls. A turn with
116
+ * tool calls finishes `finish_reason: 'tool_calls'`, exactly as a real
117
+ * tool-calling turn does; a turn without them finishes `'stop'`. */
118
+ export interface MockTurn {
119
+ /** Text streamed (token by token) before the tool calls. */
120
+ text?: string;
121
+ /** Tool calls announced this turn, in order. */
122
+ toolCalls?: readonly MockToolCall[];
123
+ }
124
+
125
+ /** A canned reply: plain text, or a scripted turn. A string is exactly
126
+ * `{ text }` — the pre-tool-call API unchanged. */
127
+ export type MockReply = string | MockTurn;
128
+
99
129
  export interface MockResponderOptions {
100
- /** Canned replies, cycled one per turn. Defaults to `DEFAULT_MOCK_REPLIES`. */
101
- replies?: readonly string[];
130
+ /** Canned replies, cycled one per turn. Plain strings stream as text; a
131
+ * `MockTurn` can also script tool calls (`{ text, toolCalls }`), which is
132
+ * what lets the zero-config mock exercise the kit's tool/card path without
133
+ * hand-rolled SSE framing. Defaults to `DEFAULT_MOCK_REPLIES`. */
134
+ replies?: readonly MockReply[];
102
135
  /** Delay between chunks, in ms. Defaults to 24 — fast enough to feel alive,
103
136
  * slow enough that the streaming is visible. `0` streams as fast as the
104
137
  * event loop allows, which is what tests want. */
@@ -144,6 +177,27 @@ function frame(id: string, body: Record<string, unknown>): string {
144
177
  const delay = (ms: number): Promise<void> =>
145
178
  ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
146
179
 
180
+ /** Normalize a canned reply: a plain string is exactly `{ text }`. */
181
+ const asTurn = (reply: MockReply): MockTurn => (typeof reply === 'string' ? { text: reply } : reply);
182
+
183
+ /** How many characters of argument JSON ride in each tool-call fragment. Small
184
+ * enough that any realistic argument object spans several frames, so the
185
+ * reader's fragment-reassembly path — the one a real provider exercises — is
186
+ * exercised here too, rather than a single-frame shortcut it would never see
187
+ * in production. */
188
+ const TOOL_ARG_FRAGMENT_CHARS = 16;
189
+
190
+ /** Split argument JSON into the fragments a provider streams. Never empty: an
191
+ * empty-object call still sends its `'{}'` so the reader has arguments to
192
+ * parse. */
193
+ function argumentFragments(json: string): string[] {
194
+ const out: string[] = [];
195
+ for (let i = 0; i < json.length; i += TOOL_ARG_FRAGMENT_CHARS) {
196
+ out.push(json.slice(i, i + TOOL_ARG_FRAGMENT_CHARS));
197
+ }
198
+ return out.length > 0 ? out : [''];
199
+ }
200
+
147
201
  /**
148
202
  * Build a mock responder.
149
203
  *
@@ -170,8 +224,9 @@ export function createMockResponder(options: MockResponderOptions = {}): MockRes
170
224
  let announced = false;
171
225
 
172
226
  return function respond(_prompt?: string): AsyncIterable<string> {
173
- const reply = pool[turn % pool.length];
227
+ const scripted = asTurn(pool[turn % pool.length]);
174
228
  const id = `kai-mock-${turn + 1}`;
229
+ const turnNumber = turn + 1;
175
230
  turn += 1;
176
231
 
177
232
  return {
@@ -193,15 +248,46 @@ export function createMockResponder(options: MockResponderOptions = {}): MockRes
193
248
  // exercises the reader's empty-delta path.
194
249
  yield frame(id, { choices: [{ index: 0, delta: { role: 'assistant' }, finish_reason: null }] });
195
250
 
196
- for (const token of tokenize(reply, chunkSize)) {
251
+ for (const token of tokenize(scripted.text ?? '', chunkSize)) {
197
252
  await delay(delayMs);
198
253
  yield frame(id, { choices: [{ index: 0, delta: { content: token }, finish_reason: null }] });
199
254
  }
200
255
 
256
+ // Scripted tool calls, framed the way the OpenAI wire frames real ones:
257
+ // one announce fragment per call (`index`/`id`/`function.name` + empty
258
+ // arguments), then the argument JSON in fragments. The kit's reader
259
+ // reassembles them through the exact path a real provider's call takes.
260
+ const toolCalls = scripted.toolCalls ?? [];
261
+ for (let index = 0; index < toolCalls.length; index += 1) {
262
+ const call = toolCalls[index];
263
+ // Tell 3's shape, extended to call ids: no provider issues these.
264
+ const callId = call.id ?? `call_${MOCK_MODEL_ID}-${turnNumber}-${index + 1}`;
265
+ await delay(delayMs);
266
+ yield frame(id, {
267
+ choices: [{
268
+ index: 0,
269
+ delta: { tool_calls: [{ index, id: callId, function: { name: call.name, arguments: '' } }] },
270
+ finish_reason: null,
271
+ }],
272
+ });
273
+ for (const fragment of argumentFragments(JSON.stringify(call.arguments ?? {}))) {
274
+ await delay(delayMs);
275
+ yield frame(id, {
276
+ choices: [{
277
+ index: 0,
278
+ delta: { tool_calls: [{ index, function: { arguments: fragment } }] },
279
+ finish_reason: null,
280
+ }],
281
+ });
282
+ }
283
+ }
284
+
201
285
  // Tell 4: zero usage. A real turn that produced this much text cannot
202
- // report zero completion tokens.
286
+ // report zero completion tokens. A turn that announced tool calls ends
287
+ // `tool_calls`, exactly as a real one does, so the consumer's tool loop
288
+ // branches the same way it would against a provider.
203
289
  yield frame(id, {
204
- choices: [{ index: 0, delta: {}, finish_reason: 'stop' }],
290
+ choices: [{ index: 0, delta: {}, finish_reason: toolCalls.length > 0 ? 'tool_calls' : 'stop' }],
205
291
  usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
206
292
  });
207
293
  yield 'data: [DONE]\n\n';