@kitn.ai/ui 0.25.1 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (409) hide show
  1. package/README.md +5 -7
  2. package/dist/components/attachment-types.d.ts +46 -1
  3. package/dist/components/attachments.d.ts +31 -0
  4. package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
  5. package/dist/components/audio-visualizer/index.d.ts +15 -1
  6. package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
  7. package/dist/components/chat-thread.d.ts +3 -41
  8. package/dist/components/code-block.d.ts +22 -0
  9. package/dist/components/conversation-item.d.ts +54 -1
  10. package/dist/components/conversation-list.d.ts +65 -0
  11. package/dist/components/form.d.ts +42 -0
  12. package/dist/components/message.d.ts +7 -0
  13. package/dist/components/toast.d.ts +2 -1
  14. package/dist/components/voice-input.d.ts +8 -0
  15. package/dist/components/voice-output.d.ts +12 -1
  16. package/dist/components/workspace-shell.d.ts +87 -0
  17. package/dist/{create-tween-B5Y4Im8G.js → create-tween-BFT6c-Y8.js} +1 -1
  18. package/dist/{create-tween-4z1XYLkR.js → create-tween-CJNlzoaO.js} +1 -1
  19. package/dist/{create-tween-CUzOlaMS.js → create-tween-CQED4T0g.js} +1 -1
  20. package/dist/custom-elements.json +2931 -2572
  21. package/dist/diagnostics/hook.d.ts +81 -0
  22. package/dist/diagnostics/index.d.ts +7 -0
  23. package/dist/diagnostics/report-request.d.ts +61 -0
  24. package/dist/diagnostics.d.ts +5 -0
  25. package/dist/diagnostics.js +209 -0
  26. package/dist/elements/agent-card.js +1 -1
  27. package/dist/elements/artifact.js +1 -1
  28. package/dist/elements/attachments.js +1 -1
  29. package/dist/elements/audio-visualizer.js +1 -1
  30. package/dist/elements/autoloader.js +1 -1
  31. package/dist/elements/avatar.js +1 -1
  32. package/dist/elements/badge.js +1 -1
  33. package/dist/elements/button.js +1 -1
  34. package/dist/elements/card.js +1 -1
  35. package/dist/elements/cards.js +1 -1
  36. package/dist/elements/chain-of-thought.js +1 -1
  37. package/dist/elements/chat-scope-picker.js +1 -1
  38. package/dist/elements/chat-workspace.js +1 -1
  39. package/dist/elements/chat.js +1 -1
  40. package/dist/elements/checkpoint.js +1 -1
  41. package/dist/elements/choice.js +1 -1
  42. package/dist/elements/chunks/{Icon-b5A8hlHs.js → Icon--Y8vsFal.js} +1 -1
  43. package/dist/elements/chunks/action-icons-D9u3OzYW.js +1 -0
  44. package/dist/elements/chunks/arrow-left-CVh1TeN7.js +1 -0
  45. package/dist/elements/chunks/{artifact-BSuPYFHY.js → artifact-BkYcfIlZ.js} +1 -1
  46. package/dist/elements/chunks/attachments-DwfNlubq.js +1 -0
  47. package/dist/elements/chunks/audio-visualizer-D7lB6mvR.js +1 -0
  48. package/dist/elements/chunks/{badge-TIMiJFKc.js → badge-Q0-Cmwzz.js} +1 -1
  49. package/dist/elements/chunks/{button-B9okqG73.js → button-flUbeufF.js} +1 -1
  50. package/dist/elements/chunks/{card-renderer-CSoTL_e1.js → card-renderer-3Dyl-FpN.js} +1 -1
  51. package/dist/elements/chunks/check-B5kBPKeo.js +1 -0
  52. package/dist/elements/chunks/chevron-down-DZ1GS39h.js +1 -0
  53. package/dist/elements/chunks/chevron-right-CvP7OUd2.js +1 -0
  54. package/dist/elements/chunks/{choice-card-CGMc3kek.js → choice-card-D4QUIOWZ.js} +1 -1
  55. package/dist/elements/chunks/circle-CDf9g6MQ.js +1 -0
  56. package/dist/elements/chunks/circle-check-CA47Nqbz.js +1 -0
  57. package/dist/elements/chunks/{circle-x-mhH7pOK2.js → circle-x-CJ_HVbC8.js} +1 -1
  58. package/dist/elements/chunks/code-block-BdLiTitd.js +1 -0
  59. package/dist/elements/chunks/collapsible-BzbXpPzr.js +1 -0
  60. package/dist/elements/chunks/{composer-CZZmtYOT.js → composer-Byve-n8K.js} +2 -2
  61. package/dist/elements/chunks/{confirm-card-BWjf2-xo.js → confirm-card-B0flE3MN.js} +1 -1
  62. package/dist/elements/chunks/context-VLIL3sJ-.js +1 -0
  63. package/dist/elements/chunks/controllable-DTwTIlwp.js +1 -0
  64. package/dist/elements/chunks/conversation-item-BDztezOG.js +1 -0
  65. package/dist/elements/chunks/copy-Nf-kqxXH.js +1 -0
  66. package/dist/elements/chunks/{create-tween-CUrM6D_o.js → create-tween-c4Z8TDYz.js} +2 -2
  67. package/dist/elements/chunks/default-input-C2iLFq0b.js +1 -0
  68. package/dist/elements/chunks/define-wjHR1MkU.js +1 -0
  69. package/dist/elements/chunks/disclosure-CcNbyLy0.js +1 -0
  70. package/dist/elements/chunks/{download-DnCyWFJE.js → download-C4V7tBdb.js} +1 -1
  71. package/dist/elements/chunks/dropdown-BgWTthUx.js +1 -0
  72. package/dist/elements/chunks/{ellipsis-CVxqfsDZ.js → ellipsis-7gU33mL2.js} +1 -1
  73. package/dist/elements/chunks/embed-D3KewsIJ.js +1 -0
  74. package/dist/elements/chunks/{external-link-DG2sRdQL.js → external-link-CSOEsNlx.js} +1 -1
  75. package/dist/elements/chunks/{file-text-D0J9F6M7.js → file-text-D1G8khle.js} +1 -1
  76. package/dist/elements/chunks/{file-tree-yGWNK0Js.js → file-tree-zvB2i7P9.js} +1 -1
  77. package/dist/elements/chunks/{folder-NV1pi_ud.js → folder-WW2LGLid.js} +1 -1
  78. package/dist/elements/chunks/form-CQirdC4W.js +1 -0
  79. package/dist/elements/chunks/hover-card-CJJkfHTK.js +1 -0
  80. package/dist/elements/chunks/icon-Cfgmf4fa.js +1 -0
  81. package/dist/elements/chunks/{info-C8r5Q6cc.js → info-DX3YMOt6.js} +1 -1
  82. package/dist/elements/chunks/input-BtW9U6Sq.js +1 -0
  83. package/dist/elements/chunks/{kbd-OGJDUT-O.js → kbd-LGXwuT_V.js} +1 -1
  84. package/dist/elements/chunks/{link-BdsfLB7b.js → link-2My69BqT.js} +1 -1
  85. package/dist/elements/chunks/{link-preview-Cf5KOP-i.js → link-preview-OQ9IEq0f.js} +1 -1
  86. package/dist/elements/chunks/{loader-B5QzK_8_.js → loader-iOxc_Tu-.js} +1 -1
  87. package/dist/elements/chunks/{markdown-DbozyYqa.js → markdown-DgBFaGAz.js} +1 -1
  88. package/dist/elements/chunks/{message-DtXKPqiR.js → message-VMZohrXx.js} +1 -1
  89. package/dist/elements/chunks/message-circle-CpXMM-_n.js +1 -0
  90. package/dist/elements/chunks/message-square-DxcWtETQ.js +1 -0
  91. package/dist/elements/chunks/message-tZmV2A3p.js +1 -0
  92. package/dist/elements/chunks/{minimize-2-SegJ_oku.js → minimize-2-DPIUKTrT.js} +1 -1
  93. package/dist/elements/chunks/{model-switcher-D7JrFFHp.js → model-switcher-DsT8tFB0.js} +1 -1
  94. package/dist/elements/chunks/{overlay-CV7z2YuX.js → overlay-DuiwdXjm.js} +1 -1
  95. package/dist/elements/chunks/{paperclip-Bg0ITU3b.js → paperclip-CRZVp4z_.js} +1 -1
  96. package/dist/elements/chunks/{progress-bar-D1_rzt6N.js → progress-bar-DNy66e_E.js} +1 -1
  97. package/dist/elements/chunks/{prompt-suggestion-D5Sm8xF1.js → prompt-suggestion-Bn64Nl7L.js} +1 -1
  98. package/dist/elements/chunks/reasoning-Emn9N4-T.js +1 -0
  99. package/dist/elements/chunks/{resizable-Dpzjlvp4.js → resizable-D181b4fM.js} +1 -1
  100. package/dist/elements/chunks/{rotate-cw-DzVDJOA1.js → rotate-cw-CPWe37D9.js} +1 -1
  101. package/dist/elements/chunks/{scroll-area-93A1bbeG.js → scroll-area-ClZkZxIk.js} +1 -1
  102. package/dist/elements/chunks/scroll-button-DPE-t3x_.js +1 -0
  103. package/dist/elements/chunks/{separator-DH2r_ZSZ.js → separator-CeJHQqLW.js} +1 -1
  104. package/dist/elements/chunks/{settings-BFMOd6yB.js → settings-CqaHgJF9.js} +1 -1
  105. package/dist/elements/chunks/{settings-group-B3VZKIcz.js → settings-group-CjqjLCOn.js} +1 -1
  106. package/dist/elements/chunks/share-CyfnNEqp.js +1 -0
  107. package/dist/elements/chunks/{skeleton-N8BuWYmf.js → skeleton-D8akBnKS.js} +1 -1
  108. package/dist/elements/chunks/slots-DaNjX0rc.js +1 -0
  109. package/dist/elements/chunks/{source-w9V0NnBn.js → source-UWCvmVak.js} +1 -1
  110. package/dist/elements/chunks/{star-DHvACxtm.js → star-DoHFAikQ.js} +1 -1
  111. package/dist/elements/chunks/store-Cjq0qwYN.js +1 -0
  112. package/dist/elements/chunks/{tasks-card-lPxoodlA.js → tasks-card-CmZ5xh6v.js} +1 -1
  113. package/dist/elements/chunks/{text-shimmer-BY_rI3s5.js → text-shimmer-DYn09zrz.js} +1 -1
  114. package/dist/elements/chunks/textarea-skiGHURM.js +1 -0
  115. package/dist/elements/chunks/{thumbs-up-DQe0hvkZ.js → thumbs-up-DX2Ijk3H.js} +1 -1
  116. package/dist/elements/chunks/{toast-store-VUZZBhzH.js → toast-store-CFnQpThX.js} +1 -1
  117. package/dist/elements/chunks/{tool-C1YtxwPu.js → tool-DKQ2D1DP.js} +1 -1
  118. package/dist/elements/chunks/{tooltip-BqwnFWhn.js → tooltip-B0G99y8w.js} +1 -1
  119. package/dist/elements/chunks/{triangle-alert-B6or7F5u.js → triangle-alert-F9cyUEyy.js} +1 -1
  120. package/dist/elements/chunks/{use-card-resolution-DJg32jGH.js → use-card-resolution-DoA2f_EU.js} +1 -1
  121. package/dist/elements/chunks/{variant-aurora-QXTZPyST.js → variant-aurora-qt6Zct8M.js} +2 -2
  122. package/dist/elements/chunks/variant-custom-tJp22_BQ.js +1 -0
  123. package/dist/{variant-wave-BwzrHD1s.js → elements/chunks/variant-wave-CaQ5ti39.js} +2 -2
  124. package/dist/elements/chunks/x-B6UnOiLw.js +1 -0
  125. package/dist/elements/coachmark.js +1 -1
  126. package/dist/elements/code-block.js +1 -1
  127. package/dist/elements/command.js +1 -1
  128. package/dist/elements/compare.js +1 -1
  129. package/dist/elements/composer.js +1 -1
  130. package/dist/elements/confirm-card.js +1 -1
  131. package/dist/elements/context-meter.js +1 -1
  132. package/dist/elements/conversation-item.d.ts +1 -0
  133. package/dist/elements/conversation-item.js +1 -0
  134. package/dist/elements/conversation-list.js +1 -1
  135. package/dist/elements/default-input.d.ts +3 -3
  136. package/dist/elements/define.d.ts +27 -0
  137. package/dist/elements/diagnostic-events.d.ts +74 -0
  138. package/dist/elements/dialog.js +1 -1
  139. package/dist/elements/dock.d.ts +1 -0
  140. package/dist/elements/dock.js +149 -0
  141. package/dist/elements/dropdown.d.ts +1 -0
  142. package/dist/elements/dropdown.js +1 -0
  143. package/dist/elements/editable-label.js +1 -1
  144. package/dist/elements/element-diagnostics.d.ts +81 -0
  145. package/dist/elements/embed.js +1 -1
  146. package/dist/elements/empty.js +1 -1
  147. package/dist/elements/feedback-bar.js +1 -1
  148. package/dist/elements/file-tree.js +1 -1
  149. package/dist/elements/file-upload.js +1 -1
  150. package/dist/elements/form.js +1 -1
  151. package/dist/elements/hover-card.js +1 -1
  152. package/dist/elements/icon.js +1 -1
  153. package/dist/elements/image.js +1 -1
  154. package/dist/elements/input.js +1 -1
  155. package/dist/elements/kbd.js +1 -1
  156. package/dist/elements/link-preview.js +1 -1
  157. package/dist/elements/loader.js +1 -1
  158. package/dist/elements/markdown.js +1 -1
  159. package/dist/elements/menu.js +1 -1
  160. package/dist/elements/message-skills.js +1 -1
  161. package/dist/elements/message.js +1 -1
  162. package/dist/elements/model-switcher.js +1 -1
  163. package/dist/elements/nav.js +1 -1
  164. package/dist/elements/notice.js +1 -1
  165. package/dist/elements/pane-group.js +1 -1
  166. package/dist/elements/pane.js +1 -1
  167. package/dist/elements/popover.js +1 -1
  168. package/dist/elements/progress-bar.js +1 -1
  169. package/dist/elements/prompt-dock.js +1 -1
  170. package/dist/elements/prompt-input.js +1 -1
  171. package/dist/elements/prompt-suggestions.js +1 -1
  172. package/dist/elements/reasoning.js +1 -1
  173. package/dist/elements/register.d.ts +2 -0
  174. package/dist/elements/remote.js +1 -1
  175. package/dist/elements/resizable.js +1 -1
  176. package/dist/elements/response-stream.js +3 -3
  177. package/dist/elements/screen.js +1 -1
  178. package/dist/elements/scroll-area.js +1 -1
  179. package/dist/elements/scroll-button.js +1 -1
  180. package/dist/elements/search.js +1 -1
  181. package/dist/elements/segmented.js +1 -1
  182. package/dist/elements/separator.js +1 -1
  183. package/dist/elements/setting-item.js +1 -1
  184. package/dist/elements/settings-group.js +1 -1
  185. package/dist/elements/skeleton.js +1 -1
  186. package/dist/elements/slots.d.ts +35 -3
  187. package/dist/elements/source.js +1 -1
  188. package/dist/elements/status.js +1 -1
  189. package/dist/elements/switch.js +1 -1
  190. package/dist/elements/tabs.js +1 -1
  191. package/dist/elements/tasks.js +1 -1
  192. package/dist/elements/text-shimmer.js +1 -1
  193. package/dist/elements/thinking-bar.js +1 -1
  194. package/dist/elements/thread.js +1 -1
  195. package/dist/elements/toast.js +1 -1
  196. package/dist/elements/tool.js +1 -1
  197. package/dist/elements/tooltip.js +1 -1
  198. package/dist/elements/voice-input.js +1 -1
  199. package/dist/elements/voice-output.js +1 -1
  200. package/dist/elements.d.ts +232 -148
  201. package/dist/index.d.ts +2 -0
  202. package/dist/index.js +5456 -4931
  203. package/dist/index.server.js +4142 -3669
  204. package/dist/kai-provider.es.js +40 -40
  205. package/dist/kai.es.js +1 -1
  206. package/dist/llms/llms-full.txt +184 -69
  207. package/dist/llms/llms.txt +3 -3
  208. package/dist/mcp.es.js +2669 -546
  209. package/dist/primitives/use-resize-observer.d.ts +23 -0
  210. package/dist/primitives/use-speech-recognition.d.ts +8 -0
  211. package/dist/primitives/use-text-stream.d.ts +5 -0
  212. package/dist/react/index.d.ts +115 -266
  213. package/dist/react.js +247 -221
  214. package/dist/register-impl-DpE7icIb.js +293 -0
  215. package/dist/schemas/index.d.ts +1 -1
  216. package/dist/schemas/tool-defs.d.ts +35 -0
  217. package/dist/schemas.js +403 -310
  218. package/dist/{solid-BMuDmFo_.js → solid-BtdqNZI7.js} +8435 -7394
  219. package/dist/{solid-CGYNdLRR.js → solid-CnavwBye.js} +5987 -5035
  220. package/dist/solid.d.ts +5 -0
  221. package/dist/solid.js +210 -203
  222. package/dist/solid.server.js +210 -203
  223. package/dist/state/index.d.ts +4 -0
  224. package/dist/state/persistence.d.ts +51 -0
  225. package/dist/state/stream.d.ts +50 -0
  226. package/dist/state/threads.d.ts +71 -0
  227. package/dist/state.js +269 -169
  228. package/dist/types.d.ts +4 -2
  229. package/dist/ui/dock.d.ts +109 -0
  230. package/dist/ui/hover-card.d.ts +44 -0
  231. package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-B8II3-I1.js} +27 -27
  232. package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CMNWOSJR.js} +28 -28
  233. package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CcuDMWwQ.js} +2 -2
  234. package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-BdvYC7af.js} +40 -40
  235. package/dist/{variant-custom-BhS9wIpU.js → variant-custom-C714mqKl.js} +65 -65
  236. package/dist/variant-custom-L16JLLZy.js +1 -0
  237. package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-2S4La2Ka.js} +2 -2
  238. package/dist/{variant-wave-CbVsmgwT.js → variant-wave-D7ruiA1W.js} +25 -25
  239. package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-ecwykeyL.js} +21 -21
  240. package/dist/wire/chunk.d.ts +47 -0
  241. package/dist/wire/diagnostics.d.ts +575 -0
  242. package/dist/wire/encode-probe.d.ts +70 -0
  243. package/dist/wire/encode.d.ts +24 -0
  244. package/dist/wire/index.d.ts +2 -0
  245. package/dist/wire/sse.d.ts +10 -2
  246. package/dist/wire.js +917 -480
  247. package/frameworks/react/index.tsx +132 -93
  248. package/llms-full.txt +184 -69
  249. package/llms.txt +3 -3
  250. package/package.json +27 -7
  251. package/src/agent-tooling/archetypes.ts +41 -9
  252. package/src/agent-tooling/catalog/README.md +676 -0
  253. package/src/agent-tooling/catalog/catalog-types.ts +231 -0
  254. package/src/agent-tooling/catalog/fabrications.ts +96 -0
  255. package/src/agent-tooling/catalog/invariants.ts +284 -0
  256. package/src/agent-tooling/catalog/labs-titles.ts +114 -0
  257. package/src/agent-tooling/catalog/scenarios.ts +87 -0
  258. package/src/agent-tooling/catalog/surfaces.ts +275 -0
  259. package/src/agent-tooling/integrations/anthropic.ts +7 -1
  260. package/src/agent-tooling/integrations/cloudflare.ts +43 -2
  261. package/src/agent-tooling/integrations/langgraph.ts +7 -1
  262. package/src/agent-tooling/integrations/mastra.ts +7 -1
  263. package/src/agent-tooling/integrations/mock.ts +92 -17
  264. package/src/agent-tooling/integrations/ollama.ts +7 -1
  265. package/src/agent-tooling/integrations/openai.ts +7 -1
  266. package/src/agent-tooling/integrations/openrouter.ts +7 -1
  267. package/src/agent-tooling/integrations/pi.ts +56 -1
  268. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
  269. package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
  270. package/src/agent-tooling/mcp/manifest.ts +100 -1
  271. package/src/agent-tooling/mcp/server.ts +61 -5
  272. package/src/agent-tooling/mcp/tools/reference.ts +440 -4
  273. package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
  274. package/src/agent-tooling/mcp/tools/theme.ts +146 -30
  275. package/src/agent-tooling/mcp/validate-args.ts +141 -0
  276. package/src/agent-tooling/registry.ts +19 -7
  277. package/src/agent-tooling/route-emit.ts +26 -2
  278. package/src/components/attachment-types.ts +47 -1
  279. package/src/components/attachments.tsx +169 -22
  280. package/src/components/audio-visualizer/fit-scale.ts +112 -0
  281. package/src/components/audio-visualizer/index.tsx +80 -3
  282. package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
  283. package/src/components/audio-visualizer/variant-bar.tsx +38 -6
  284. package/src/components/audio-visualizer/variant-custom.tsx +8 -2
  285. package/src/components/audio-visualizer/variant-grid.tsx +16 -11
  286. package/src/components/audio-visualizer/variant-radial.tsx +15 -10
  287. package/src/components/audio-visualizer/variant-wave.tsx +7 -2
  288. package/src/components/chat-container.tsx +4 -1
  289. package/src/components/chat-thread.tsx +36 -7
  290. package/src/components/code-block.tsx +79 -3
  291. package/src/components/composer.tsx +8 -1
  292. package/src/components/conversation-item.tsx +114 -4
  293. package/src/components/conversation-list.tsx +212 -12
  294. package/src/components/embed.tsx +4 -0
  295. package/src/components/form.tsx +41 -14
  296. package/src/components/message.tsx +75 -5
  297. package/src/components/response-stream.tsx +13 -7
  298. package/src/components/screen.tsx +5 -0
  299. package/src/components/scroll-button.tsx +7 -0
  300. package/src/components/toast.tsx +11 -5
  301. package/src/components/voice-input.tsx +35 -3
  302. package/src/components/voice-output.tsx +46 -6
  303. package/src/components/workspace-shell.tsx +285 -0
  304. package/src/diagnostics/hook.ts +352 -0
  305. package/src/diagnostics/index.ts +82 -0
  306. package/src/diagnostics/report-request.ts +296 -0
  307. package/src/elements/attachments.tsx +6 -7
  308. package/src/elements/audio-visualizer.tsx +48 -4
  309. package/src/elements/chat-workspace.tsx +159 -287
  310. package/src/elements/chat.tsx +12 -9
  311. package/src/elements/code-block.tsx +19 -1
  312. package/src/elements/command.tsx +4 -1
  313. package/src/elements/compiled.css +1 -1
  314. package/src/elements/conversation-item.tsx +80 -0
  315. package/src/elements/conversation-list.tsx +60 -11
  316. package/src/elements/default-input.tsx +5 -5
  317. package/src/elements/define.tsx +168 -8
  318. package/src/elements/diagnostic-events.ts +114 -0
  319. package/src/elements/dialog.tsx +47 -0
  320. package/src/elements/disclosure.ts +34 -12
  321. package/src/elements/dock.tsx +204 -0
  322. package/src/elements/dropdown.tsx +123 -0
  323. package/src/elements/element-diagnostics.ts +392 -0
  324. package/src/elements/element-manifest.json +12 -0
  325. package/src/elements/element-meta.json +672 -439
  326. package/src/elements/element-nonscalar.json +170 -0
  327. package/src/elements/element-types.d.ts +232 -148
  328. package/src/elements/menu.tsx +13 -0
  329. package/src/elements/prompt-dock.tsx +2 -1
  330. package/src/elements/prompt-input.tsx +8 -8
  331. package/src/elements/register-impl.ts +46 -0
  332. package/src/elements/register.ts +28 -0
  333. package/src/elements/resizable.tsx +52 -25
  334. package/src/elements/scroll-button.tsx +5 -0
  335. package/src/elements/slots.ts +107 -12
  336. package/src/elements/styles.css +30 -6
  337. package/src/elements/thinking-bar.tsx +16 -7
  338. package/src/elements/toast.tsx +3 -0
  339. package/src/elements/tool.tsx +26 -5
  340. package/src/elements/voice-input.tsx +11 -2
  341. package/src/elements/voice-output.tsx +16 -3
  342. package/src/index.ts +2 -0
  343. package/src/primitives/use-resize-observer.ts +33 -0
  344. package/src/primitives/use-speech-recognition.ts +12 -1
  345. package/src/primitives/use-stick-to-bottom.ts +34 -2
  346. package/src/primitives/use-text-stream.ts +33 -2
  347. package/src/remote/provider-runtime.ts +6 -3
  348. package/src/schemas/index.ts +1 -0
  349. package/src/schemas/tool-defs.ts +297 -6
  350. package/src/solid.ts +5 -0
  351. package/src/state/index.ts +12 -0
  352. package/src/state/persistence.ts +180 -0
  353. package/src/state/stream.ts +71 -4
  354. package/src/state/threads.ts +142 -0
  355. package/src/types.ts +4 -2
  356. package/src/ui/dialog.tsx +6 -0
  357. package/src/ui/dock.tsx +445 -0
  358. package/src/ui/dropdown.tsx +67 -23
  359. package/src/ui/hover-card.tsx +156 -6
  360. package/src/ui/input.tsx +29 -10
  361. package/src/ui/resizable.tsx +11 -0
  362. package/src/wire/chunk.ts +47 -0
  363. package/src/wire/consume.ts +185 -26
  364. package/src/wire/diagnostics.ts +727 -0
  365. package/src/wire/encode-probe.ts +214 -0
  366. package/src/wire/encode.ts +267 -14
  367. package/src/wire/formats/anthropic.ts +8 -1
  368. package/src/wire/formats/openai.ts +5 -0
  369. package/src/wire/index.ts +22 -0
  370. package/src/wire/read.ts +250 -6
  371. package/src/wire/sse.ts +16 -3
  372. package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
  373. package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
  374. package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
  375. package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
  376. package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
  377. package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
  378. package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
  379. package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
  380. package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
  381. package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
  382. package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
  383. package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
  384. package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
  385. package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
  386. package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
  387. package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
  388. package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
  389. package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
  390. package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
  391. package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
  392. package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
  393. package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
  394. package/dist/elements/chunks/input-DrseEjhp.js +0 -1
  395. package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
  396. package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
  397. package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
  398. package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
  399. package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
  400. package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
  401. package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
  402. package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
  403. package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
  404. package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
  405. package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
  406. package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
  407. package/dist/register-impl-DGmGzrEM.js +0 -145
  408. package/dist/variant-custom-MkTNTycd.js +0 -1
  409. package/src/primitives/card-validate-generator.testlib.ts +0 -38
