@kitn.ai/ui 0.20.1 → 0.21.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 (500) hide show
  1. package/README.md +44 -45
  2. package/dist/components/artifact-card.d.ts +51 -0
  3. package/dist/components/artifact.d.ts +1 -1
  4. package/dist/components/attachments.d.ts +2 -2
  5. package/dist/components/audio-visualizer/index.d.ts +3 -3
  6. package/dist/components/audio-visualizer/labs/lab-choreography.d.ts +59 -0
  7. package/dist/components/audio-visualizer/labs/lab-shaders.d.ts +22 -0
  8. package/dist/components/audio-visualizer/labs/lab-visualizer.d.ts +18 -0
  9. package/dist/components/audio-visualizer/variant-aurora.d.ts +2 -2
  10. package/dist/components/audio-visualizer/variant-bar.d.ts +2 -2
  11. package/dist/components/audio-visualizer/variant-custom.d.ts +2 -2
  12. package/dist/components/audio-visualizer/variant-grid.d.ts +1 -1
  13. package/dist/components/audio-visualizer/variant-radial.d.ts +1 -1
  14. package/dist/components/audio-visualizer/variant-wave.d.ts +1 -1
  15. package/dist/components/card-fallback.d.ts +12 -2
  16. package/dist/components/card-renderer.d.ts +63 -2
  17. package/dist/components/chat-container.d.ts +3 -0
  18. package/dist/components/chat-scope-picker.d.ts +2 -2
  19. package/dist/components/chat-thread.d.ts +68 -18
  20. package/dist/components/choice-card.d.ts +3 -28
  21. package/dist/components/composer-dom.d.ts +1 -1
  22. package/dist/components/composer-highlight.d.ts +1 -1
  23. package/dist/components/composer-history.d.ts +1 -1
  24. package/dist/components/composer.d.ts +1 -1
  25. package/dist/components/confirm-card.d.ts +3 -18
  26. package/dist/components/context.d.ts +8 -4
  27. package/dist/components/conversation-item.d.ts +1 -1
  28. package/dist/components/conversation-list.d.ts +4 -3
  29. package/dist/components/embed.d.ts +3 -3
  30. package/dist/components/file-tree.d.ts +11 -22
  31. package/dist/components/form-widgets.d.ts +1 -1
  32. package/dist/components/form.d.ts +3 -44
  33. package/dist/components/link-preview.d.ts +3 -3
  34. package/dist/components/loader.d.ts +30 -48
  35. package/dist/components/message-skills.d.ts +4 -0
  36. package/dist/components/message.d.ts +84 -21
  37. package/dist/components/model-switcher.d.ts +2 -2
  38. package/dist/components/prompt-input.d.ts +2 -2
  39. package/dist/components/response-compare-types.d.ts +11 -2
  40. package/dist/components/response-compare.d.ts +3 -3
  41. package/dist/components/source.d.ts +12 -3
  42. package/dist/components/tasks-card.d.ts +3 -31
  43. package/dist/components/thread.d.ts +17 -5
  44. package/dist/components/toast.d.ts +2 -2
  45. package/dist/components/tool-classify.d.ts +8 -0
  46. package/dist/components/tool-types.d.ts +29 -1
  47. package/dist/components/tool.d.ts +3 -3
  48. package/dist/components/use-card-resolution.d.ts +1 -1
  49. package/dist/create-tween-D3Y5qiij.js +338 -0
  50. package/dist/create-tween-DGKY1FDY.js +341 -0
  51. package/dist/create-tween-paho5Rh-.js +7 -0
  52. package/dist/custom-elements.json +1681 -454
  53. package/dist/elements/agent-card.js +1 -1
  54. package/dist/elements/artifact.js +1 -1
  55. package/dist/elements/attachments.js +1 -1
  56. package/dist/elements/audio-visualizer.js +1 -1
  57. package/dist/elements/avatar.js +1 -1
  58. package/dist/elements/badge.js +1 -1
  59. package/dist/elements/button.js +1 -1
  60. package/dist/elements/card.js +1 -1
  61. package/dist/elements/cards.js +1 -1
  62. package/dist/elements/chain-of-thought.js +1 -1
  63. package/dist/elements/chat-scope-picker.js +1 -1
  64. package/dist/elements/chat-types.d.ts +70 -10
  65. package/dist/elements/chat-workspace.js +1 -1
  66. package/dist/elements/chat.js +1 -1
  67. package/dist/elements/checkpoint.js +1 -1
  68. package/dist/elements/choice.js +1 -1
  69. package/dist/elements/chunks/{Icon-Tj58ES_d.js → Icon-C-2LvGDG.js} +1 -1
  70. package/dist/elements/chunks/{action-icons-ns1Fnedj.js → action-icons-CaYoImEk.js} +1 -1
  71. package/dist/elements/chunks/arrow-left-Bb46H7w9.js +1 -0
  72. package/dist/elements/chunks/artifact-BBIscOxJ.js +1 -0
  73. package/dist/elements/chunks/{attachments-mCB5F1Fq.js → attachments-BB56zoji.js} +1 -1
  74. package/dist/elements/chunks/audio-visualizer-BxOx4THz.js +1 -0
  75. package/dist/elements/chunks/{badge-B4Zuajl2.js → badge-SxLSZ19R.js} +1 -1
  76. package/dist/elements/chunks/{button-ZWNif3--.js → button-CmkUkz6c.js} +1 -1
  77. package/dist/elements/chunks/card-renderer-Db4ffkWv.js +1 -0
  78. package/dist/elements/chunks/card-tags-D8lZ-C_U.js +1 -0
  79. package/dist/elements/chunks/chat-thread-B3Ks-cKr.js +1 -0
  80. package/dist/elements/chunks/check-C8desc_h.js +1 -0
  81. package/dist/elements/chunks/chevron-down-DKtc2HNB.js +1 -0
  82. package/dist/elements/chunks/chevron-right-Dw4GPhwL.js +1 -0
  83. package/dist/elements/chunks/choice-card-Q9cYYDyM.js +1 -0
  84. package/dist/elements/chunks/circle-BeokBsvB.js +1 -0
  85. package/dist/elements/chunks/circle-check-wJSqt859.js +1 -0
  86. package/dist/elements/chunks/{circle-x-B7faJFlY.js → circle-x-D0MEfxOM.js} +1 -1
  87. package/dist/elements/chunks/code-block-C8VzAraE.js +1 -0
  88. package/dist/elements/chunks/{collapsible-DM1Ckd4e.js → collapsible-Cvj61obE.js} +1 -1
  89. package/dist/elements/chunks/{composer-BguS0QL_.js → composer-D86ztyL0.js} +2 -2
  90. package/dist/elements/chunks/confirm-card-BdyDAGLw.js +1 -0
  91. package/dist/elements/chunks/context-WHDl-xSx.js +1 -0
  92. package/dist/elements/chunks/conversation-list-CdR14_Y4.js +1 -0
  93. package/dist/elements/chunks/create-tween-C_A_B638.js +7 -0
  94. package/dist/elements/chunks/{default-input-Cqqilg9t.js → default-input-CSZqUM81.js} +1 -1
  95. package/dist/elements/chunks/define-BzPnNsXg.js +1 -0
  96. package/dist/elements/chunks/{disclosure-CIZ5c8nO.js → disclosure-DVKsoc1F.js} +1 -1
  97. package/dist/elements/chunks/{download-Dsbg3ste.js → download-BjA54IMJ.js} +1 -1
  98. package/dist/elements/chunks/{dropdown-BDd1-Zgi.js → dropdown-BjVVHWXH.js} +1 -1
  99. package/dist/elements/chunks/{ellipsis-Dw6qrss-.js → ellipsis-BNedmqfi.js} +1 -1
  100. package/dist/elements/chunks/embed-DQsl4XEq.js +1 -0
  101. package/dist/elements/chunks/{external-link-Vt74zAoL.js → external-link-Di-dw2CU.js} +1 -1
  102. package/dist/elements/chunks/{file-text-CZrZF6_v.js → file-text-B3sAODCV.js} +1 -1
  103. package/dist/elements/chunks/{file-tree-DF4okKyo.js → file-tree-Dgto-bMn.js} +1 -1
  104. package/dist/elements/chunks/{folder-glP5rha4.js → folder-D6rMadFV.js} +1 -1
  105. package/dist/elements/chunks/form-CILxvhQ7.js +1 -0
  106. package/dist/elements/chunks/hover-card-BtiF4XiU.js +1 -0
  107. package/dist/elements/chunks/{icon-BLb8beoi.js → icon-DKkmze3y.js} +1 -1
  108. package/dist/elements/chunks/{info-CIsv92JK.js → info-CWRjZkuy.js} +1 -1
  109. package/dist/elements/chunks/{input-Dds1kFyt.js → input--QJBK6BA.js} +1 -1
  110. package/dist/elements/chunks/{kbd-De_xbgi9.js → kbd-C3zuKh8R.js} +1 -1
  111. package/dist/elements/chunks/{link-i4r_k7z4.js → link-BL5JA7Q0.js} +1 -1
  112. package/dist/elements/chunks/link-preview-CU37bbXh.js +1 -0
  113. package/dist/elements/chunks/{loader-BmQH4s3V.js → loader-XmpyxyRH.js} +1 -1
  114. package/dist/elements/chunks/{markdown-Zi21WhUz.js → markdown-3Gv5UZ_o.js} +1 -1
  115. package/dist/elements/chunks/message-CnBA2OUt.js +1 -0
  116. package/dist/elements/chunks/message-X5NZbq-W.js +1 -0
  117. package/dist/elements/chunks/message-square-CnpAm_P0.js +1 -0
  118. package/dist/elements/chunks/{minimize-2--ifeCGrl.js → minimize-2-DwyrUTcM.js} +1 -1
  119. package/dist/elements/chunks/{model-switcher-B94YAKsM.js → model-switcher-CclaJEHt.js} +1 -1
  120. package/dist/elements/chunks/{overlay-kD8dwRv_.js → overlay-Cepd-KcS.js} +1 -1
  121. package/dist/elements/chunks/{paperclip-q21dYOSK.js → paperclip-CdwKjrlu.js} +1 -1
  122. package/dist/elements/chunks/{progress-bar-BrAIIaaJ.js → progress-bar-DMVXBD3b.js} +1 -1
  123. package/dist/elements/chunks/{prompt-suggestion-Bjn2K-fR.js → prompt-suggestion-Di_WZE_5.js} +1 -1
  124. package/dist/elements/chunks/reasoning-D0jMch5u.js +1 -0
  125. package/dist/elements/chunks/{resizable-Dp4JExql.js → resizable-1znbL1Gv.js} +1 -1
  126. package/dist/elements/chunks/{rotate-cw-CFWWkpj2.js → rotate-cw-DVhhgx8n.js} +1 -1
  127. package/dist/elements/chunks/{scroll-area-Bb0kHH1j.js → scroll-area-Bs4bFS1P.js} +1 -1
  128. package/dist/elements/chunks/scroll-button-Bet5NLc4.js +1 -0
  129. package/dist/elements/chunks/{separator-9kRgr1X9.js → separator-C5Gh8qGC.js} +1 -1
  130. package/dist/elements/chunks/{settings-B8lmec4D.js → settings-5vmEFg0K.js} +1 -1
  131. package/dist/elements/chunks/{settings-group-I0hEuXiN.js → settings-group-BWLB38kz.js} +1 -1
  132. package/dist/elements/chunks/{share-C3lTiYGt.js → share-BZ3G_DaB.js} +1 -1
  133. package/dist/elements/chunks/skeleton-DafPJQTp.js +1 -0
  134. package/dist/elements/chunks/slots-CIw9RlAe.js +1 -0
  135. package/dist/elements/chunks/source-D_qj_6uJ.js +1 -0
  136. package/dist/elements/chunks/{star-CSJtGxgv.js → star-Cuv7j2IE.js} +1 -1
  137. package/dist/elements/chunks/{store-CHyW95TP.js → store-C1StPHfW.js} +1 -1
  138. package/dist/elements/chunks/tasks-card-EyoBZfpA.js +1 -0
  139. package/dist/elements/chunks/{text-shimmer-Cn9TmNpI.js → text-shimmer-D9gRSh34.js} +1 -1
  140. package/dist/elements/chunks/textarea-DuhtHfcm.js +1 -0
  141. package/dist/elements/chunks/{thumbs-up-PNVVThEF.js → thumbs-up-B9hwv43w.js} +1 -1
  142. package/dist/elements/chunks/{toast-store-DKbQn3Wn.js → toast-store-Bm3DUEDe.js} +1 -1
  143. package/dist/elements/chunks/{tool-DjTRpIpl.js → tool-CDtW7L0z.js} +1 -1
  144. package/dist/elements/chunks/tooltip-eB226mGK.js +1 -0
  145. package/dist/elements/chunks/{triangle-alert-DsHTHCPm.js → triangle-alert-C1SNzTqK.js} +1 -1
  146. package/dist/elements/chunks/use-card-resolution-YZh2MvI5.js +1 -0
  147. package/dist/elements/chunks/{variant-aurora-Dc4nQUia.js → variant-aurora-Cj1F7D0l.js} +2 -2
  148. package/dist/elements/chunks/{variant-custom-y_3kVQhS.js → variant-custom-T9gpt7QE.js} +1 -1
  149. package/dist/elements/chunks/{variant-wave-D5OR1-9Z.js → variant-wave-CxU9z-TE.js} +2 -2
  150. package/dist/elements/chunks/{video-B7vmenoC.js → video-CK4R7Rus.js} +1 -1
  151. package/dist/elements/chunks/x-D1qx0aLd.js +1 -0
  152. package/dist/elements/coachmark.js +1 -1
  153. package/dist/elements/code-block.js +1 -1
  154. package/dist/elements/command.js +1 -1
  155. package/dist/elements/compare.js +1 -1
  156. package/dist/elements/composer.js +1 -1
  157. package/dist/elements/confirm-card.js +1 -1
  158. package/dist/elements/context-meter.js +1 -1
  159. package/dist/elements/conversation-list.js +1 -1
  160. package/dist/elements/default-input.d.ts +7 -7
  161. package/dist/elements/define.d.ts +1 -0
  162. package/dist/elements/dialog.js +1 -1
  163. package/dist/elements/disclosure.d.ts +1 -1
  164. package/dist/elements/editable-label.js +1 -1
  165. package/dist/elements/element-data-types.d.ts +107 -0
  166. package/dist/elements/embed.js +1 -1
  167. package/dist/elements/empty.js +1 -1
  168. package/dist/elements/feedback-bar.js +1 -1
  169. package/dist/elements/file-tree.js +1 -1
  170. package/dist/elements/file-upload.js +1 -1
  171. package/dist/elements/form.js +1 -1
  172. package/dist/elements/hover-card.js +1 -1
  173. package/dist/elements/icon.js +1 -1
  174. package/dist/elements/image.js +1 -1
  175. package/dist/elements/input.js +1 -1
  176. package/dist/elements/kbd.js +1 -1
  177. package/dist/elements/link-preview.js +1 -1
  178. package/dist/elements/loader.js +1 -1
  179. package/dist/elements/markdown.js +1 -1
  180. package/dist/elements/menu.js +1 -1
  181. package/dist/elements/message-skills.js +1 -1
  182. package/dist/elements/message.js +1 -1
  183. package/dist/elements/model-switcher.js +1 -1
  184. package/dist/elements/nav.js +1 -1
  185. package/dist/elements/notice.js +1 -1
  186. package/dist/elements/pane-group.js +1 -1
  187. package/dist/elements/pane.js +1 -1
  188. package/dist/elements/popover.js +1 -1
  189. package/dist/elements/progress-bar.js +1 -1
  190. package/dist/elements/prompt-dock.js +1 -1
  191. package/dist/elements/prompt-input.js +1 -1
  192. package/dist/elements/prompt-suggestions.js +1 -1
  193. package/dist/elements/reasoning.js +1 -1
  194. package/dist/elements/register.d.ts +8 -6
  195. package/dist/elements/remote.js +1 -1
  196. package/dist/elements/resizable.js +1 -1
  197. package/dist/elements/response-stream.js +2 -2
  198. package/dist/elements/screen.js +1 -1
  199. package/dist/elements/scroll-area.js +1 -1
  200. package/dist/elements/scroll-button.js +1 -1
  201. package/dist/elements/search.js +1 -1
  202. package/dist/elements/segmented.js +1 -1
  203. package/dist/elements/separator.js +1 -1
  204. package/dist/elements/setting-item.js +1 -1
  205. package/dist/elements/settings-group.js +1 -1
  206. package/dist/elements/skeleton.js +1 -1
  207. package/dist/elements/slots.d.ts +16 -0
  208. package/dist/elements/source.js +1 -1
  209. package/dist/elements/status.js +1 -1
  210. package/dist/elements/switch.js +1 -1
  211. package/dist/elements/tabs.js +1 -1
  212. package/dist/elements/tasks.js +1 -1
  213. package/dist/elements/text-shimmer.js +1 -1
  214. package/dist/elements/thinking-bar.js +1 -1
  215. package/dist/elements/thread.js +1 -1
  216. package/dist/elements/toast.js +1 -1
  217. package/dist/elements/tool.js +1 -1
  218. package/dist/elements/tooltip.js +1 -1
  219. package/dist/elements/validate-messages.d.ts +25 -0
  220. package/dist/elements/voice-input.js +1 -1
  221. package/dist/elements/voice-output.js +1 -1
  222. package/dist/elements.d.ts +2725 -214
  223. package/dist/index.d.ts +163 -125
  224. package/dist/index.js +6336 -5802
  225. package/dist/index.server.d.ts +5 -0
  226. package/dist/index.server.js +5446 -4937
  227. package/dist/kai-provider.es.d.ts +5 -0
  228. package/dist/kai-provider.es.js +79 -77
  229. package/dist/kai.es.d.ts +5 -0
  230. package/dist/kai.es.js +1 -1
  231. package/dist/llms/llms-full.txt +762 -148
  232. package/dist/llms/llms.txt +57 -5
  233. package/dist/mcp.es.js +4010 -770
  234. package/dist/primitives/card-component-types.d.ts +11 -0
  235. package/dist/primitives/card-data-types.d.ts +196 -0
  236. package/dist/primitives/card-host.d.ts +1 -1
  237. package/dist/primitives/card-recovery.d.ts +3 -3
  238. package/dist/primitives/card-registry.d.ts +4 -14
  239. package/dist/primitives/card-resolution.d.ts +1 -1
  240. package/dist/primitives/card-routing.d.ts +1 -1
  241. package/dist/primitives/card-tags.d.ts +11 -0
  242. package/dist/primitives/card-validate-cards.d.ts +57 -0
  243. package/dist/primitives/card-validate-generator.testlib.d.ts +20 -0
  244. package/dist/primitives/card-validate-schemas.d.ts +17 -0
  245. package/dist/primitives/card-validate.d.ts +24 -0
  246. package/dist/primitives/create-kai-chat.d.ts +3 -3
  247. package/dist/primitives/embed-providers.d.ts +1 -1
  248. package/dist/primitives/link-preview.d.ts +1 -1
  249. package/dist/primitives/message-feedback.d.ts +2 -2
  250. package/dist/primitives/toast-store.d.ts +1 -1
  251. package/dist/react/index.d.ts +717 -299
  252. package/dist/react/use-kai-chat.d.ts +8 -4
  253. package/dist/react.d.ts +5 -0
  254. package/dist/react.js +417 -316
  255. package/dist/register-impl-bzrZ44ft.js +145 -0
  256. package/dist/remote/host-embed.d.ts +1 -1
  257. package/dist/remote/index.d.ts +2 -2
  258. package/dist/remote/provider-runtime.d.ts +2 -2
  259. package/dist/remote/provider.d.ts +2 -2
  260. package/dist/remote/validate.d.ts +1 -1
  261. package/dist/remote/wire.d.ts +1 -1
  262. package/dist/schemas/artifact.schema.json +92 -0
  263. package/dist/schemas/embed.schema.json +0 -2
  264. package/dist/schemas/from-tool-call.d.ts +48 -0
  265. package/dist/schemas/index.d.ts +48 -0
  266. package/dist/schemas/link.schema.json +0 -2
  267. package/dist/schemas/provider-subsets.d.ts +136 -0
  268. package/dist/schemas/registry.d.ts +140 -0
  269. package/dist/schemas/tool-defs.d.ts +121 -0
  270. package/dist/schemas.d.ts +5 -0
  271. package/dist/schemas.js +717 -0
  272. package/dist/solid-BCJUQqwS.js +22750 -0
  273. package/dist/solid-BdENBcEq.js +20108 -0
  274. package/dist/solid.d.ts +66 -0
  275. package/dist/solid.js +261 -0
  276. package/dist/solid.server.d.ts +5 -0
  277. package/dist/solid.server.js +261 -0
  278. package/dist/state/index.d.ts +14 -4
  279. package/dist/state/messages.d.ts +8 -3
  280. package/dist/state/mock.d.ts +46 -0
  281. package/dist/state/parts.d.ts +85 -0
  282. package/dist/state/stream.d.ts +15 -9
  283. package/dist/state.d.ts +5 -0
  284. package/dist/state.js +253 -84
  285. package/dist/ui/action-icons.d.ts +1 -1
  286. package/dist/ui/collapsible.d.ts +11 -6
  287. package/dist/ui/dropdown.d.ts +47 -42
  288. package/dist/ui/pane-group.d.ts +1 -1
  289. package/dist/variant-aurora-1wMcXRUS.js +381 -0
  290. package/dist/variant-aurora-BKHHiOgL.js +391 -0
  291. package/dist/{variant-aurora-DVtGqVH6.js → variant-aurora-DOb_o4pC.js} +1 -1
  292. package/dist/{variant-custom-Dif-IV4u.js → variant-custom-CJGB0Kbw.js} +1 -1
  293. package/dist/variant-custom-Co0CkXJF.js +200 -0
  294. package/dist/variant-custom-DWSSgmd2.js +170 -0
  295. package/dist/variant-wave-C3-45cL6.js +218 -0
  296. package/dist/{variant-wave-DbfNdvSi.js → variant-wave-CEODq-9q.js} +1 -1
  297. package/dist/variant-wave-jdXBnCUZ.js +208 -0
  298. package/dist/wire/chunk.d.ts +171 -0
  299. package/dist/wire/consume.d.ts +26 -0
  300. package/dist/wire/encode.d.ts +148 -0
  301. package/dist/wire/formats/anthropic.d.ts +2 -0
  302. package/dist/wire/formats/openai.d.ts +5 -0
  303. package/dist/wire/index.d.ts +14 -0
  304. package/dist/wire/read.d.ts +26 -0
  305. package/dist/wire/sink-helpers.d.ts +21 -0
  306. package/dist/wire/sse.d.ts +33 -0
  307. package/dist/wire.d.ts +5 -53
  308. package/dist/wire.js +898 -0
  309. package/frameworks/react/index.tsx +183 -154
  310. package/frameworks/react/runtime.tsx +21 -1
  311. package/frameworks/react/use-kai-chat.tsx +11 -1
  312. package/llms-full.txt +762 -148
  313. package/llms.txt +57 -5
  314. package/package.json +61 -8
  315. package/src/agent-tooling/archetypes.ts +96 -0
  316. package/src/agent-tooling/integrations/anthropic.ts +412 -0
  317. package/src/agent-tooling/integrations/cloudflare.ts +136 -52
  318. package/src/agent-tooling/integrations/langgraph.ts +67 -13
  319. package/src/agent-tooling/integrations/mastra.ts +120 -12
  320. package/src/agent-tooling/integrations/mock.ts +43 -8
  321. package/src/agent-tooling/integrations/ollama.ts +61 -24
  322. package/src/agent-tooling/integrations/openai.ts +87 -0
  323. package/src/agent-tooling/integrations/openrouter.ts +56 -8
  324. package/src/agent-tooling/integrations/pi.ts +79 -23
  325. package/src/agent-tooling/integrations/pydantic-ai.ts +24 -2
  326. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +84 -13
  327. package/src/agent-tooling/mcp/manifest.ts +206 -25
  328. package/src/agent-tooling/mcp/tools/debug.ts +13 -7
  329. package/src/agent-tooling/mcp/tools/reference.ts +285 -6
  330. package/src/agent-tooling/mcp/tools/scaffold.ts +3345 -675
  331. package/src/agent-tooling/registry.ts +17 -0
  332. package/src/agent-tooling/types.ts +229 -1
  333. package/src/components/artifact-card.tsx +120 -0
  334. package/src/components/audio-visualizer/index.tsx +9 -0
  335. package/src/components/audio-visualizer/labs/lab-choreography.ts +187 -0
  336. package/src/components/audio-visualizer/labs/lab-shaders.ts +363 -0
  337. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +102 -0
  338. package/src/components/audio-visualizer/shader-canvas.tsx +31 -1
  339. package/src/components/card-fallback.tsx +42 -10
  340. package/src/components/card-renderer.tsx +146 -9
  341. package/src/components/chat-container.tsx +4 -0
  342. package/src/components/chat-thread.tsx +118 -51
  343. package/src/components/choice-card.tsx +17 -29
  344. package/src/components/composer.tsx +12 -2
  345. package/src/components/confirm-card.tsx +24 -20
  346. package/src/components/context.tsx +12 -4
  347. package/src/components/conversation-list.tsx +18 -2
  348. package/src/components/file-tree.tsx +11 -22
  349. package/src/components/file-upload.tsx +14 -8
  350. package/src/components/form.tsx +14 -47
  351. package/src/components/loader.tsx +39 -12
  352. package/src/components/message-skills.tsx +4 -0
  353. package/src/components/message.tsx +294 -46
  354. package/src/components/reasoning.tsx +92 -5
  355. package/src/components/response-compare-types.ts +25 -0
  356. package/src/components/response-compare.tsx +4 -9
  357. package/src/components/source.tsx +50 -24
  358. package/src/components/tasks-card.tsx +10 -33
  359. package/src/components/thread.tsx +84 -42
  360. package/src/components/toast.tsx +11 -5
  361. package/src/components/tool-classify.ts +26 -0
  362. package/src/components/tool-types.ts +31 -1
  363. package/src/elements/agent-card.tsx +11 -11
  364. package/src/elements/artifact.tsx +15 -7
  365. package/src/elements/attachments.tsx +6 -4
  366. package/src/elements/avatar.tsx +1 -1
  367. package/src/elements/button.tsx +3 -3
  368. package/src/elements/card.tsx +2 -2
  369. package/src/elements/cards.tsx +109 -14
  370. package/src/elements/chain-of-thought.tsx +14 -10
  371. package/src/elements/chat-scope-picker.tsx +9 -7
  372. package/src/elements/chat-types.ts +59 -6
  373. package/src/elements/chat-workspace.tsx +50 -9
  374. package/src/elements/chat.tsx +64 -3
  375. package/src/elements/choice.tsx +8 -8
  376. package/src/elements/coachmark.tsx +1 -1
  377. package/src/elements/command.tsx +8 -23
  378. package/src/elements/compare.tsx +7 -6
  379. package/src/elements/compiled.css +1 -1
  380. package/src/elements/composer.tsx +8 -8
  381. package/src/elements/confirm-card.tsx +9 -9
  382. package/src/elements/context-meter.tsx +4 -18
  383. package/src/elements/conversation-list.tsx +14 -9
  384. package/src/elements/default-input.tsx +3 -3
  385. package/src/elements/define.tsx +178 -43
  386. package/src/elements/editable-label.tsx +17 -2
  387. package/src/elements/element-data-types.ts +112 -0
  388. package/src/elements/element-meta.json +1596 -304
  389. package/src/elements/element-types.d.ts +2636 -211
  390. package/src/elements/feedback-bar.tsx +1 -1
  391. package/src/elements/file-tree.tsx +1 -1
  392. package/src/elements/file-upload.tsx +1 -1
  393. package/src/elements/form.tsx +14 -6
  394. package/src/elements/input.tsx +1 -1
  395. package/src/elements/kbd.tsx +1 -1
  396. package/src/elements/menu.tsx +10 -29
  397. package/src/elements/message-skills.tsx +7 -9
  398. package/src/elements/message.tsx +200 -32
  399. package/src/elements/model-switcher.tsx +5 -3
  400. package/src/elements/pane.tsx +1 -1
  401. package/src/elements/prompt-dock.tsx +8 -8
  402. package/src/elements/prompt-input.tsx +10 -10
  403. package/src/elements/prompt-suggestions.tsx +7 -4
  404. package/src/elements/reasoning.tsx +1 -1
  405. package/src/elements/register.ts +9 -0
  406. package/src/elements/resizable.globals.d.ts +36 -0
  407. package/src/elements/resizable.tsx +24 -13
  408. package/src/elements/response-stream.tsx +1 -1
  409. package/src/elements/scroll-button.tsx +1 -1
  410. package/src/elements/search.tsx +6 -1
  411. package/src/elements/segmented.tsx +5 -11
  412. package/src/elements/separator.tsx +1 -1
  413. package/src/elements/slots.ts +57 -24
  414. package/src/elements/source.tsx +21 -22
  415. package/src/elements/switch.tsx +3 -3
  416. package/src/elements/tasks.tsx +5 -4
  417. package/src/elements/thread.tsx +36 -4
  418. package/src/elements/toast.tsx +3 -2
  419. package/src/elements/tool.tsx +1 -1
  420. package/src/elements/validate-messages.ts +76 -0
  421. package/src/elements/voice-input.tsx +7 -7
  422. package/src/elements/voice-output.tsx +4 -4
  423. package/src/index.ts +141 -6
  424. package/src/primitives/card-component-types.ts +63 -0
  425. package/src/primitives/card-data-types.ts +312 -0
  426. package/src/primitives/card-recovery.ts +13 -2
  427. package/src/primitives/card-registry.tsx +34 -23
  428. package/src/primitives/card-schemas/artifact.schema.json +92 -0
  429. package/src/primitives/card-schemas/embed.schema.json +0 -2
  430. package/src/primitives/card-schemas/link.schema.json +0 -2
  431. package/src/primitives/card-tags.ts +61 -0
  432. package/src/primitives/card-validate-cards.ts +255 -0
  433. package/src/primitives/card-validate-generator.testlib.ts +38 -0
  434. package/src/primitives/card-validate-schemas.ts +58 -0
  435. package/src/primitives/card-validate.ts +48 -20
  436. package/src/primitives/create-tween.ts +54 -2
  437. package/src/primitives/message-feedback.ts +3 -2
  438. package/src/primitives/use-audio-analysis.ts +20 -1
  439. package/src/primitives/use-sequencer.ts +20 -1
  440. package/src/schemas/from-tool-call.ts +151 -0
  441. package/src/schemas/index.ts +340 -0
  442. package/src/schemas/provider-subsets.ts +538 -0
  443. package/src/schemas/registry.ts +355 -0
  444. package/src/schemas/tool-defs.ts +492 -0
  445. package/src/solid.ts +150 -0
  446. package/src/state/index.ts +27 -1
  447. package/src/state/messages.ts +21 -4
  448. package/src/state/mock.ts +211 -0
  449. package/src/state/parts.ts +295 -0
  450. package/src/state/stream.ts +56 -58
  451. package/src/ui/collapsible.tsx +17 -5
  452. package/src/ui/dropdown.tsx +46 -12
  453. package/src/ui/overlay.tsx +10 -4
  454. package/src/wire/chunk.ts +201 -0
  455. package/src/wire/consume.ts +440 -0
  456. package/src/wire/encode.ts +474 -0
  457. package/src/wire/formats/anthropic.ts +267 -0
  458. package/src/wire/formats/openai.ts +187 -0
  459. package/src/wire/index.ts +52 -0
  460. package/src/wire/read.ts +152 -0
  461. package/src/wire/sink-helpers.ts +50 -0
  462. package/src/wire/sse.ts +140 -0
  463. package/dist/create-tween-hvpmSuwW.js +0 -7
  464. package/dist/elements/chunks/arrow-left-DQocUFvy.js +0 -1
  465. package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +0 -1
  466. package/dist/elements/chunks/card-BkHbp4BA.js +0 -1
  467. package/dist/elements/chunks/chat-thread-CkRN6pZ7.js +0 -1
  468. package/dist/elements/chunks/check-B9-gn6SS.js +0 -1
  469. package/dist/elements/chunks/chevron-down-BNsxc2hk.js +0 -1
  470. package/dist/elements/chunks/chevron-right-Hv00StBO.js +0 -1
  471. package/dist/elements/chunks/circle-0e3KJTDr.js +0 -1
  472. package/dist/elements/chunks/circle-check-BNAS0JEy.js +0 -1
  473. package/dist/elements/chunks/code-block-BFUHn6Va.js +0 -1
  474. package/dist/elements/chunks/context-Cb7k4F-v.js +0 -1
  475. package/dist/elements/chunks/conversation-list-CvoAkWhN.js +0 -1
  476. package/dist/elements/chunks/create-tween-oVvAIG8r.js +0 -7
  477. package/dist/elements/chunks/define-D1din7Ld.js +0 -1
  478. package/dist/elements/chunks/hover-card-Cmm6Q53m.js +0 -1
  479. package/dist/elements/chunks/message-BqyXDN3-.js +0 -1
  480. package/dist/elements/chunks/message-feedback-Djr3z6Yb.js +0 -1
  481. package/dist/elements/chunks/message-square-vFAgbDaX.js +0 -1
  482. package/dist/elements/chunks/reasoning-DTpCGtnY.js +0 -1
  483. package/dist/elements/chunks/scroll-button-B0cH5fXf.js +0 -1
  484. package/dist/elements/chunks/skeleton-DSXW5Yya.js +0 -1
  485. package/dist/elements/chunks/slots--V19HwUb.js +0 -1
  486. package/dist/elements/chunks/textarea-CUwqAX0G.js +0 -1
  487. package/dist/elements/chunks/tooltip-CgBZCVKp.js +0 -1
  488. package/dist/elements/chunks/use-card-resolution-BSu_XHjH.js +0 -1
  489. package/dist/elements/chunks/x-GRUeeQFT.js +0 -1
  490. package/dist/host-embed.d.ts +0 -33
  491. package/dist/kai-provider.d.ts +0 -2
  492. package/dist/origin.d.ts +0 -5
  493. package/dist/provider-runtime.d.ts +0 -27
  494. package/dist/register-impl-DQyejdfb.js +0 -145
  495. package/dist/validate.d.ts +0 -4
  496. package/dist/version.d.ts +0 -4
  497. package/src/components/component-meta.json +0 -4550
  498. package/src/elements/card-media.jpg +0 -0
  499. package/src/elements/resizable.d.ts +0 -27
  500. package/src/elements/video-poster.jpg +0 -0
