@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
@@ -9,8 +9,24 @@ import {
9
9
  } from '@kitn.ai/ui/schemas';
10
10
  import type { CardSchemaName, ToolProvider } from '@kitn.ai/ui/schemas';
11
11
  import type { Tool } from './types';
12
- import { cardHostTags, cardTagForType, cardTypeForTag, getElement, listElements } from '../manifest';
12
+ import {
13
+ cardHostTags,
14
+ cardTagForType,
15
+ cardTypeForTag,
16
+ entryForTag,
17
+ getElement,
18
+ listElements,
19
+ optInEntryForTag,
20
+ } from '../manifest';
13
21
  import type { CemMember } from '../manifest';
22
+ // The RAW literals, not listInvariants() / listSurfaceRecipes(). Those re-run a
23
+ // zod parse over the whole catalog, and this is a per-lookup serving path called
24
+ // once for every element a harness asks about. The parse is not skipped, only
25
+ // moved: invariants.test.ts and surfaces.test.ts run it over these same literals
26
+ // in CI, so a malformed record fails a test rather than a request.
27
+ import { invariants } from '../../catalog/invariants';
28
+ import { surfaceRecipes } from '../../catalog/surfaces';
29
+ import type { TInvariant, TInvariantExample, TSurfaceRecipe } from '../../catalog/catalog-types';
14
30
 
