@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
@@ -9,6 +9,14 @@
9
9
  // element, so it carries its own shadow root + the shared kit stylesheet — it's
10
10
  // viewport-positioned AND fully kit-styled, never a raw div.
11
11
  //
12
+ // ADOPTS, else creates: `ensureMounted` first
13
+ // looks for a connected `<kai-toast-region>` already in the document and binds
14
+ // the store to it, so an app that placed its own region and also calls
15
+ // `toast()` gets ONE region, not two overlapping ones. It creates a region only
16
+ // when none exists. With two or more candidate regions the choice is genuinely
17
+ // ambiguous — the first in document order wins, and a one-time console.warn
18
+ // says so (decide loudly).
19
+ //
12
20
  // SSR-safe: every DOM touch is guarded by `typeof document`. On the server,
13
21
  // raising a toast is an inert no-op (the store updates, nothing mounts).
14
22
 
@@ -156,21 +164,75 @@ function resolveDuration(item: Pick<ToastItem, 'duration' | 'action'>): number {
156
164
  }
157
165
 
158
166
  /**
159
- * Lazily create the single `<kai-toast-region>` host on `document.body` and
160
- * bind the store to its `toasts` property. Idempotent + SSR-safe. The element
161
- * upgrade (its `defineWebComponent` registration) happens when the elements
162
- * bundle loads; setting the property before/after upgrade both work because
167
+ * Lazily resolve the single `<kai-toast-region>` host for a target and bind the
168
+ * store to its `toasts` property. Idempotent + SSR-safe. The element upgrade
169
+ * (its `defineWebComponent` registration) happens when the elements bundle
170
+ * loads; setting the property before/after upgrade both work because
163
171
  * `customElement` reflects late-set properties.
172
+ *
173
+ * ADOPT-IF-PRESENT: a connected
174
+ * `<kai-toast-region>` already in the document (same `target`, not already
175
+ * claimed for another target) is adopted — the store binds to IT, and no
176
+ * second region mounts. Adoption respects the region's authored attributes
177
+ * (position/stack/…): config from `configureToasts()` is not stamped onto an
178
+ * adopted region here, though an explicit `configureToasts()` call still
179
+ * updates every region, adopted included. Binding the store REPLACES a
180
+ * `toasts` array the app set as data — after the first `toast()` call the
181
+ * imperative store owns the adopted region's list. Only when no candidate
182
+ * exists is a fresh region created on `document.body`. Two or more candidates
183
+ * for the same target are genuinely ambiguous: the first in document order
184
+ * wins, with a one-time console.warn (decide loudly).
185
+ *
186
+ * If an adopted (or created) region later leaves the DOM, the cache entry is
187
+ * dropped and the next call resolves fresh — adopt again if a region exists,
188
+ * else create — so a removed region never becomes a dead cache entry that
189
+ * swallows toasts.
164
190
  */
165
191
  // One region per distinct target (the `null` key = the global / viewport region).
166
192
  // Every region binds the SAME store proxy and filters to its own target, so a
167
193
  // toast routes to the region for its `target`.
168
194
  const regions = new Map<HTMLElement | null, HTMLElement>();
169
195
 