@@ -1,4 +1,6 @@
1
1
  import type { Integration, Archetype } from './types';
2
+ import openai from './integrations/openai';
3
+ import anthropic from './integrations/anthropic';
2
4
  import openrouter from './integrations/openrouter';
3
5
  import vercelAiSdk from './integrations/vercel-ai-sdk';
4
6
  import langgraph from './integrations/langgraph';
@@ -10,7 +12,22 @@ import pydanticAi from './integrations/pydantic-ai';
10
12
  import mock from './integrations/mock';
11
13
  import { archetypes as _archetypes } from './archetypes';
12
14
 
15
+ // The surface axis for the scaffolder's gate, derived from the presets above.
16
+ // Re-exported here because `scripts/verify-scaffold-compiles.mjs` bundles this
17
+ // module for its axes and must not reach past the registry for one of them.
18
+ export {
19
+ BASE_COMPONENT,
20
+ listCapabilityGroups,
21
+ listSurfaceProbes,
22
+ type CapabilityGroup,
23
+ type SurfaceProbe,
24
+ } from './archetypes';
25
+
26
+ // Order is the order a scaffolding agent reads them in. `openai` and `anthropic`
27
+ // lead because they are the two keys a developer is most likely to already hold.
13
28
  export const integrations: Integration[] = [
29
+ openai,
30
+ anthropic,
14
31
  openrouter,
15
32
  vercelAiSdk,
16
33
  langgraph,
@@ -3,9 +3,96 @@ import { z } from 'zod';
3
3
  export const Category = z.enum(['provider', 'gateway', 'framework', 'harness', 'mock']);
4
4
  export const Language = z.enum(['ts', 'python']);
5
5
  export const StreamFormat = z.enum(['openai-sse', 'ai-sdk', 'native']);
6
- export const Framework = z.enum(['html', 'react', 'next', 'vue', 'svelte', 'fastapi', 'express', 'worker', 'tanstack-start']);
6
+ /**
7
+ * The scaffold's target.
8
+ *
9
+ * Two of these are NOT web-component consumers, and the difference is load-bearing:
10
+ * - `angular` consumes `kai-*` like vue/svelte/html, but needs
11
+ * `CUSTOM_ELEMENTS_SCHEMA` and binds arrays/objects with `[prop]="…"`.
12
+ * - `solid` consumes the SolidJS components DIRECTLY from the `@kitn.ai/ui`
13
+ * root entry. The kit is authored in Solid, so routing a Solid consumer
14
+ * through the custom-element facade would ship the Solid runtime twice and
15
+ * cross a reactive-context boundary for nothing.
16
+ */
17
+ export const Framework = z.enum(['html', 'react', 'next', 'vue', 'svelte', 'angular', 'solid', 'fastapi', 'express', 'worker', 'tanstack-start']);
7
18
  export const Placement = z.enum(['side', 'full-page', 'docked-widget', 'inline']);
8
19
 
20
+ /**
21
+ * Whether this integration's SECRET may sit in the browser bundle.
22
+ *
23
+ * Read `'needs-proxy'` as "a server hop is mandatory" and `'frontend-safe'` as
24
+ * "the browser may call the upstream itself". This is the flag `create-kai`
25
+ * consults before it decides where a key goes, so getting it wrong in the
26
+ * permissive direction writes an API key into client code. There is deliberately
27
+ * no default and no boolean: the refinement below REJECTS an integration that
28
+ * declares neither, because "absent" must never read as "safe".
29
+ *
30
+ * `'needs-proxy'` covers two cases, and the second is easy to miss:
31
+ * 1. a secret. The route holds a key, so a static bundle cannot.
32
+ * 2. a server-only CAPABILITY. `pi` spawns a local process; no key is involved
33
+ * and a browser still cannot do it.
34
+ *
35
+ * `'frontend-safe'` is the narrow claim: nothing secret AND no server-only
36
+ * capability. Two integrations qualify, and both were read off their routes —
37
+ * `ollama` fetches `localhost:11434` with no auth header at all, and `mock`
38
+ * ships no route to reach.
39
+ *
40
+ * Do not infer this from the provider's name. A provider with a CORS-friendly
41
+ * public endpoint and one that requires a proxy look identical from outside; only
42
+ * the route says which it is. That is the same lesson `forwardsFromClient` and
43
+ * `clientToolFormat` were each added to record.
44
+ */
45
+ export const KeyExposure = z.enum(['frontend-safe', 'needs-proxy']);
46
+
47
+ /**
48
+ * The packages an app must install BEYOND `@kitn.ai/ui` to run this
49
+ * integration's route.
50
+ *
51
+ * Derived once, here, from the route's own import statements, so the CLI never
52
+ * has to re-parse route source to find them. Today this fact only exists as prose
53
+ * in `runNote`, which no installer can read.
54
+ *
55
+ * The rule, enforced by `registry.test.ts`: `npm` is exactly the set of
56
+ * bare-module specifiers imported by the TS route sources, normalised to package
57
+ * names (`@langchain/core/tools` counts as `@langchain/core`), minus `node:`
58
+ * builtins and minus `@kitn.ai/ui` itself, which every scaffold already depends
59
+ * on. `pip` is a superset of the python route's imports, because a Python app
60
+ * also needs its ASGI server (`uvicorn`), which nothing imports.
61
+ *
62
+ * Type-only packages (`@types/*`) are not listed: nothing imports them, so the
63
+ * rule cannot see them, and the frameworks that need them already carry them.
64
+ */
65
+ export const DepsSchema = z.object({
66
+ npm: z.array(z.string()).default([]),
67
+ pip: z.array(z.string()).default([]),
68
+ });
69
+
70
+ /**
71
+ * An env var name that holds a secret rather than an address.
72
+ *
73
+ * Anchored at the END, which is the whole precision of it: `CF_API_TOKEN` and
74
+ * `AI_GATEWAY_API_KEY` match, while `CF_ACCOUNT_ID` and `MASTRA_URL` do not.
75
+ * `MASTRA_URL` is the case that stops this being a proxy for "declares any env
76
+ * var at all" — a base URL is not a credential.
77
+ *
78
+ * This is a SAFETY NET over the declaration, never its source. Three integrations
79
+ * (`langgraph`, `vercel-ai-sdk`, `pydantic-ai`) hold a key their route source
80
+ * never names, because the SDK reads the env var itself; their `envVars` is what
81
+ * catches them here, and nothing but the author reading the route would have.
82
+ *
83
+ * Exported because the scaffolder names the secrets back at the developer in its
84
+ * run note ("OPENAI_API_KEY stays on the server"). That sentence and the
85
+ * refinement below have to agree about which env vars are secret, so there is one
86
+ * pattern rather than two free to drift apart.
87
+ */
88
+ export const SECRET_ENV_VAR = /(?:KEY|TOKEN|SECRET|PASSWORD)$/;
89
+
90
+ /**
91
+ * A credential written into a request from route source. The second alternative
92
+ * is Anthropic's spelling, which is not an `Authorization` header at all.
93
+ */
94
+ const AUTH_HEADER = /Authorization\s*:|['"]x-api-key['"]\s*:/i;
95
+
9
96
  export const IntegrationSchema = z.object({
10
97
  id: z.string(),
11
98
  title: z.string(),
@@ -14,9 +101,150 @@ export const IntegrationSchema = z.object({
14
101
  streamFormat: StreamFormat,
15
102
  envVars: z.array(z.string()).default([]),
16
103
  routeTemplates: z.record(z.string(), z.string()), // keyed by Framework value → code string
104
+ /**
105
+ * The backend as ONE web-standard handler, `(Request) => Response`, written as
106
+ * a complete `async function chatHandler(request: Request)` declaration.
107
+ *
108
+ * WHY THIS EXISTS. `routeTemplates` is keyed by framework, and in practice
109
+ * every TS integration only ever filled in `next`. Everything else fell
110
+ * through to it, so a svelte scaffold emitted a Next.js `export async function
111
+ * POST(req)` — which TYPECHECKS under SvelteKit and then throws
112
+ * `req.json is not a function` on the first submit, because SvelteKit calls
113
+ * `POST(event)`. vue and html got the same snippet with nowhere to put it.
114
+ *
115
+ * The handler BODY is portable; only the few lines that declare the route
116
+ * differ per framework. So integrations write the body once here and the
117
+ * scaffolder wraps it (see `WEB_ROUTE_ADAPTERS` in mcp/tools/scaffold.ts).
118
+ * `routeTemplates` stays for routes that genuinely cannot be expressed this
119
+ * way: a Worker using an `env` binding, an Express `(req, res)` bridge, a
120
+ * FastAPI service.
121
+ *
122
+ * An exact `routeTemplates[framework]` still wins over this.
123
+ */
124
+ webRoute: z.string().optional(),
17
125
  streamMapping: z.string(), // prose: how the stream maps to messages
18
126
  runNote: z.string(),
19
127
  docsSlug: z.string(),
128
+ /**
129
+ * The request-body fields this integration's ROUTE reads off the client and
130
+ * forwards upstream. Anything not listed is owned by the route or by the agent
131
+ * behind it.
132
+ *
133
+ * The scaffolder emits an editable const for a field only when it appears
134
+ * here, and that is the whole point: `model` used to be emitted whenever a
135
+ * route template contained the substring 'model', which is true of any
136
+ * template that so much as writes `model: 'llama3.2'`, so four integrations
137
+ * shipped an editable const their route threw away. The mirror-image bug is a
138
+ * `tools` array that never gets sent, which leaves kai-tool a panel no code
139
+ * path can populate.
140
+ *
141
+ * Empty by default, so a new integration emits nothing until its route really
142
+ * does forward the field.
143
+ */
144
+ forwardsFromClient: z.array(z.enum(['model', 'tools'])).default([]),
145
+ /**
146
+ * The tool-definition envelope this integration's ROUTE expects to find in the
147
+ * `tools` array the client POSTs. Required exactly when `forwardsFromClient`
148
+ * includes `'tools'`, and meaningless otherwise.
149
+ *
150
+ * WHY THIS IS DECLARED AND NOT DERIVED. It used to be looked up from
151
+ * `streamFormat`, and that is a category error: `streamFormat` describes the
152
+ * shape of the RESPONSE stream, while the tool envelope is a REQUEST concern.
153
+ * The two only appeared to agree because every integration that forwarded
154
+ * tools happened to be `openai-sse`. `anthropic` is where the conflation
155
+ * becomes visible — it is `streamFormat: 'native'`, which says nothing about
156
+ * request shape, and the old table mapped `native` to null.
157
+ *
158
+ * And keying on the integration's PROVIDER would be wrong too, which is the
159
+ * part worth reading the route before assuming: `anthropic`'s handler converts
160
+ * the array itself (`toAnthropicTools` reads `raw.function.name` /
161
+ * `.function.parameters`), so it wants `'openai'` here. Handing it Anthropic's
162
+ * own `{ name, input_schema }` shape would yield tools with a blank name. Only
163
+ * the route knows what it accepts, so only the integration can state it — the
164
+ * same reason `forwardsFromClient` lives here rather than being sniffed out of
165
+ * the route source.
166
+ *
167
+ * Optional in the type, mandatory in practice: the refinement below rejects an
168
+ * integration that forwards tools without one. There is deliberately no
169
+ * default — a default is how a tools array with no card in it ships silently.
170
+ */
171
+ clientToolFormat: z.enum(['openai', 'anthropic', 'jsonschema']).optional(),
172
+ /** See {@link DepsSchema}. Empty is a real answer: a fetch-only route needs nothing. */
173
+ deps: DepsSchema.default({ npm: [], pip: [] }),
174
+ /**
175
+ * See {@link KeyExposure}. Optional in the TYPE only so the refinement below
176
+ * owns the error message — Zod skips refinements when the base object already
177
+ * failed, so a plain required field would report "Invalid input" and this is
178
+ * the one field where the reader needs to be told what is at stake.
179
+ */
180
+ keyExposure: KeyExposure.optional(),
181
+ }).superRefine((integration, ctx) => {
182
+ // Enforced against the real catalog by `registry.test.ts`, which parses every
183
+ // integration through this schema. A new host that forwards tools therefore
184
+ // cannot reach the scaffolder undeclared: it fails at the catalog boundary,
185
+ // before any emit path has to decide what to do about it.
186
+ if (integration.forwardsFromClient.includes('tools') && integration.clientToolFormat === undefined) {
187
+ ctx.addIssue({
188
+ code: z.ZodIssueCode.custom,
189
+ path: ['clientToolFormat'],
190
+ message:
191
+ `integration '${integration.id}' forwards a 'tools' array but declares no clientToolFormat. ` +
192
+ `State the envelope its route expects: 'openai' ({ type: 'function', function: { parameters } }), ` +
193
+ `'anthropic' ({ name, input_schema }), or 'jsonschema' ({ name, description, schema }). ` +
194
+ `Read the route's own handler to decide — a route that CONVERTS the array server-side wants the ` +
195
+ `shape it converts FROM, not its own provider's.`,
196
+ });
197
+ }
198
+
199
+ // ---- keyExposure ----
200
+ //
201
+ // Two checks, and the split matters. The first refuses SILENCE. The second
202
+ // refuses a specific LIE, and only ever in the dangerous direction: it can
203
+ // turn a 'frontend-safe' claim into an error, never the reverse. Declaring
204
+ // 'needs-proxy' where a proxy was not strictly required costs a server hop;
205
+ // declaring 'frontend-safe' where it was required costs the key.
206
+
207
+ if (integration.keyExposure === undefined) {
208
+ ctx.addIssue({
209
+ code: z.ZodIssueCode.custom,
210
+ path: ['keyExposure'],
211
+ message:
212
+ `integration '${integration.id}' declares no keyExposure. State whether its SECRET may reach the ` +
213
+ `browser bundle: 'needs-proxy' (a key, or a server-only capability such as spawning a process, so ` +
214
+ `the CLI must keep it behind a server) or 'frontend-safe' (nothing secret and nothing server-only, ` +
215
+ `so the browser may call the upstream directly). Read the route to decide, not the provider's name: ` +
216
+ `a public CORS-friendly endpoint and one that requires a proxy are indistinguishable from outside. ` +
217
+ `There is no default on purpose — a missing flag read as "safe" is how an API key ships in client code.`,
218
+ });
219
+ }
220
+
221
+ if (integration.keyExposure === 'frontend-safe') {
222
+ const secrets = integration.envVars.filter((name) => SECRET_ENV_VAR.test(name));
223
+ if (secrets.length > 0) {
224
+ ctx.addIssue({
225
+ code: z.ZodIssueCode.custom,
226
+ path: ['keyExposure'],
227
+ message:
228
+ `integration '${integration.id}' claims keyExposure 'frontend-safe' but declares the secret env ` +
229
+ `var(s) ${secrets.join(', ')}. A frontend bundle is public, so that combination puts a key in ` +
230
+ `client code. Use 'needs-proxy'.`,
231
+ });
232
+ }
233
+
234
+ const routeSources = [
235
+ ...Object.values(integration.routeTemplates),
236
+ ...(integration.webRoute ? [integration.webRoute] : []),
237
+ ];
238
+ if (routeSources.some((code) => AUTH_HEADER.test(code))) {
239
+ ctx.addIssue({
240
+ code: z.ZodIssueCode.custom,
241
+ path: ['keyExposure'],
242
+ message:
243
+ `integration '${integration.id}' claims keyExposure 'frontend-safe' but its route sends an ` +
244
+ `authorization header, so it holds a credential a browser bundle must not. Use 'needs-proxy'.`,
245
+ });
246
+ }
247
+ }
20
248
  });
21
249
  export type Integration = z.infer<typeof IntegrationSchema>;
22
250
 
@@ -0,0 +1,120 @@
1
+ // src/components/artifact-card.tsx
2
+ // The `artifact` built-in card: chrome + sizing around <Artifact>, plus the
3
+ // bridge from its observation callbacks onto the frozen Card Contract.
4
+ import { createUniqueId, untrack, Show, type JSX } from 'solid-js';
5
+ import type { CardHost } from '../primitives/card-contract';
6
+ import { Artifact } from './artifact';
7
+
8
+ // `ArtifactCardData` is AUTHORED IN ../primitives/card-data-types.ts, along with
9
+ // `ArtifactCardFile` — the same declaration `FileTree`/`Artifact` use, which is
10
+ // why nothing here restates the file shape. See the note in confirm-card.tsx, or
11
+ // that file's header, for why the card payload types left a `.tsx` and why they
12
+ // are `type` aliases. Re-exported here unchanged.
13
+
14
+ import type { ArtifactCardData } from '../primitives/card-data-types';
15
+
16
+ export type {
17
+ ArtifactCardData,
18
+ ArtifactCardEnvelope,
19
+ ArtifactCardFile,
20
+ ArtifactCardTab,
21
+ } from '../primitives/card-data-types';
22
+
23
+ /** Height the artifact card falls back to. Tall enough that a framed page is
24
+ * actually legible in a thread, short enough to leave the conversation visible. */
25
+ export const DEFAULT_ARTIFACT_CARD_HEIGHT = '420px';
26
+
27
+ function resolveHeight(height: number | string | undefined): string {
28
+ if (typeof height === 'number') return `${height}px`;
29
+ if (typeof height === 'string' && height.trim() !== '') return height;
30
+ return DEFAULT_ARTIFACT_CARD_HEIGHT;
31
+ }
32
+
33
+ export interface ArtifactCardProps {
34
+ data: ArtifactCardData;
35
+ cardId: string;
36
+ heading?: string;
37
+ host?: CardHost;
38
+ }
39
+
40
+ /** Chrome + sizing around `<Artifact>` for the `artifact` card type.
41
+ *
42
+ * WHY A WRAPPER IS REQUIRED, not cosmetic. `<Artifact>`'s root is
43
+ * `flex h-full w-full flex-col` — it is built to FILL a container that already
44
+ * has a height (a resizable panel, a split view). A message thread gives its
45
+ * parts no height at all, so `h-full` resolves against an auto-height parent,
46
+ * the frame computes to ZERO, and the card renders as an invisible nothing.
47
+ * The explicit `height` here is what makes the card visible; `data.height`
48
+ * overrides it.
49
+ *
50
+ * `part`/`data-card-type` are stable handles. `CardRenderer` renders card
51
+ * components bare, and in the web-component path `cardComponentsFromTags` maps a
52
+ * non-overridden built-in straight to its Solid component — so there is no
53
+ * `<kai-artifact>` tag in the DOM to point at. This wrapper is the only stable
54
+ * thing to select, which is what lets a test count rendered artifacts inside
55
+ * `<kai-thread>`'s shadow root.
56
+ *
57
+ * `part="card"` matches the other chromed cards, which get it from `<Card>`;
58
+ * this one hand-rolls its chrome and so states it directly. The artifact-specific
59
+ * handle is `data-card-type`, NOT a second part token: every `::part` name has to
60
+ * be declared in `elements/slots.ts` (the drift guard in `slots.test.ts` enforces
61
+ * it), so adding an `artifact` part is a deliberate public-API decision to make
62
+ * there, not something to smuggle in from a component.
63
+ *
64
+ * `envelope.title` renders as a HEADING above the frame rather than being folded
65
+ * into `displayUrl`: the address field states where the preview is pointing, and
66
+ * overwriting it with a title would make it lie. A heading is also what the four
67
+ * other chromed cards (form/confirm/tasks/choice) already do with `title`.
68
+ *
69
+ * `tab`/`activeFile` are SEEDS, never re-asserted — see their notes on
70
+ * `ArtifactCardData`. A revised envelope must not undo what the user did.
71
+ *
72
+ * The three observation callbacks emit the contract's EXISTING `state` verb —
73
+ * the contract is frozen, and a new kind would force a CARD_CONTRACT_VERSION
74
+ * bump. Each patch key mirrors a `data` field name, so a host can merge the
75
+ * patch straight back into `envelope.data` and re-send it; `addCard` upserts on
76
+ * `envelope.id`, so that round-trip revises the card instead of duplicating it. */
77
+ export function ArtifactCard(props: ArtifactCardProps): JSX.Element {
78
+ const headingId = createUniqueId();
79
+ // Read ONCE, non-reactively: these seed the view and must not be re-asserted
80
+ // when a revision replaces the envelope. See ArtifactCardData.activeFile.
81
+ const seedTab = untrack(() => props.data.tab);
82
+ const seedActiveFile = untrack(() => props.data.activeFile);
83
+ const patch = (p: Record<string, unknown>) =>
84
+ props.host?.emit({ kind: 'state', cardId: props.cardId, patch: p });
85
+
86
+ return (
87
+ <div
88
+ part="card"
89
+ data-card-type="artifact"
90
+ data-card-id={props.cardId}
91
+ role="group"
92
+ aria-labelledby={props.heading ? headingId : undefined}
93
+ aria-label={props.heading ? undefined : 'Artifact'}
94
+ style={{ height: resolveHeight(props.data.height) }}
95
+ class="flex w-full flex-col overflow-hidden rounded-xl border border-border bg-card"
96
+ >
97
+ <Show when={props.heading}>
98
+ <h3
99
+ id={headingId}
100
+ class="shrink-0 truncate border-b border-border px-3 py-2 text-sm font-medium text-foreground"
101
+ >
102
+ {props.heading}
103
+ </h3>
104
+ </Show>
105
+ <div class="min-h-0 flex-1">
106
+ <Artifact
107
+ src={props.data.src}
108
+ files={props.data.files}
109
+ defaultTab={seedTab}
110
+ activeFile={seedActiveFile}
111
+ displayUrl={props.data.displayUrl}
112
+ iframeTitle={props.heading ? `${props.heading} preview` : 'Artifact preview'}
113
+ onNavigate={(url) => patch({ src: url })}
114
+ onTabChange={(tab) => patch({ tab })}
115
+ onFileSelect={(path) => patch({ activeFile: path })}
116
+ />
117
+ </div>
118
+ </div>
119
+ );
120
+ }
@@ -326,6 +326,15 @@ export function AudioVisualizer(props: AudioVisualizerProps): JSX.Element {
326
326
  void load()
327
327
  .then((m) => { if (!cancelled) setShader(() => m.default); })
328
328
  .catch((err) => {
329
+ // Same `cancelled` check as the `.then` above. The two handlers were
330
+ // asymmetric: a rejection arriving after this effect was disposed
331
+ // still warned, even though there is no longer a component to fall
332
+ // back to and nothing the message could usefully tell anyone. Worse,
333
+ // the warning surfaces against whatever is running by the time the
334
+ // rejection lands rather than against the mount that asked for the
335
+ // chunk, so it reads as a fault in unrelated code -- in a test run,
336
+ // in an unrelated test.
337
+ if (cancelled) return;
329
338
  console.warn(
330
339
  `<kai-audio-visualizer variant="${v}">: failed to load the shader chunk, falling back to bars.`,
331
340
  err,
@@ -0,0 +1,187 @@
1
+ import type { LabLook } from './lab-shaders';
2
+
3
+ /** The agent states the kit's visualizers respond to, plus manual free play. */
4
+ export type LabState = 'manual' | 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking';
5
+
6
+ export const LAB_STATES: LabState[] = ['manual', 'idle', 'connecting', 'listening', 'thinking', 'speaking'];
7
+
8
+ /** Every tunable the lab shaders read. Flat on purpose: story args map 1:1. */
9
+ export interface LabParams {
10
+ baseR: number; ampIdle: number; ampVoice: number; radVoice: number;
11
+ sigma: number; gain: number; f1: number; f2: number; s1: number; s2: number;
12
+ envSpd: number; sepSpd: number; whiteLo: number; whiteHi: number;
13
+ bloomMul: number; bloomGain: number; delta: number; off: number;
14
+ wWidth: number; wMin: number; fillGain: number; edgeGain: number;
15
+ flut: number; twistSpd: number; warpAmp: number; lens: number; spec: number;
16
+ tint: number; vSpeed: number; presence: number; gather: number;
17
+ core: number; neural: number; boltJag: number; boltWidth: number; boltRate: number;
18
+ }
19
+
20
+ const SHARED: LabParams = {
21
+ baseR: 0.33, ampIdle: 0.017, ampVoice: 0.043, radVoice: 0.24,
22
+ sigma: 0.022, gain: 0.42, f1: 6, f2: 10, s1: 0.55, s2: 0.85,
23
+ envSpd: 0.21, sepSpd: 0.38, whiteLo: 1.35, whiteHi: 2.3,
24
+ bloomMul: 2.6, bloomGain: 0.18, delta: 0.35, off: 0.024,
25
+ wWidth: 0.045, wMin: 0.006, fillGain: 0.38, edgeGain: 0.7,
26
+ flut: 0.01, twistSpd: 0.55, warpAmp: 0.75, lens: 0.85, spec: 0.35,
27
+ tint: 0.25, vSpeed: 2.2, presence: 1, gather: 0,
28
+ core: 0, neural: 0, boltJag: 0.5, boltWidth: 3, boltRate: 0.25,
29
+ };
30
+
31
+ /** Hand-tuned in the aurora playground; per-look starting points. */
32
+ export const LOOK_DEFAULTS: Record<LabLook, LabParams> = {
33
+ braid: { ...SHARED },
34
+ ribbon: {
35
+ ...SHARED,
36
+ baseR: 0.315, ampIdle: 0.012, ampVoice: 0.032, radVoice: 0.09,
37
+ sigma: 0.014, gain: 0.6, f1: 3, f2: 9, s1: 1.1, s2: 2.2,
38
+ envSpd: 0.5, whiteLo: 1.0, whiteHi: 2.4, bloomMul: 2.5, bloomGain: 0.15,
39
+ wWidth: 0.085, wMin: 0.009, fillGain: 0.85, edgeGain: 0.35, twistSpd: 1.9,
40
+ },
41
+ planet: {
42
+ ...SHARED,
43
+ radVoice: 0, gain: 1.0, fillGain: 0.75, edgeGain: 0.5,
44
+ f2: 12, s1: 1, s2: 1, twistSpd: 1.0, warpAmp: 0.9,
45
+ whiteLo: 1.2, whiteHi: 2.6,
46
+ },
47
+ orb: {
48
+ ...SHARED,
49
+ radVoice: 0, gain: 1.1, fillGain: 0.65, edgeGain: 0.45,
50
+ f2: 10, s1: 1, s2: 1, twistSpd: 1.2, warpAmp: 1.0,
51
+ lens: 0.8, spec: 0.3, vSpeed: 3.0,
52
+ },
53
+ };
54
+
55
+ const ORB_LOOKS: LabLook[] = ['planet', 'orb'];
56
+
57
+ /** Loudness loop standing in for a live voice while `speaking` (dB per third-second). */
58
+ const ENV_DB = [-60.9, -49.0, -46.7, -54.1, -50.0, -47.8, -49.3, -53.3, -53.5, -50.4,
59
+ -46.9, -53.0, -50.2, -52.5, -53.9, -50.6, -50.8, -49.2, -55.1, -48.7,
60
+ -48.4, -47.4, -49.6, -50.7, -49.0, -46.9, -50.8, -52.9, -52.2, -46.6,
61
+ -46.6, -46.2];
62
+
63
+ function envelopeAt(sec: number): number {
64
+ const x = (sec % 10.6) * 3;
65
+ const i = Math.max(0, Math.min(ENV_DB.length - 1, Math.floor(x)));
66
+ const j = Math.min(ENV_DB.length - 1, i + 1);
67
+ const f = x - i;
68
+ const db = ENV_DB[i] * (1 - f) + ENV_DB[j] * f;
69
+ return Math.max(0, Math.min(1, (db + 58) / 14));
70
+ }
71
+
72
+ interface Slow {
73
+ presence: number; gather: number; tintAdd: number; warpMul: number;
74
+ deltaAdd: number; f2Add: number; gainMul: number; neural: number;
75
+ }
76
+
77
+ export interface LabFrame {
78
+ t: number;
79
+ level: number;
80
+ values: LabParams;
81
+ }
82
+
83
+ /**
84
+ * The state choreography from the playground, per frame. Slow targets glide
85
+ * over seconds (presence slowest, so smoke visibly forms and dissipates);
86
+ * tempo runs on an accumulated warped clock, so state changes never jump the
87
+ * animation phase; the ember beats and the bolts fire in real time.
88
+ */
89
+ export function createChoreography(getLook: () => LabLook, getState: () => LabState, getParams: () => LabParams) {
90
+ let tAnim = 0;
91
+ let rateSm = 1;
92
+ let smooth = 0;
93
+ let elapsed = 0;
94
+ const slow: Slow = { presence: 1, gather: 0, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
95
+
96
+ const step = (dt: number): LabFrame => {
97
+ elapsed += dt;
98
+ const P = getParams();
99
+ const state = getState();
100
+ const orb = ORB_LOOKS.includes(getLook());
101
+ const base = orb ? 0.35 : 1.0;
102
+
103
+ const drive = envelopeAt(elapsed);
104
+ const k = drive > smooth ? 0.25 : 0.06;
105
+ smooth += (drive - smooth) * k;
106
+
107
+ const beat = Math.pow(0.5 + 0.5 * Math.sin((elapsed / 1.2) * Math.PI * 2), 3.0);
108
+ const flick = 0.5 + 0.5 * Math.sin((elapsed / 0.35) * Math.PI * 2);
109
+
110
+ let target: Slow;
111
+ let rate: number;
112
+ let level: number;
113
+ let core: number;
114
+ let gpulse = 0;
115
+ switch (state) {
116
+ case 'idle':
117
+ target = orb
118
+ ? { presence: 0.12, gather: -0.8, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 }
119
+ : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.8, neural: 0 };
120
+ rate = base; level = 0; core = orb ? 0.06 : 0;
121
+ break;
122
+ case 'connecting':
123
+ target = orb
124
+ ? { presence: 0.22, gather: -0.25, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.9, neural: 0 }
125
+ : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 };
126
+ rate = base * 1.4; level = 0.04; core = orb ? 0.18 + 0.55 * beat : 0;
127
+ if (!orb) gpulse = 0.2 * beat;
128
+ break;
129
+ case 'listening':
130
+ target = orb
131
+ ? { presence: 0.8, gather: 0.5, tintAdd: 0.05, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 }
132
+ : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
133
+ rate = base * 1.7; level = 0.2; core = orb ? 0.12 : 0;
134
+ break;
135
+ case 'thinking':
136
+ target = orb
137
+ ? { presence: 1, gather: 0.6, tintAdd: 0.5, warpMul: 1.3, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 1 }
138
+ : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0.5, f2Add: 3, gainMul: 1, neural: 0 };
139
+ rate = orb ? 2.2 : 2.5; level = 0.12 + 0.2 * flick; core = orb ? 0.05 : 0;
140
+ if (!orb) gpulse = 0.1 * flick;
141
+ break;
142
+ case 'speaking':
143
+ target = orb
144
+ ? { presence: 1, gather: 0, tintAdd: 0, warpMul: 1.25, deltaAdd: 0, f2Add: 0, gainMul: 1.05, neural: 0 }
145
+ : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
146
+ rate = base * 1.5 + 5.5 * smooth; level = Math.min(1, smooth * 1.35);
147
+ core = orb ? 0.08 + 0.6 * smooth : 0;
148
+ break;
149
+ default:
150
+ target = { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: P.neural };
151
+ rate = base + P.vSpeed * smooth; level = smooth; core = P.core;
152
+ }
153
+
154
+ const mixTo = (cur: number, tgt: number, tc: number): number =>
155
+ cur + (tgt - cur) * (1 - Math.exp(-dt / tc));
156
+ slow.presence = mixTo(slow.presence, target.presence, 1.4);
157
+ slow.gather = mixTo(slow.gather, target.gather, 1.0);
158
+ slow.tintAdd = mixTo(slow.tintAdd, target.tintAdd, 0.6);
159
+ slow.warpMul = mixTo(slow.warpMul, target.warpMul, 0.6);
160
+ slow.deltaAdd = mixTo(slow.deltaAdd, target.deltaAdd, 0.6);
161
+ slow.f2Add = mixTo(slow.f2Add, target.f2Add, 0.6);
162
+ slow.gainMul = mixTo(slow.gainMul, target.gainMul, 0.6);
163
+ slow.neural = mixTo(slow.neural, target.neural, 0.6);
164
+
165
+ rateSm += (rate - rateSm) * (1 - Math.exp(-dt / 0.4));
166
+ tAnim += dt * rateSm;
167
+
168
+ return {
169
+ t: tAnim,
170
+ level,
171
+ values: {
172
+ ...P,
173
+ presence: slow.presence,
174
+ gather: slow.gather,
175
+ core,
176
+ neural: slow.neural,
177
+ tint: Math.min(1, P.tint + slow.tintAdd),
178
+ warpAmp: P.warpAmp * slow.warpMul,
179
+ delta: P.delta + slow.deltaAdd,
180
+ f2: P.f2 + slow.f2Add,
181
+ gain: P.gain * slow.gainMul * (1 + gpulse),
182
+ },
183
+ };
184
+ };
185
+
186
+ return { step };
187
+ }