15
31
  /**
16
32
  * component_reference — look up AI/UI (kai-*) web components, their props,
@@ -225,6 +241,341 @@ function renderCardHost(tag: string): string[] {
225
241
  ];
226
242
  }
227
243
 
244
+ // ─────────────────────────────────────────────────────────────────────────────
245
+ // The composition catalog: invariants, and recipe membership
246
+ // ─────────────────────────────────────────────────────────────────────────────
247
+
248
+ /**
249
+ * An invariant applies to a tag if it is unscoped by tag, or names it.
250
+ *
251
+ * `appliesTo.targets` deliberately does NOT filter here: `upgrade-race` is
252
+ * scoped to script-tag DELIVERY, which is a fact about how the page loads and
253
+ * not about which element is on it — every element can be dropped onto a CDN
254
+ * page. So it is served everywhere and the scope is RENDERED (see `scopeOf`),
255
+ * which is the difference between a conditional rule a reader can apply and an
256
+ * unqualified one they will either over-apply or stop trusting.
257
+ */
258
+ function invariantsFor(tag: string): TInvariant[] {
259
+ return invariants.filter((i) => !i.appliesTo.tags || i.appliesTo.tags.includes(tag));
260
+ }
261
+
262
+ /**
263
+ * The recipe's nesting, as markup a reader can paste.
264
+ *
265
+ * `noteSep` is how much of the record to print: the appendix passes ' — ' and
266
+ * gets the WHY, an element lookup passes '' and gets only the shape, on the same
267
+ * split the wiring rows already use. A recipe with no `composition` prints
268
+ * nothing at all rather than "flat" — the field being absent means nobody
269
+ * decided, and a rendered "(none)" would turn a gap into a claim.
270
+ */
271
+ function compositionLines(r: TSurfaceRecipe, noteSep: string): string[] {
272
+ if (!r.composition) return [];
273
+ return [
274
+ '- **Composition** — where the parts go (a slotted child, not a sibling):',
275
+ ...r.composition.map(
276
+ (c) =>
277
+ ` - \`<${c.child} slot="${c.slot}">\` goes INSIDE \`<${c.parent}>\`` +
278
+ (noteSep && c.note ? `${noteSep}${c.note}` : ''),
279
+ ),
280
+ ];
281
+ }
282
+
283
+ function recipesFor(tag: string): TSurfaceRecipe[] {
284
+ return surfaceRecipes.filter((r) => r.ingredients.includes(tag));
285
+ }
286
+
287
+ /**
288
+ * How the coverage of one invariant reads — never a bare status word, and never
289
+ * silence.
290
+ *
291
+ * Three of the catalog's records are enforced by NOTHING and two more by half of
292
+ * what they say. A section that printed every rule as an equal-looking bullet
293
+ * would put back exactly the overstatement those records were rewritten to
294
+ * remove, one layer further out where it is harder to see. The wording also says
295
+ * whose code the guard reads: every path here is inside the KIT's own repo, and
296
+ * none of them checks the consumer's.
297
+ */
298
+ function coverageOf(inv: TInvariant): string {
299
+ const by = inv.enforcedBy;
300
+ // `guard` is '' only for kind:'none', and that combination reaches neither the
301
+ // 'enforced' nor the 'partial' branch below: invariants.test.ts ("open ⟺
302
+ // enforcedBy.kind none") asserts the equivalence in BOTH directions, so a
303
+ // kind:'none' record is always status:'open'. Named here because a reader of
304
+ // this file alone cannot see what makes `enforced by ` with nothing after it
305
+ // unreachable.
306
+ const guard =
307
+ by.kind === 'test'
308
+ ? `the kit's own tests (${by.paths.join(', ')})`
309
+ : by.kind === 'lint'
310
+ ? `the kit's \`${by.script}\` script, in required CI`
311
+ : by.kind === 'structural'
312
+ ? `a structural guarantee in ${by.path}`
313
+ : '';
314
+
315
+ switch (inv.status) {
316
+ case 'enforced':
317
+ return `enforced by ${guard}`;
318
+ case 'partial':
319
+ return `PARTIALLY ENFORCED: one half is covered, by ${guard}; the statement says which half is not`;
320
+ case 'open':
321
+ return (
322
+ 'NOT ENFORCED: nothing in the kit checks this' +
323
+ (by.kind === 'none' && by.until ? `, until ${by.until}` : '') +
324
+ '. A rule you apply, not a guarantee you will be warned about'
325
+ );
326
+ }
327
+ }
328
+
329
+ /** What narrows an invariant, when something does. `targets` is not `tags`. */
330
+ function scopeOf(inv: TInvariant): string {
331
+ const { tags, targets, parts } = inv.appliesTo;
332
+ const bits: string[] = [];
333
+ if (tags) bits.push(`only ${tags.join(', ')}`);
334
+ if (targets) bits.push(`${targets.join(' / ')} delivery only`);
335
+ if (parts) bits.push(`parts ${parts.join(', ')}`);
336
+ return bits.join('; ');
337
+ }
338
+
339
+ /**
340
+ * The wrong/right pairs, as one fenced block per invariant.
341
+ *
342
+ * A fence rather than inline code because a `right` form is allowed to span
343
+ * lines (the URL guards do), and because the pairs are meant to be
344
+ * pattern-matched and grepped verbatim — the self-audit checklist greps emitted
345
+ * code for the `wrong` form and expects zero hits, which only works if what is
346
+ * served here is the literal and not a paraphrase of it.
347
+ */
348
+ function exampleLines(examples: TInvariantExample[]): string[] {
349
+ if (examples.length === 0) return [];
350
+ const out: string[] = ['', '```js'];
351
+ examples.forEach((ex, i) => {
352
+ if (i > 0) out.push('');
353
+ out.push('// WRONG', ex.wrong, '// RIGHT', ex.right);
354
+ if (ex.note) out.push(...ex.note.split('\n').map((l) => `// ${l}`));
355
+ });
356
+ out.push('```');
357
+ return out;
358
+ }
359
+
360
+ /**
361
+ * The one sentence saying how much of this section is actually guarded.
362
+ *
363
+ * BOTH numerators are derived and both are needed. `open` alone was the first
364
+ * form of this line, and it is the more quotable half: "3 of the 7 below are
365
+ * enforced by NOTHING" compresses, in any reader summarising it, into "3
366
+ * unenforced, 4 enforced" — and two of that four are `partial`, covered on one
367
+ * half only. That is this repo's own compression-drops-the-qualifier failure,
368
+ * sitting in the sentence written to prevent it. Naming both counts leaves the
369
+ * compression nothing to invent.
370
+ *
371
+ * Returns '' when every applicable record is fully enforced, so the line can
372
+ * never outlive the gap it describes and become a comfortable falsehood.
373
+ *
374
+ * Exported for reference.test.ts, which drives all four count combinations over
375
+ * synthetic records — the real catalog can only instance one of them at a time.
376
+ */
377
+ export function coverageSummary(applicable: TInvariant[]): string {
378
+ const open = applicable.filter((i) => i.status === 'open').length;
379
+ const partial = applicable.filter((i) => i.status === 'partial').length;
380
+ if (open === 0 && partial === 0) return '';
381
+
382
+ const total = applicable.length;
383
+ const half = (n: number) => `only half of what ${n === 1 ? 'it says' : 'they say'}`;
384
+ const clauses: string[] = [];
385
+
386
+ if (open > 0) {
387
+ clauses.push(`${open} of the ${total} below ${open === 1 ? 'is' : 'are'} enforced by NOTHING at all`);
388
+ }
389
+ if (partial > 0) {
390
+ clauses.push(
391
+ open > 0
392
+ ? `${partial} more by ${half(partial)}`
393
+ : `${partial} of the ${total} below ${partial === 1 ? 'is' : 'are'} enforced by ${half(partial)}`,
394
+ );
395
+ }
396
+ return ` ${clauses.join(', and ')}.`;
397
+ }
398
+
399
+ /**
400
+ * `###` to match every other section heading in this file (see '### Props'),
401
+ * `####` for the per-record blocks, matching the card contract's sub-headings.
402
+ *
403
+ * Each invariant gets its heading (id, scope, coverage) and its one-line
404
+ * `statement` — enough to apply the rule and to know how much to trust it —
405
+ * but NOT the diagnosis and wrong/right examples. Those are the bulk: measured
406
+ * on this tree, the full body of the 7 catalog records runs ~13 KB, and every
407
+ * unscoped record (5 of 7) applies to all 80 elements, so printing the full
408
+ * body here paid that in full on every lookup. `renderInvariantAppendix`
409
+ * carries the long form exactly once; this function points to it instead of
410
+ * repeating it.
411
+ */
412
+ function catalogSectionLines(tag: string): string[] {
413
+ const applicable = invariantsFor(tag);
414
+ const lines: string[] = [];
415
+
416
+ if (applicable.length > 0) {
417
+ lines.push(
418
+ '',
419
+ '### Invariants',
420
+ 'Rules that have already broken real consumers of this kit. Each block says what enforces ' +
421
+ 'it — read that line rather than assuming CI catches a violation, because nothing here ' +
422
+ 'reads YOUR code.' + coverageSummary(applicable) + ' Diagnosis and wrong/right examples for ' +
423
+ 'every invariant are served once, not repeated per element — call component_reference with ' +
424
+ '{ name: "invariants" }.',
425
+ );
426
+
427
+ for (const inv of applicable) {
428
+ const scope = scopeOf(inv);
429
+ lines.push('', `#### ${inv.id}${scope ? ` (${scope})` : ''} — ${coverageOf(inv)}`, inv.statement);
430
+ }
431
+ }
432
+
433
+ // No recipe, no section. An element that is in none gets its universal
434
+ // invariants and nothing else — a "part of: (none)" row would be a fabricated
435
+ // membership claim dressed as an empty one.
436
+ const recipes = recipesFor(tag);
437
+ if (recipes.length > 0) {
438
+ lines.push(
439
+ '',
440
+ '### Appears in surface recipes',
441
+ 'Compositions this element is part of, each with the whole ingredient list and the host ' +
442
+ 'wiring — nothing coordinates one element with another except your own code ' +
443
+ '(host-coordinates). The WHY behind each wiring edge, and the caveats on the nesting ' +
444
+ 'below, are served once rather than repeated per ingredient — call component_reference ' +
445
+ 'with { name: "recipes" }.',
446
+ );
447
+ for (const r of recipes) {
448
+ lines.push(
449
+ '',
450
+ `#### ${r.id} — ${r.intent}`,
451
+ `- **Ingredients:** ${r.ingredients.map((t) => `\`<${t}>\``).join(', ')}`,
452
+ `- **Delivery:** ${r.targets.join(', ')} · archetype: ${r.archetypes.join(', ')}`,
453
+ `- **Backend:** your own endpoint, read with \`${r.backend.reader}\` from \`@kitn.ai/ui/wire\``,
454
+ // WHERE the parts go. Printed per element and not only in the appendix,
455
+ // because this is the one fact a builder cannot infer from anything else
456
+ // on the page: the wiring rows say which event drives which property and
457
+ // are silent about nesting, so an element lookup that omitted this left
458
+ // the reader to guess between a child and a sibling. Short enough to
459
+ // repeat; the `note` (the WHY) stays in the appendix with the wiring notes.
460
+ ...compositionLines(r, ''),
461
+ // Bare ids, deliberately. This row is a DEPENDENCY list, not a coverage
462
+ // claim, and it can only ever be read a few lines below the full
463
+ // `### Invariants` section in the same response, where each of these ids
464
+ // already carries its own coverage line. Repeating the status here would
465
+ // print it a second (and, with two recipes, a third) time per element for
466
+ // no fact a reader does not already have on the page.
467
+ `- **Invariants it leans on:** ${r.invariants.join(', ')}`,
468
+ // Compact: the edge (event out of A, property into B) with no `note`.
469
+ // The note is the WHY — often a full sentence, sometimes several — and
470
+ // repeating it is the same shape of duplication task 4 removed from
471
+ // invariants: this recipe's ingredients (kai-chat, kai-conversations,
472
+ // kai-resizable, kai-artifact) all print this identical wiring list.
473
+ // `renderRecipeAppendix` carries the notes exactly once.
474
+ '- **Wiring** — event out of A, property into B, wired by the host:',
475
+ );
476
+ for (const w of r.wiring) {
477
+ lines.push(` - \`<${w.from}>\` fires \`${w.event}\` → host sets \`${w.to}.${w.property}\``);
478
+ }
479
+ }
480
+ }
481
+
482
+ return lines;
483
+ }
484
+
485
+ /**
486
+ * The long-form recipe reference, served exactly once rather than repeated on
487
+ * every ingredient. `catalogSectionLines` prints the ingredients, delivery,
488
+ * backend and a compact wiring list (edge only, no `note`) per element and
489
+ * points here for the rest — the WHY behind each wiring edge, which is the
490
+ * bulk: `workspace-chat` alone has 4 ingredients, and every one of them
491
+ * printed every wiring note in full before this moved. Reached via
492
+ * `component_reference({ name: "recipes" })`.
493
+ */
494
+ function renderRecipeAppendix(): string[] {
495
+ const lines: string[] = [
496
+ `## Surface recipe catalog (${surfaceRecipes.length} total) — wiring notes`,
497
+ '',
498
+ 'Every element lookup that appears in a recipe lists its ingredients, delivery, backend and ' +
499
+ 'a compact wiring list (event out of A, property into B). This is the long form: the WHY ' +
500
+ 'behind each wiring edge, written once here rather than repeated on every ingredient.',
501
+ ];
502
+
503
+ for (const r of surfaceRecipes) {
504
+ lines.push(
505
+ '',
506
+ `#### ${r.id} — ${r.intent}`,
507
+ `- **Ingredients:** ${r.ingredients.map((t) => `\`<${t}>\``).join(', ')}`,
508
+ `- **Delivery:** ${r.targets.join(', ')} · archetype: ${r.archetypes.join(', ')}`,
509
+ `- **Backend:** your own endpoint, read with \`${r.backend.reader}\` from \`@kitn.ai/ui/wire\``,
510
+ `- **Invariants it leans on:** ${r.invariants.join(', ')}`,
511
+ ...compositionLines(r, ' — '),
512
+ '- **Wiring** — event out of A, property into B, wired by the host:',
513
+ );
514
+ for (const w of r.wiring) {
515
+ lines.push(
516
+ ` - \`<${w.from}>\` fires \`${w.event}\` → host sets \`${w.to}.${w.property}\`` +
517
+ (w.note ? ` — ${w.note}` : ''),
518
+ );
519
+ }
520
+ }
521
+
522
+ return lines;
523
+ }
524
+
525
+ /**
526
+ * The long-form invariant reference, served exactly once rather than repeated
527
+ * on every element it applies to. `catalogSectionLines` prints only the id,
528
+ * scope and one-line statement per element and points here for the rest —
529
+ * this is that "rest": every record's full statement again for context, its
530
+ * diagnosis rows, and its wrong/right examples, each written once for the
531
+ * whole catalog regardless of how many of the 80 elements the record applies
532
+ * to. Reached via `component_reference({ name: "invariants" })`.
533
+ */
534
+ function renderInvariantAppendix(): string[] {
535
+ const lines: string[] = [
536
+ `## Invariant catalog (${invariants.length} total) — diagnosis and examples`,
537
+ '',
538
+ 'Every element lookup lists the invariants that apply to it by id and one-line statement. ' +
539
+ 'This is the long form: full statement, diagnosis and wrong/right examples for each record, ' +
540
+ 'written once here rather than repeated on every element it applies to.',
541
+ ];
542
+
543
+ for (const inv of invariants) {
544
+ const scope = scopeOf(inv);
545
+ lines.push('', `#### ${inv.id}${scope ? ` (${scope})` : ''} — ${coverageOf(inv)}`, inv.statement);
546
+ if (inv.diagnosis.length > 0) {
547
+ lines.push('', 'If you are debugging:');
548
+ for (const d of inv.diagnosis) lines.push(`- ${d.symptom} → ${d.cause}`);
549
+ }
550
+ lines.push(...exampleLines(inv.examples));
551
+ }
552
+
553
+ return lines;
554
+ }
555
+
556
+ /**
557
+ * The payload out of `CustomEvent<T>`, or `undefined` when there is no payload.
558
+ *
559
+ * The manifest types every event, but as the wrapper — printing that raw teaches
560
+ * a reader to write `CustomEvent<...>` where a payload belongs. Anything that is
561
+ * not of the form `CustomEvent<…>` has NO payload to print, and this returns
562
+ * `undefined` so the caller omits the `detail` clause entirely.
563
+ *
564
+ * That is read off the generator rather than guessed at. gen-element-api.mjs
565
+ * writes the CEM type as ``CustomEvent<${e.detail}>`` when the element declares a
566
+ * detail and the bare string `CustomEvent` when it does not — exactly two shapes,
567
+ * and the bare one means the detail is `void` (e.g. `'kai-click': void` in
568
+ * button.tsx). Passing an unrecognised type through unchanged looked like a safe
569
+ * fallback for an already-unwrapped payload; what it actually caught was the void
570
+ * events, which then rendered ``Carries no detail. `detail`: `CustomEvent` `` — a
571
+ * line contradicting itself, on 13 events across 10 elements. The whole-manifest
572
+ * probe in reference.test.ts holds both directions of the rule.
573
+ */
574
+ function eventDetail(typeText: string | undefined): string | undefined {
575
+ const m = /^CustomEvent<([\s\S]*)>$/.exec(typeText?.trim() ?? '');
576
+ return m ? m[1].trim() || undefined : undefined;
577
+ }
578
+
228
579
  function formatReference(tag: string, provider: ToolProvider): string {
229
580
  const el = getElement(tag);
230
581
 
@@ -246,6 +597,66 @@ function formatReference(tag: string, provider: ToolProvider): string {
246
597
  lines.push('', el.description.trim());
247
598
  }
248
599
 
600
+ // ── Getting the element ────────────────────────────────────────────────────
601
+ // FIRST, above every other section. An element that never upgrades renders
602
+ // nothing and logs NOTHING: the property assigns and reads back fine, and
603
+ // whenDefined() never settles, so the listener is never attached. That symptom
604
+ // is also what props-not-attributes blames on a different cause, so a reader
605
+ // who has the invariants and not this line is steered to the wrong diagnosis.
606
+ const entry = entryForTag(tag);
607
+ const iface = el.name;
608
+ const neverUpgrades =
609
+ 'If you skip registering it the element never upgrades: nothing renders, ' +
610
+ '**no error and no warning is logged**, a property you set assigns and reads ' +
611
+ `back correctly, and \`customElements.whenDefined('${tag}')\` never resolves.`;
612
+ lines.push('', '### Getting the element');
613
+ if (entry) {
614
+ lines.push(
615
+ `Register it before you use it. ${neverUpgrades}`,
616
+ '',
617
+ '```ts',
618
+ "import '@kitn.ai/ui/elements';",
619
+ `import '@kitn.ai/ui/elements/${entry}'; // or just this one`,
620
+ '```',
621
+ );
622
+ } else {
623
+ // entryForTag is undefined exactly when register-impl.ts does not import this
624
+ // element's source file — i.e. it is NOT in the register-all bundle. The only
625
+ // current instance is kai-remote, a deliberate exception (opt-in cross-origin
626
+ // iframe card) documented at src/elements/element-diagnostics.ts:347-363 and
627
+ // vite.config.elements.ts:44-50. `import '@kitn.ai/ui/elements'` would NOT
628
+ // register a tag in this state, so asserting it here is exactly the false
629
+ // claim this section exists to prevent.
630
+ //
631
+ // The specifier is still NOT guessed — stripping `kai-` is wrong for ten of
632
+ // the eighty elements. `optInEntryForTag` reads it off the module the
633
+ // per-element build actually emitted, matched to this tag by the tag literal
634
+ // it registers; see the note there. Telling the reader to go look it up was
635
+ // the last place in this reference where "how to make the element exist" did
636
+ // not answer itself, and the answer was in the build config all along.
637
+ const optIn = optInEntryForTag(tag);
638
+ lines.push(
639
+ `**\`${tag}\` is opt-in — it is not part of \`import '@kitn.ai/ui/elements'\` ` +
640
+ '(register-all), and that import alone will NOT register it.** ' +
641
+ (optIn
642
+ ? `Import its own entry point instead. ${neverUpgrades}`
643
+ : // No built module claims this tag, so there is no specifier to name.
644
+ // Stay honest rather than inventing one.
645
+ 'Find its specific `@kitn.ai/ui/elements/<name>` entry point in the ' +
646
+ `package's published exports before using it. ${neverUpgrades}`),
647
+ );
648
+ if (optIn) {
649
+ lines.push('', '```ts', `import '@kitn.ai/ui/elements/${optIn}';`, '```');
650
+ }
651
+ }
652
+ if (iface) {
653
+ lines.push(
654
+ '',
655
+ `TypeScript: \`import type { ${iface} } from '@kitn.ai/ui/elements';\` — ` +
656
+ 'the element interface ships with the package; do not hand-roll a structural type.',
657
+ );
658
+ }
659
+
249
660
  // ── Contract note ──────────────────────────────────────────────────────────
250
661
  lines.push(
251
662
  '',
@@ -306,7 +717,12 @@ function formatReference(tag: string, provider: ToolProvider): string {
306
717
  lines.push('', '### Events (CustomEvent, listen via addEventListener)');
307
718
  for (const ev of events) {
308
719
  const desc = ev.description?.trim() ?? '';
309
- lines.push(`- **${ev.name}** — ${desc}`);
720
+ const detail = eventDetail(ev.type?.text);
721
+ lines.push(
722
+ detail
723
+ ? `- **${ev.name}** — ${desc} \`detail\`: \`${detail}\``
724
+ : `- **${ev.name}** — ${desc}`,
725
+ );
310
726
  }
311
727
  }
312
728
 
@@ -372,6 +788,9 @@ function formatReference(tag: string, provider: ToolProvider): string {
372
788
  }
373
789
  }
374
790
 
791
+ // ── The composition catalog ────────────────────────────────────────────────
792
+ lines.push(...catalogSectionLines(tag));
793
+
375
794
  return lines.join('\n');
376
795
  }