196
+ // Decide-loudly, once: ambiguity between 2+ candidate regions is warned about a
197
+ // single time per page, not on every toast.
198
+ let warnedAmbiguousRegions = false;
199
+
200
+ /** Read a region element's `target` property (undefined pre-upgrade → null =
201
+ * the global region). */
202
+ function regionTarget(el: HTMLElement): HTMLElement | null {
203
+ return (el as unknown as { target?: HTMLElement }).target ?? null;
204
+ }
205
+
170
206
  export function ensureMounted(target: HTMLElement | null = null): HTMLElement | undefined {
171
207
  if (typeof document === 'undefined') return undefined;
172
208
  const cached = regions.get(target);
173
209
  if (cached && cached.isConnected) return cached;
210
+ // The region this key resolved to left the DOM — drop the dead entry so it
211
+ // can never swallow toasts, and resolve fresh below.
212
+ if (cached) regions.delete(target);
213
+
214
+ // Adopt a region the app already placed. Regions this store already
215
+ // claimed for OTHER targets are not candidates.
216
+ const claimed = new Set(regions.values());
217
+ const candidates = Array.from(
218
+ document.querySelectorAll<HTMLElement>('kai-toast-region'),
219
+ ).filter((el) => el.isConnected && !claimed.has(el) && regionTarget(el) === target);
220
+ if (candidates.length > 1 && !warnedAmbiguousRegions) {
221
+ warnedAmbiguousRegions = true;
222
+ console.warn(
223
+ `[kitn] toast(): ${candidates.length} candidate <kai-toast-region> elements are in the ` +
224
+ 'document; adopting the first in document order. Keep one region per target so the ' +
225
+ 'imperative toast() API has an unambiguous home.',
226
+ );
227
+ }
228
+ const adopted = candidates[0];
229
+ if (adopted) {
230
+ (adopted as unknown as { toasts: ToastItem[] }).toasts = toasts as ToastItem[];
231
+ regions.set(target, adopted);
232
+ setMounted(true);
233
+ return adopted;
234
+ }
235
+
174
236
  const el = document.createElement('kai-toast-region') as HTMLElement;
175
237
  // Append FIRST so the element upgrades, THEN bind. Setting a property before
176
238
  // upgrade loses it: component-register resets every prop in the constructor on
@@ -0,0 +1,70 @@
1
+ // src/primitives/url-scheme-policy.ts
2
+ // The kit's one URL-scheme allow/deny policy, split out of card-routing.ts so it
3
+ // has NO DOM dependency (`URL` is a global in both the browser and Node — the
4
+ // rest of card-routing.ts uses HTMLElement/window/CustomEvent, which aren't).
5
+ // That split matters beyond tidiness: this schema.ts (agent-tooling/construct)
6
+ // runs under tsconfig.mcp.json's Node-only, no-DOM-lib pass (it's imported
7
+ // transitively via mcp/tools/construct.ts), and importing anything from
8
+ // card-routing.ts there drags its HTMLElement/window/Document/CustomEvent
9
+ // references into that compile and breaks it — even though only isSafeUrl is
10
+ // used. card-routing.ts re-exports everything here so its own public surface
11
+ // (isSafeUrl/isScriptUrl, used by markdown.tsx/artifact.tsx/source.tsx) is
12
+ // unchanged; this is a location split, not a second policy.
13
+
14
+ const SAFE_SCHEMES = ['http:', 'https:', 'mailto:'];
15
+ const SCRIPT_SCHEMES = ['javascript:', 'vbscript:'];
16
+
17
+ /** The scheme the WHATWG parser reads out of `url`, resolved against a base so a
18
+ * relative input inherits `http:`. `undefined` when it will not parse at all.
19
+ *
20
+ * ONE parser for the two questions below, deliberately: the parsing is where
21
+ * the subtlety lives (it strips embedded tabs/newlines and trims surrounding
22
+ * whitespace before reading the scheme, so `java\nscript:` and
23
+ * ` javascript:... ` are both read as `javascript:` -- which a regex over the
24
+ * raw string would miss). Two predicates over one parse cannot drift on that;
25
+ * two hand-rolled parsers would. */
26
+ function schemeOf(url: string): string | undefined {
27
+ try { return new URL(url, 'http://_invalid_base').protocol; } catch { return undefined; }
28
+ }
29
+
30
+ /** True when `url` is safe to put in an href / hand to `window.open` / an `<img src>`.
31
+ *
32
+ * Exported so the MARKDOWN renderer, the ARTIFACT viewer and the construct
33
+ * format's `widget.launcherIcon` reuse this exact guard rather than growing a
34
+ * second scheme list that can drift from this one.
35
+ *
36
+ * Resolving against a base is deliberate and is what makes it correct for
37
+ * markdown: a relative or fragment link (`/docs`, `#section`, `./rel`) is
38
+ * ordinary markdown, and resolving it inherits the base's `http:` so it
39
+ * passes, while `javascript:`/`data:`/`vbscript:` keep their own protocol and
40
+ * fail. It is correct for the artifact viewer for the same reason: a file with
41
+ * no `src` to resolve against yields a bare relative path (`docs/report.pdf`),
42
+ * which is a legitimate artifact address. Contrast `isRenderableLink` in
43
+ * `primitives/link-preview.ts`, which takes NO base and so demands an absolute
44
+ * http(s) URL: that is the right guard for a model-supplied citation -- a
45
+ * reference to a page on the public web -- this one for markdown body links,
46
+ * artifact file addresses, and a construct's launcher icon. */
47
+ export function isSafeUrl(url: string): boolean {
48
+ const scheme = schemeOf(url);
49
+ return scheme !== undefined && SAFE_SCHEMES.includes(scheme);
50
+ }
51
+
52
+ /** True when navigating to `url` would EXECUTE it as script in the initiating
53
+ * document's origin.
54
+ *
55
+ * Strictly narrower than `!isSafeUrl(url)`, and not a competing policy: it
56
+ * answers a different question, for the one sink where the allowlist is the
57
+ * wrong tool. An `<iframe src>` legitimately takes `data:` and `blob:` (a
58
+ * `data:` blob artifact is a documented `<kai-artifact>` use -- it is what
59
+ * `displayUrl` exists for) and both get an OPAQUE origin in every modern
60
+ * browser, so neither can reach the host page. `javascript:`/`vbscript:` are
61
+ * the schemes that run in the EMBEDDER's origin, and they are the whole risk:
62
+ * the default sandbox (no `allow-same-origin`) already makes the browser refuse
63
+ * them, but a consumer who sets `allow-same-origin` turns a model-supplied
64
+ * `src` into host-origin script execution. The artifact viewer used to suggest
65
+ * that setting for "an artifact you trust"; it no longer does, and this guard
66
+ * is what protects the consumers who took the old advice. */
67
+ export function isScriptUrl(url: string): boolean {
68
+ const scheme = schemeOf(url);
69
+ return scheme !== undefined && SCRIPT_SCHEMES.includes(scheme);
70
+ }
@@ -10,3 +10,36 @@ export function observeContentHeight(el: Element, onHeight: (height: number) =>
10
10
  ro.observe(el);
11
11
  return () => ro.disconnect();
12
12
  }
13
+
14
+ /** Observe an element's resizes but report the FULL rendered document height (not the
15
+ * observed element's own content-box) — `document.body.scrollHeight`.
16
+ *
17
+ * Used by the remote-card provider runtime to size the host iframe:
18
+ * `observeContentHeight` reports the ResizeObserver content-box of
19
+ * the observed root, which drops that root's OWN padding/border and any ancestor
20
+ * (e.g. `<body>`) padding above it — the host then clips the bottom of the card by
21
+ * exactly those lost pixels. `scrollHeight` is the full padding-box height as actually
22
+ * rendered, so it stays correct no matter which element in the ancestor chain carries
23
+ * the padding/border, including if the provider page's own styles change later —
24
+ * reading contentRect off one fixed element, or hand-summing computed padding/border
25
+ * off a fixed list of ancestors, would both need updating every time that chain does.
26
+ *
27
+ * Deliberately `document.body.scrollHeight`, NOT `document.documentElement.scrollHeight`
28
+ * (N1, task-10-report.md "Fix-wave re-review"): the CSSOM View spec special-cases the
29
+ * scrollHeight of the ROOT element to be `max(viewport scrolling area, viewport
30
+ * height)` — and the host sets the iframe's viewport FROM this very measurement
31
+ * (`host-embed.ts` `sizeIframe`), so `documentElement.scrollHeight` can only grow for
32
+ * the life of the frame: once the iframe is tall, the root's own scrollHeight is
33
+ * floored at that height even after the card's content shrinks. `<body>` carries no
34
+ * such floor — its scrollHeight is a plain padding-box measurement of body's own
35
+ * content, so it shrinks along with the card. */
36
+ export function observeDocumentHeight(el: Element, onHeight: (height: number) => void): () => void {
37
+ let last = -1;
38
+ const ro = new ResizeObserver(() => {
39
+ const doc = el.ownerDocument;
40
+ const h = doc?.body?.scrollHeight ?? doc?.documentElement?.scrollHeight ?? el.getBoundingClientRect().height;
41
+ if (last < 0 || Math.abs(h - last) > THRESHOLD) { last = h; onHeight(h); }
42
+ });
43
+ ro.observe(el);
44
+ return () => ro.disconnect();
45
+ }
@@ -51,6 +51,14 @@ export interface SpeechRecognitionStartOptions {
51
51
  lang?: string;
52
52
  /** Called with each interim (non-final) transcript when `interim` is enabled. */
53
53
  onInterim?: (text: string) => void;
54
+ /**
55
+ * Called when the recognition session hits a runtime error (`recognition.onerror`),
56
+ * with the platform's error code (`network`, `not-allowed`, `no-speech`, ...) and a
57
+ * human-readable message. The session still ends through `onend`, so `start()` still
58
+ * resolves (with whatever text was captured before the error). Without this callback
59
+ * a runtime failure is invisible: the `error` signal is state, not a notification.
60
+ */
61
+ onError?: (error: string, message: string) => void;
54
62
  }
55
63
 
56
64
  /**
@@ -102,7 +110,10 @@ export function useSpeechRecognition(options: UseSpeechRecognitionOptions = {})
102
110
  };
103
111
 
104
112
  recognition.onerror = (event) => {
105
- setError(event.error ?? 'Speech recognition error');
113
+ const code = event.error ?? 'unknown';
114
+ const message = `Speech recognition error: ${code}`;
115
+ setError(message);
116
+ opts.onError?.(code, message);
106
117
  };
107
118
 
108
119
  recognition.onend = () => {
@@ -17,14 +17,42 @@ export function useStickToBottom() {
17
17
 
18
18
  function scrollToBottom(behavior: ScrollBehavior = 'smooth') {
19
19
  if (!containerEl) return;
20
- containerEl.scrollTo({ top: containerEl.scrollHeight, behavior });
20
+ if (typeof containerEl.scrollTo === 'function') {
21
+ containerEl.scrollTo({ top: containerEl.scrollHeight, behavior });
22
+ } else {
23
+ containerEl.scrollTop = containerEl.scrollHeight;
24
+ }
21
25
  shouldStick = true;
22
26
  setIsAtBottom(true);
23
27
  }
24
28
 
29
+ let pendingFrame: number | undefined;
30
+
31
+ /**
32
+ * `cancelAnimationFrame`, captured at SETUP -- not called bare at cleanup.
33
+ *
34
+ * Cleanup is not guaranteed to run while the page that mounted this
35
+ * primitive is still standing: a host can tear its DOM globals down first
36
+ * (`component-register`'s `disconnectedCallback` defers a microtask; a
37
+ * test environment deletes the globals synchronously right after
38
+ * detaching). A bare `cancelAnimationFrame` there throws, surfacing as an
39
+ * unhandled rejection that fails a run in which every test passed --
40
+ * see tests/components/teardown-without-dom-globals.test.tsx, and the
41
+ * same pattern in create-tween.ts.
42
+ *
43
+ * Guarded because "setup" here is the component body, and a server render
44
+ * executes component bodies too; Node has neither global.
45
+ */
46
+ const cancelFrame = typeof cancelAnimationFrame === 'function'
47
+ ? cancelAnimationFrame.bind(globalThis)
48
+ : () => {};
49
+
25
50
  function onNewContent() {
26
51
  if (shouldStick) {
27
- requestAnimationFrame(() => scrollToBottom('instant'));
52
+ pendingFrame = requestAnimationFrame(() => {
53
+ pendingFrame = undefined;
54
+ scrollToBottom('instant');
55
+ });
28
56
  }
29
57
  }
30
58
 
@@ -36,6 +64,10 @@ export function useStickToBottom() {
36
64
  onCleanup(() => {
37
65
  el.removeEventListener('scroll', checkIfAtBottom);
38
66
  observer.disconnect();
67
+ if (pendingFrame !== undefined) {
68
+ cancelFrame(pendingFrame);
69
+ pendingFrame = undefined;
70
+ }
39
71
  });
40
72
  }
41
73
 
@@ -5,6 +5,19 @@ export interface UseTextStreamOptions {
5
5
  speed?: number;
6
6
  characterChunkSize?: number;
7
7
  fadeDuration?: number;
8
+ segmentDelay?: number;
9
+ }
10
+
11
+ /** Default fade-in duration for a given speed (ms) — shared with ResponseStream. */
12
+ export function defaultFadeDuration(speed: number): number {
13
+ const s = Math.min(100, Math.max(1, speed));
14
+ return Math.round(1000 / Math.sqrt(s));
15
+ }
16
+
17
+ /** Default per-segment stagger for a given speed (ms) — shared with ResponseStream. */
18
+ export function defaultSegmentDelay(speed: number): number {
19
+ const s = Math.min(100, Math.max(1, speed));
20
+ return Math.max(1, Math.round(100 / Math.sqrt(s)));
8
21
  }
9
22
 
10
23
  export interface TextStreamSegment {
@@ -23,6 +36,7 @@ export function useTextStream(options: UseTextStreamOptions) {
23
36
  let fullText = '';
24
37
  let charIndex = 0;
25
38
  let intervalId: ReturnType<typeof setInterval> | undefined;
39
+ let completeTimeoutId: ReturnType<typeof setTimeout> | undefined;
26
40
  let isPaused = false;
27
41
  let asyncIterator: AsyncIterator<string> | undefined;
28
42
 
@@ -31,6 +45,10 @@ export function useTextStream(options: UseTextStreamOptions) {
31
45
  clearInterval(intervalId);
32
46
  intervalId = undefined;
33
47
  }
48
+ if (completeTimeoutId !== undefined) {
49
+ clearTimeout(completeTimeoutId);
50
+ completeTimeoutId = undefined;
51
+ }
34
52
  }
35
53
 
36
54
  function typewriterTick() {
@@ -76,8 +94,21 @@ export function useTextStream(options: UseTextStreamOptions) {
76
94
  const words = source.split(/(\s+)/).filter(Boolean);
77
95
  setSegments(words.map((text, index) => ({ text, index })));
78
96
  setDisplayedText(source);
79
- // isComplete fires after animation has time to play
80
- // (segments count * delay per segment from ResponseStream)
97
+ // Completion announces after the staggered animation has had time to
98
+ // play: segments * per-segment delay + one fade duration — the promise
99
+ // the comment here used to make with no code behind it (nothing on this
100
+ // path ever called setIsComplete(true), so kai-complete never fired for
101
+ // a fade-mode string). A timer, not a synchronous write: the consumer
102
+ // attaches its kai-complete listener a beat after mount, and a
103
+ // same-tick fire races past it.
104
+ const segDelay = typeof options.segmentDelay === 'number'
105
+ ? Math.max(0, options.segmentDelay)
106
+ : defaultSegmentDelay(speed);
107
+ const fadeDur = options.fadeDuration ?? defaultFadeDuration(speed);
108
+ completeTimeoutId = setTimeout(() => {
109
+ completeTimeoutId = undefined;
110
+ setIsComplete(true);
111
+ }, words.length * segDelay + fadeDur);
81
112
  }
82
113
  } else {
83
114
  if (options.mode === 'typewriter') {
@@ -14,7 +14,7 @@ import { createPacker, isCardWireFrame, type WireMessage } from './wire';
14
14
  import { assertOrigin, redactFrame } from './origin';
15
15
  import { negotiateVersion } from './version';
16
16
  import { hasPollutionKey } from './validate';
17
- import { observeContentHeight } from '../primitives/use-resize-observer';
17
+ import { observeDocumentHeight } from '../primitives/use-resize-observer';
18
18
  import { validateAgainstSchema, type JsonSchema } from '../primitives/card-validate';
19
19
 
20
20
  /** A provider-side renderer for one card `type`. Renamed (was CardRenderer) per H-K
@@ -105,10 +105,13 @@ export function createCardBridge(options: CreateCardBridgeOptions): CardBridge {
105
105
  }
106
106
 
107
107
  function startObserver(): void {
108
- // Tear down any existing observer so observeContentHeight's internal `last` baseline
108
+ // Tear down any existing observer so observeDocumentHeight's internal `last` baseline
109
109
  // re-initializes to -1 and the newly-mounted card always emits its initial height.
110
+ // observeDocumentHeight (not observeContentHeight) so the reported height covers
111
+ // the FULL rendered document — root's own padding/border AND the provider page's
112
+ // body padding above it — not just root's ResizeObserver content-box (D1).
110
113
  stopObserver?.(); stopObserver = null;
111
- stopObserver = observeContentHeight(root, (height) => {
114
+ stopObserver = observeDocumentHeight(root, (height) => {
112
115
  if (!currentId) return;
113
116
  cardHost.emit({ kind: 'resize', cardId: currentId, height });
114
117
  });
@@ -279,6 +279,7 @@ export {
279
279
  } from './tool-defs';
280
280
  export type {
281
281
  AnthropicToolDef,
282
+ CardRequireRule,
282
283
  CardToolInput,
283
284
  CardToolOptions,
284
285
  CardToolSource,