@@ -25,10 +25,19 @@ defineWebComponent<Props, Events>('kai-thinking-bar', {
25
25
  text: 'Thinking',
26
26
  stoppable: false,
27
27
  stopLabel: 'Answer now',
28
- }, (props, { dispatch, flag }) => (
29
- <ThinkingBar
30
- text={props.text}
31
- stopLabel={props.stopLabel}
32
- onStop={flag('stoppable') ? () => dispatch('kai-stop') : undefined}
33
- />
34
- ));
28
+ }, (props, { dispatch, flag, reflectFlag }) => {
29
+ // `stoppable` reflects, following kai-tool's `disabled` (its FIX1). Without it the
30
+ // remove direction is dead: `el.removeAttribute('stoppable')` parses to `undefined`,
31
+ // the prop was already `undefined` after a bare-attribute add, so no prop change
32
+ // fires and `flag()`'s non-reactive hasAttribute fallback is never re-read the
33
+ // stop affordance stays rendered forever. reflectFlag's coercing read-back resolves
34
+ // every write through the same `flag()` policy, making both directions reactive.
35
+ reflectFlag('stoppable');
36
+ return (
37
+ <ThinkingBar
38
+ text={props.text}
39
+ stopLabel={props.stopLabel}
40
+ onStop={flag('stoppable') ? () => dispatch('kai-stop') : undefined}
41
+ />
42
+ );
43
+ });
@@ -47,6 +47,9 @@ interface Events {
47
47
  * Stack-level defaults are also declarative: `<kai-toast-region appearance="card"
48
48
  * inverse>` makes every toast that doesn't set its own `appearance`/`inverse`
49
49
  * render as an inverted card. A per-toast value always wins.
50
+ *
51
+ * Your app chrome must stay below the toast layer; set `--kai-toast-z`
52
+ * (default 100) on the host to move the layer.
50
53
  */
51
54
  defineWebComponent<Props, Events>('kai-toast-region', {
52
55
  toasts: [],
@@ -1,4 +1,4 @@
1
- import { Show } from 'solid-js';
1
+ import { createSignal, Show } from 'solid-js';
2
2
  import { defineWebComponent } from './define';
3
3
  import { Tool, type ToolPart } from '../components/tool';
4
4
  import { wireDisclosure } from './disclosure';
@@ -36,13 +36,34 @@ defineWebComponent<Props, Events>('kai-tool', {
36
36
  defaultOpen: undefined,
37
37
  disabled: undefined,
38
38
  }, (props, ctx) => {
39
- const { flag } = ctx;
40
- let api: CollapsibleController | undefined;
39
+ const { flag, reflectFlag } = ctx;
40
+
41
+ // A SIGNAL, not a `let`. This facade gates its whole subtree on `<Show when={props.tool}>`,
42
+ // and `tool` is an object prop, so the only sequence a consumer of the HTML spelling
43
+ // has is markup-then-assign: the element connects with no tool, renders nothing, and
44
+ // the Collapsible — and therefore the controller — arrives a tick later.
45
+ //
46
+ // With a plain `let`, wireDisclosure's effects ran once against `undefined` and never
47
+ // again, because the getter they were handed was not reactive and a bare `open`
48
+ // attribute never changes `props.open` to re-trigger them. Net result: `<kai-tool open>`
49
+ // silently stayed shut while `el.open` read back `true` — the property and the
50
+ // rendering disagreed. Making the controller reactive is the whole fix: the effects
51
+ // re-run the moment it lands. `Tool` already tracks its own copy this way internally.
52
+ // Pinned by the ordering rows in tests/elements/tool.test.tsx.
53
+ const [api, setApi] = createSignal<CollapsibleController>();
41
54
 
42
55
  // The standard disclosure surface: settable+reflecting `open`, kai-open-change,
43
56
  // show/hide/toggle, disabled-gating. See ./disclosure. This is the SOLE emitter
44
57
  // of kai-open-change — the Tool/Collapsible no longer wires its own.
45
- wireDisclosure(ctx, () => api, () => props.open);
58
+ wireDisclosure(ctx, api, () => props.open);
59
+
60
+ // `disabled` reflects too, following kai-dock. Without it the prop is write-only in
61
+ // the read direction AND deaf in the write one: `el.setAttribute('disabled', '')`
62
+ // after mount is parsed by component-register to `undefined`, so the prop never
63
+ // changes and nothing re-renders. reflectFlag's coercing setter resolves that
64
+ // `undefined` back through the same `flag()` policy, which is what makes the plain
65
+ // HTML gesture work at runtime and not only at parse time (findings G-05).
66
+ reflectFlag('disabled');
46
67
 
47
68
  return (
48
69
  <Show when={props.tool}>
@@ -50,7 +71,7 @@ defineWebComponent<Props, Events>('kai-tool', {
50
71
  toolPart={props.tool!}
51
72
  defaultOpen={flag('defaultOpen')}
52
73
  disabled={flag('disabled')}
53
- controllerRef={(a) => (api = a)}
74
+ controllerRef={(a) => setApi(a)}
54
75
  />
55
76
  </Show>
56
77
  );
@@ -39,6 +39,13 @@ interface Events {
39
39
  * push-to-talk indicator) in sync with the mic. Fires on real transitions
40
40
  * only (manual click and programmatic start()/stop()), never on mount. */
41
41
  'kai-recording-change': { recording: boolean };
42
+ /** A voice session failed, so no failure is ever silent. `detail.source` names
43
+ * the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on
44
+ * `<kai-voice-output>`), `detail.error` carries the platform error code, the
45
+ * thrown exception's name, or `no-result` when recognition ended with no error
46
+ * and no text (the user said nothing), and `detail.message` is human-readable.
47
+ * Deliberate cancellation does not fire. */
48
+ 'kai-voice-error': { source: 'recognition'; error: string; message: string };
42
49
  }
43
50
 
44
51
  /**
@@ -47,8 +54,9 @@ interface Events {
47
54
  * `SpeechRecognition` (Chrome/Safari; no Firefox — and cloud-based in Chrome).
48
55
  * Set `el.transcribe` to route audio through your own async transcriber instead.
49
56
  * Where neither is available it records the blob and emits `kai-audio-captured`
50
- * with no text. Also emits `kai-transcription` (final text) and, with `interim`,
51
- * `kai-transcript-interim` (live partials).
57
+ * with no text. Also emits `kai-transcription` (final text), `kai-voice-error`
58
+ * (a failed or empty session) and, with `interim`, `kai-transcript-interim`
59
+ * (live partials).
52
60
  */
53
61
  defineWebComponent<Props, Events>('kai-voice-input', {
54
62
  transcribe: undefined,
@@ -85,6 +93,7 @@ defineWebComponent<Props, Events>('kai-voice-input', {
85
93
  onTranscription={(text) => dispatch('kai-transcription', { text })}
86
94
  onInterim={(text) => dispatch('kai-transcript-interim', { text })}
87
95
  onRecordingChange={(recording) => dispatch('kai-recording-change', { recording })}
96
+ onError={(detail) => dispatch('kai-voice-error', detail)}
88
97
  controllerRef={(c) => (controller = c)}
89
98
  />
90
99
  );
@@ -20,18 +20,30 @@ interface Props extends Record<string, unknown> {
20
20
 
21
21
  /** Events fired by `<kai-voice-output>`. */
22
22
  interface Events {
23
- /** Playback started or stopped. Drive your own UI in sync. Fires on real transitions
24
- * only (manual click and programmatic speak()/stop()), never on mount. */
23
+ /** Playback started or stopped. Drive your own UI in sync. `speaking: true`
24
+ * fires when audio actually starts (utterance.onstart natively; audio playback
25
+ * beginning on the `synthesize` path), not when speak() is called; earlier
26
+ * releases fired it optimistically inside speak() itself. Fires on real
27
+ * transitions only (manual click and programmatic speak()/stop()), never on
28
+ * mount. */
25
29
  'kai-speaking-change': { speaking: boolean };
26
30
  /** The model path (`synthesize`) resolved audio: the raw `Blob` before playback. */
27
31
  'kai-synthesized': { blob: Blob };
32
+ /** A voice session failed, so no failure is ever silent. `detail.source` names
33
+ * the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on
34
+ * `<kai-voice-output>`), `detail.error` carries the platform error code, the
35
+ * thrown exception's name, or `no-result` when recognition ended with no error
36
+ * and no text (the user said nothing), and `detail.message` is human-readable.
37
+ * Deliberate cancellation does not fire. */
38
+ 'kai-voice-error': { source: 'synthesis'; error: string; message: string };
28
39
  }
29
40
 
30
41
  /**
31
42
  * `<kai-voice-output>` — a speaker button that reads `text` aloud. Native by
32
43
  * default (`speechSynthesis`); set `el.synthesize` to route through your TTS
33
44
  * model instead. The output sibling of `<kai-voice-input>`. Emits
34
- * `kai-speaking-change` and (model path) `kai-synthesized`.
45
+ * `kai-speaking-change`, `kai-voice-error` (a failed synthesis) and (model
46
+ * path) `kai-synthesized`.
35
47
  */
36
48
  defineWebComponent<Props, Events>('kai-voice-output', {
37
49
  text: '',
@@ -63,6 +75,7 @@ defineWebComponent<Props, Events>('kai-voice-output', {
63
75
  onSynthesize={props.synthesize ? (text) => props.synthesize!(text) : undefined}
64
76
  onSpeakingChange={(speaking) => dispatch('kai-speaking-change', { speaking })}
65
77
  onSynthesized={(blob) => dispatch('kai-synthesized', { blob })}
78
+ onError={(detail) => dispatch('kai-voice-error', detail)}
66
79
  controllerRef={(c) => (controller = c)}
67
80
  />
68
81
  );
package/src/index.ts CHANGED
@@ -339,6 +339,8 @@ export type { VoiceInputProps, VoiceInputController } from './components/voice-i
339
339
  export { ConversationList } from './components/conversation-list';
340
340
  export type { ConversationListProps, ConversationListController } from './components/conversation-list';
341
341
  export { ConversationItem } from './components/conversation-item';
342
+ export { SlottedConversationItem } from './components/conversation-item';
343
+ export type { SlottedConversationItemProps } from './components/conversation-item';
342
344
  export type { ConversationItemProps } from './components/conversation-item';
343
345
  export { ModelSwitcher } from './components/model-switcher';
344
346
  export type { ModelSwitcherProps } from './components/model-switcher';
@@ -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 (D1, rung 5 IVP
18
+ * task-10-report.md): `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,