377
796
 
@@ -382,7 +801,16 @@ export const reference: Tool = {
382
801
  'For a card-backed element it also returns the card\'s JSON Schema and a ready-to-send ' +
383
802
  'tool definition generated from it — pass `provider` to get that provider\'s envelope.',
384
803
  inputSchema: z.object({
385
- name: z.string().optional(),
804
+ name: z
805
+ .string()
806
+ .optional()
807
+ .describe(
808
+ 'The element tag, e.g. "kai-chat". Omit it (or pass "list") to get the ' +
809
+ 'index of every element with a one-line summary, then ask again for the one you want. ' +
810
+ 'Pass "invariants" for the full diagnosis and wrong/right examples behind every ' +
811
+ 'invariant id an element lookup shows. Pass "recipes" for the full wiring notes ' +
812
+ 'behind every surface recipe an element lookup names.',
813
+ ),
386
814
  provider: z
387
815
  .enum(PROVIDERS)
388
816
  .optional()
@@ -433,7 +861,15 @@ export const reference: Tool = {
433
861
  '\n\nCall component_reference with a specific name (e.g. { name: "kai-chat" }) for full API details.' +
434
862
  `\n\nCard-backed elements — ask for one of these to get its JSON Schema and a generated ` +
435
863
  `\`${KAI_TOOL_PREFIX}*\` tool definition:\n ${cardRows.join(', ')}` +
436
- `\nThe elements that HOST them (and carry the \`cardTypes\` / \`cardSchemas\` props): ${cardHostTags().join(', ')}`;
864
+ `\nThe elements that HOST them (and carry the \`cardTypes\` / \`cardSchemas\` props): ${cardHostTags().join(', ')}` +
865
+ `\n\nCall component_reference with { name: "invariants" } for the full diagnosis and ` +
866
+ 'wrong/right examples behind every invariant id shown on an element lookup.' +
867
+ `\n\nCall component_reference with { name: "recipes" } for the full wiring notes behind ` +
868
+ 'every surface recipe an element lookup names.';
869
+ } else if (name === 'invariants') {
870
+ text = renderInvariantAppendix().join('\n');
871
+ } else if (name === 'recipes') {
872
+ text = renderRecipeAppendix().join('\n');
437
873
  } else {
438
874
  text = formatReference(name, provider);
439
875
  }