@kitn.ai/ui 0.28.0 → 0.30.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 (615) hide show
  1. package/README.md +11 -7
  2. package/dist/{Icon-DObhsRtm.js → Icon-BzBET3E-.js} +1 -1
  3. package/dist/{action-icons-CcgNN2oT.js → action-icons-DaW2pU6m.js} +1 -1
  4. package/dist/agent-tooling/construct/public.d.ts +15 -0
  5. package/dist/agent-tooling/construct/schema.d.ts +111 -0
  6. package/dist/arrow-down-D783iMJj.js +1 -0
  7. package/dist/arrow-left-0VLM5kyg.js +1 -0
  8. package/dist/artifact-DGjzHYUT.js +1 -0
  9. package/dist/{attachments-Qr4kg-2b.js → attachments-YvXHlg88.js} +1 -1
  10. package/dist/{audio-visualizer-DToYdfSc.js → audio-visualizer-9lz5IHsL.js} +1 -1
  11. package/dist/{badge-CdEu_jn2.js → badge-Dh_vp8A5.js} +1 -1
  12. package/dist/{bell-DQAAOpDz.js → bell-CT7_WUwS.js} +1 -1
  13. package/dist/{button-DkuOnGLy.js → button-C_3te6fm.js} +1 -1
  14. package/dist/{card-renderer-Jx70m6_l.js → card-renderer-DZVaGH2e.js} +1 -1
  15. package/dist/check-CiEOVnEN.js +1 -0
  16. package/dist/{checkbox-D7iRB3nL.js → checkbox-Bu2T2e0U.js} +1 -1
  17. package/dist/{checkbox-group-B2_rpoPM.js → checkbox-group-BiryEXPQ.js} +1 -1
  18. package/dist/chevron-down-CSobuZRG.js +1 -0
  19. package/dist/chevron-right-DR9ZAP-2.js +1 -0
  20. package/dist/{choice-card-m0BYqqOK.js → choice-card-CM6IjkmL.js} +1 -1
  21. package/dist/circle-BC66EYF7.js +1 -0
  22. package/dist/circle-check-BqmahW0O.js +1 -0
  23. package/dist/{circle-x-BPG0iPst.js → circle-x-Bk-dA5Wf.js} +1 -1
  24. package/dist/{code-block-ClMLKb7C.js → code-block-B26t-Q7q.js} +1 -1
  25. package/dist/{collapsible-B4DlWicL.js → collapsible-Bhc636Cf.js} +1 -1
  26. package/dist/components/builder-composer-triggers.d.ts +62 -0
  27. package/dist/components/builder-layout.d.ts +54 -0
  28. package/dist/components/builder-message-actions.d.ts +72 -0
  29. package/dist/components/builder-panel.d.ts +189 -0
  30. package/dist/components/builder-preview.d.ts +11 -0
  31. package/dist/components/builder-shell-controls.d.ts +69 -0
  32. package/dist/components/builder-skeleton.d.ts +58 -0
  33. package/dist/components/builder-start.d.ts +75 -0
  34. package/dist/components/builder-workspace-variants.d.ts +23 -0
  35. package/dist/components/captions.d.ts +66 -0
  36. package/dist/{composer-sQ0HcvyG.js → composer-DMI85B6j.js} +1 -1
  37. package/dist/{confirm-card-rQWDQsnC.js → confirm-card-B0YIAwXp.js} +1 -1
  38. package/dist/construct-cli.es.js +3 -3
  39. package/dist/construct.d.ts +5 -0
  40. package/dist/construct.js +327 -0
  41. package/dist/{context-0kg4ZX1J.js → context-DWgfhqWp.js} +1 -1
  42. package/dist/controllable-BagRpyHv.js +1 -0
  43. package/dist/{conversation-item-BxwQLaFJ.js → conversation-item-BsOsVGmT.js} +1 -1
  44. package/dist/{conversation-list-BCfGN1JU.js → conversation-list-aX3Vtc7L.js} +1 -1
  45. package/dist/{copy-n9u9rqpi.js → copy-BmEwsNhJ.js} +1 -1
  46. package/dist/core-C8fzo39E.js +1 -12
  47. package/dist/{create-tween-uPkArjIG.js → create-tween-CNOAU3Fx.js} +1 -1
  48. package/dist/{create-tween-C-q-JCM-.js → create-tween-WfqiENls.js} +1 -1
  49. package/dist/{create-tween-CRrJXxBd.js → create-tween-wlFtW9Kh.js} +1 -1
  50. package/dist/{create-tween-DZ3RRDHD.js → create-tween-zt79ba32.js} +1 -1
  51. package/dist/{default-input-CaMrJkgH.js → default-input-DMV5Eaze.js} +1 -1
  52. package/dist/define-CI0y3eE4.js +1 -0
  53. package/dist/define.js +40 -40
  54. package/dist/define.server.js +45 -45
  55. package/dist/{disclosure-WUImBbDv.js → disclosure-NnACBxsC.js} +1 -1
  56. package/dist/{dropdown-wZVeJOMd.js → dropdown-DT7G0RGR.js} +1 -1
  57. package/dist/elements/agent-card.js +1 -1
  58. package/dist/elements/artifact.js +1 -1
  59. package/dist/elements/attachments.js +1 -1
  60. package/dist/elements/audio-visualizer.js +1 -1
  61. package/dist/elements/avatar.js +1 -1
  62. package/dist/elements/badge.js +1 -1
  63. package/dist/elements/button.js +1 -1
  64. package/dist/elements/card.js +1 -1
  65. package/dist/elements/cards.js +1 -1
  66. package/dist/elements/chain-of-thought.js +1 -1
  67. package/dist/elements/chat-scope-picker.js +1 -1
  68. package/dist/elements/chat-workspace.js +1 -1
  69. package/dist/elements/chat.js +1 -1
  70. package/dist/elements/checkbox-group.js +1 -1
  71. package/dist/elements/checkbox.js +1 -1
  72. package/dist/elements/checkpoint.js +1 -1
  73. package/dist/elements/choice.js +1 -1
  74. package/dist/elements/coachmark.js +1 -1
  75. package/dist/elements/code-block.js +1 -1
  76. package/dist/elements/command.js +1 -1
  77. package/dist/elements/compare.js +1 -1
  78. package/dist/elements/composer.js +1 -1
  79. package/dist/elements/confirm-card.js +1 -1
  80. package/dist/elements/context-meter.js +1 -1
  81. package/dist/elements/conversation-item.js +1 -1
  82. package/dist/elements/conversation-list.js +1 -1
  83. package/dist/elements/dialog.js +1 -1
  84. package/dist/elements/dock.js +1 -1
  85. package/dist/elements/dropdown.js +1 -1
  86. package/dist/elements/editable-label.js +1 -1
  87. package/dist/elements/embed.js +1 -1
  88. package/dist/elements/empty.js +1 -1
  89. package/dist/elements/feedback-bar.js +1 -1
  90. package/dist/elements/file-tree.js +1 -1
  91. package/dist/elements/file-upload.js +1 -1
  92. package/dist/elements/form.js +1 -1
  93. package/dist/elements/hover-card.js +1 -1
  94. package/dist/elements/icon.js +1 -1
  95. package/dist/elements/image.js +1 -1
  96. package/dist/elements/input.js +1 -1
  97. package/dist/elements/kbd.js +1 -1
  98. package/dist/elements/link-preview.js +1 -1
  99. package/dist/elements/loader.js +1 -1
  100. package/dist/elements/markdown.js +1 -1
  101. package/dist/elements/menu.js +1 -1
  102. package/dist/elements/message-skills.js +1 -1
  103. package/dist/elements/message.js +1 -1
  104. package/dist/elements/model-switcher.js +1 -1
  105. package/dist/elements/nav.js +1 -1
  106. package/dist/elements/notice.js +1 -1
  107. package/dist/elements/pane-grid.js +1 -1
  108. package/dist/elements/pane-group.js +1 -1
  109. package/dist/elements/pane.js +1 -1
  110. package/dist/elements/popover.js +1 -1
  111. package/dist/elements/progress-bar.js +1 -1
  112. package/dist/elements/prompt-dock.js +1 -1
  113. package/dist/elements/prompt-input.js +1 -1
  114. package/dist/elements/prompt-suggestions.js +1 -1
  115. package/dist/elements/radio-group.js +1 -1
  116. package/dist/elements/reasoning.js +1 -1
  117. package/dist/elements/remote.js +1 -1
  118. package/dist/elements/resizable.js +1 -1
  119. package/dist/elements/response-stream.js +1 -1
  120. package/dist/elements/screen.js +1 -1
  121. package/dist/elements/scroll-area.js +1 -1
  122. package/dist/elements/scroll-button.js +1 -1
  123. package/dist/elements/search.js +1 -1
  124. package/dist/elements/segmented.js +1 -1
  125. package/dist/elements/select.js +1 -1
  126. package/dist/elements/separator.js +1 -1
  127. package/dist/elements/setting-item.js +1 -1
  128. package/dist/elements/settings-group.js +1 -1
  129. package/dist/elements/skeleton.js +1 -1
  130. package/dist/elements/slider.js +1 -1
  131. package/dist/elements/source.js +1 -1
  132. package/dist/elements/status.js +1 -1
  133. package/dist/elements/switch.js +1 -1
  134. package/dist/elements/tabs.js +1 -1
  135. package/dist/elements/tasks.js +1 -1
  136. package/dist/elements/text-shimmer.js +1 -1
  137. package/dist/elements/thinking-bar.js +1 -1
  138. package/dist/elements/thread.js +1 -1
  139. package/dist/elements/toast.js +1 -1
  140. package/dist/elements/tool.js +1 -1
  141. package/dist/elements/tooltip.js +1 -1
  142. package/dist/elements/voice-input.js +1 -1
  143. package/dist/elements/voice-output.js +1 -1
  144. package/dist/{ellipsis-CbOpJnU3.js → ellipsis-6pJ7SxYT.js} +1 -1
  145. package/dist/{embed-CrfjkbUG.js → embed-BMje-nxj.js} +1 -1
  146. package/dist/engine-javascript-C1x7zo1_.js +1 -141
  147. package/dist/{external-link-ByXAwBBQ.js → external-link-Beh9DKeR.js} +1 -1
  148. package/dist/{file-text-DMib2qwt.js → file-text-D1GPfZ8Q.js} +1 -1
  149. package/dist/{file-tree-CJqM2aP7.js → file-tree-Dwj2lqg-.js} +1 -1
  150. package/dist/{folder-_BAb929C.js → folder-b6D8x1DY.js} +1 -1
  151. package/dist/{form-DSZgZQZk.js → form-DWgdxDXu.js} +1 -1
  152. package/dist/{hover-card-BQbul9eq.js → hover-card-CWRkqm40.js} +1 -1
  153. package/dist/{icon-CdcfRhYI.js → icon-CL0jdhsf.js} +1 -1
  154. package/dist/index.js +1741 -1725
  155. package/dist/index.server.js +1582 -1566
  156. package/dist/{info-DsFjGuI_.js → info-0cOUherQ.js} +1 -1
  157. package/dist/{input-DKbmkMos.js → input-BH6Ru91Q.js} +1 -1
  158. package/dist/kai.es.js +1 -1
  159. package/dist/{kbd-PvdGhX4s.js → kbd-DRAnVtNX.js} +1 -1
  160. package/dist/{link-zF8PzWfF.js → link-Dlr0vssB.js} +1 -1
  161. package/dist/{link-preview-DbM1866N.js → link-preview-DODgRyV9.js} +1 -1
  162. package/dist/loader-KvJB6NrT.js +1 -0
  163. package/dist/{markdown-LMvmAyBk.js → markdown-DX9tuJVj.js} +1 -1
  164. package/dist/mcp.es.js +9 -5
  165. package/dist/{message-BYZECyek.js → message-BqQ7Ot5q.js} +1 -1
  166. package/dist/{message-BSsgvHvf.js → message-DkaGfBd8.js} +1 -1
  167. package/dist/message-circle-BPpp5QKv.js +1 -0
  168. package/dist/message-square-BLbsd9BJ.js +1 -0
  169. package/dist/{minimize-2-BQRoBV1V.js → minimize-2-CyOHJwcN.js} +1 -1
  170. package/dist/{model-switcher-CMpCOYcB.js → model-switcher-0hrKDiK2.js} +1 -1
  171. package/dist/{overlay-Cb-MkyDa.js → overlay-DBMFXie6.js} +1 -1
  172. package/dist/{panel-right-i8warFxT.js → panel-right-t8SWJL6e.js} +1 -1
  173. package/dist/{paperclip-ByY3UVO6.js → paperclip-CdzuOjbU.js} +1 -1
  174. package/dist/play-BXy1u7rW.js +1 -0
  175. package/dist/primitives/use-auto-resize.d.ts +11 -0
  176. package/dist/{progress-bar-jVAHvMUf.js → progress-bar-CiBtxMWT.js} +1 -1
  177. package/dist/{prompt-suggestion-CD-qtNgC.js → prompt-suggestion-I_DHP21i.js} +1 -1
  178. package/dist/{radio-BsoBMhkF.js → radio-C_p3n39l.js} +1 -1
  179. package/dist/{reasoning-4kBPtlTx.js → reasoning-BDwy_tIe.js} +1 -1
  180. package/dist/register-impl-DvEnhIxx.js +424 -0
  181. package/dist/{resizable-uPmY9VY-.js → resizable-SYC-fStM.js} +1 -1
  182. package/dist/{rotate-ccw-B2xn93py.js → rotate-ccw-B1nwmwuY.js} +1 -1
  183. package/dist/{rotate-cw-CMVLoCyH.js → rotate-cw-CLAnBcm1.js} +1 -1
  184. package/dist/{scroll-area-BqLUo8ZZ.js → scroll-area-zRyXoLhI.js} +1 -1
  185. package/dist/{scroll-button-DslXiJyL.js → scroll-button-jzrbYCG9.js} +1 -1
  186. package/dist/{select-2cLRtPGT.js → select-DM-0nEe0.js} +1 -1
  187. package/dist/{separator-BWQtNJcM.js → separator-BToOOoOt.js} +1 -1
  188. package/dist/{settings-BBR63jLg.js → settings-PaGo_S4U.js} +1 -1
  189. package/dist/{settings-group-B2ciy-Iw.js → settings-group-BFXGIfXq.js} +1 -1
  190. package/dist/{skeleton-CkHI-HgC.js → skeleton-DYpmFnnm.js} +1 -1
  191. package/dist/{slider-DDR9U-i0.js → slider-ebutAmkQ.js} +1 -1
  192. package/dist/{solid-DruVOXnf.js → solid-15v_3WVL.js} +3563 -3412
  193. package/dist/{solid-BzCFdL25.js → solid-5P-otgdi.js} +4502 -4296
  194. package/dist/solid.d.ts +6 -0
  195. package/dist/solid.js +259 -254
  196. package/dist/solid.server.js +259 -254
  197. package/dist/{source-GEnFF528.js → source-c1gpRl9h.js} +1 -1
  198. package/dist/{star-CilHq8GP.js → star-pcV_3LqF.js} +1 -1
  199. package/dist/{store-Ciyk6eZG.js → store-CSgbFFCg.js} +1 -1
  200. package/dist/{switch-KkeQIbuH.js → switch-Bh2OdLV2.js} +1 -1
  201. package/dist/{tasks-card-BrN4bggJ.js → tasks-card-CbqQAn2S.js} +1 -1
  202. package/dist/text-shimmer-BSzgEnDH.js +1 -0
  203. package/dist/textarea-DrYNt_0z.js +1 -0
  204. package/dist/theme.tokens.css +22 -21
  205. package/dist/{thumbs-up-CsT9Wzb9.js → thumbs-up-BL3-NenK.js} +1 -1
  206. package/dist/{toast-store-tgK6MuMv.js → toast-store-DkOlYczt.js} +1 -1
  207. package/dist/{tool-DzUjIBT8.js → tool-CeIWUVUe.js} +1 -1
  208. package/dist/{tooltip-Bkkg_4t0.js → tooltip-GA-nmg06.js} +1 -1
  209. package/dist/{trash-2-jBKxjGGQ.js → trash-2-CT66QWlm.js} +1 -1
  210. package/dist/{triangle-alert-DlQ68ppf.js → triangle-alert-CeHLWxhD.js} +1 -1
  211. package/dist/ui/color-field.d.ts +48 -0
  212. package/dist/ui/textarea.d.ts +4 -0
  213. package/dist/ui/toggle-chip.d.ts +40 -0
  214. package/dist/{upload-TcAHXv9W.js → upload-9Csb0F0J.js} +1 -1
  215. package/dist/{use-card-resolution-DaZqAdWf.js → use-card-resolution-Zg0a08Z-.js} +1 -1
  216. package/dist/{variant-aurora-DbW_OWL2.js → variant-aurora-4VBQHIKV.js} +1 -1
  217. package/dist/{variant-aurora-CNmfHhcx.js → variant-aurora-DBeCAQNk.js} +2 -2
  218. package/dist/{variant-aurora-D6GsdTPA.js → variant-aurora-FzHVXHby.js} +2 -2
  219. package/dist/{variant-aurora-BhLuYxJR.js → variant-aurora-LE3fqxgw.js} +1 -1
  220. package/dist/{variant-custom-BvYHR62b.js → variant-custom-AFRGcOBS.js} +1 -1
  221. package/dist/{variant-custom-DV2x254s.js → variant-custom-BQkNuPpE.js} +2 -2
  222. package/dist/{variant-custom-BRvaNHSi.js → variant-custom-DI5R0rln.js} +1 -1
  223. package/dist/{variant-custom-DMTrEO5w.js → variant-custom-WWnrrRHS.js} +2 -2
  224. package/dist/{variant-wave-CyBueXj9.js → variant-wave-DUCbH5oI.js} +2 -2
  225. package/dist/{variant-wave-BNMGrDfj.js → variant-wave-DuQV7DhQ.js} +2 -2
  226. package/dist/{variant-wave-BpDd8t3Z.js → variant-wave-nSI2sfII.js} +1 -1
  227. package/dist/{variant-wave-sp-qwsdI.js → variant-wave-wTP5v_jU.js} +1 -1
  228. package/dist/x-eiO9V6J6.js +1 -0
  229. package/{src/elements/styles.css → kit-base.css} +27 -44
  230. package/package.json +32 -17
  231. package/solid.css +33 -0
  232. package/theme.css +39 -23
  233. package/bin/route.test.js +0 -58
  234. package/dist/arrow-down-CjRU3JgV.js +0 -1
  235. package/dist/arrow-left-Bnpb1UEW.js +0 -1
  236. package/dist/artifact-Bwt7OgcR.js +0 -1
  237. package/dist/check-njkVdZu2.js +0 -1
  238. package/dist/chevron-down-B72s6PXR.js +0 -1
  239. package/dist/chevron-right-BatuHzUm.js +0 -1
  240. package/dist/circle-check-B62pODB3.js +0 -1
  241. package/dist/circle-zx0ByzY9.js +0 -1
  242. package/dist/controllable-CnGpMF6r.js +0 -1
  243. package/dist/define-By-uL588.js +0 -1
  244. package/dist/loader-BM4CEz4G.js +0 -1
  245. package/dist/message-circle-DruwObfX.js +0 -1
  246. package/dist/message-square-BG6q6mlm.js +0 -1
  247. package/dist/play-BvKKq3fX.js +0 -1
  248. package/dist/register-impl-B1hLkrI8.js +0 -424
  249. package/dist/text-shimmer-Dcj1MHuq.js +0 -1
  250. package/dist/textarea-Dpvbngbg.js +0 -1
  251. package/dist/x-Z5UntkIJ.js +0 -1
  252. package/src/agent-tooling/README.md +0 -192
  253. package/src/agent-tooling/archetypes.ts +0 -205
  254. package/src/agent-tooling/catalog/README.md +0 -676
  255. package/src/agent-tooling/catalog/catalog-types.ts +0 -231
  256. package/src/agent-tooling/catalog/fabrications.ts +0 -96
  257. package/src/agent-tooling/catalog/invariants.ts +0 -284
  258. package/src/agent-tooling/catalog/labs-titles.ts +0 -114
  259. package/src/agent-tooling/catalog/scenarios.ts +0 -87
  260. package/src/agent-tooling/catalog/surfaces.ts +0 -347
  261. package/src/agent-tooling/construct/cli-entry.ts +0 -8
  262. package/src/agent-tooling/construct/cli.ts +0 -147
  263. package/src/agent-tooling/construct/codegen.ts +0 -1635
  264. package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
  265. package/src/agent-tooling/construct/dev.ts +0 -148
  266. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
  267. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
  268. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
  269. package/src/agent-tooling/construct/schema.ts +0 -452
  270. package/src/agent-tooling/integrations/anthropic.ts +0 -442
  271. package/src/agent-tooling/integrations/cloudflare.ts +0 -218
  272. package/src/agent-tooling/integrations/langgraph.ts +0 -133
  273. package/src/agent-tooling/integrations/mastra.ts +0 -182
  274. package/src/agent-tooling/integrations/mock.ts +0 -148
  275. package/src/agent-tooling/integrations/ollama.ts +0 -97
  276. package/src/agent-tooling/integrations/openai.ts +0 -95
  277. package/src/agent-tooling/integrations/openrouter.ts +0 -82
  278. package/src/agent-tooling/integrations/pi.ts +0 -176
  279. package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
  280. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
  281. package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
  282. package/src/agent-tooling/mcp/manifest.ts +0 -422
  283. package/src/agent-tooling/mcp/server.ts +0 -116
  284. package/src/agent-tooling/mcp/stdio.ts +0 -18
  285. package/src/agent-tooling/mcp/tools/construct.ts +0 -130
  286. package/src/agent-tooling/mcp/tools/debug.ts +0 -621
  287. package/src/agent-tooling/mcp/tools/reference.ts +0 -980
  288. package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
  289. package/src/agent-tooling/mcp/tools/theme.ts +0 -456
  290. package/src/agent-tooling/mcp/tools/types.ts +0 -14
  291. package/src/agent-tooling/mcp/validate-args.ts +0 -141
  292. package/src/agent-tooling/recipes/composed-thread.ts +0 -714
  293. package/src/agent-tooling/recipes/index.ts +0 -22
  294. package/src/agent-tooling/recipes/types.ts +0 -32
  295. package/src/agent-tooling/registry.ts +0 -132
  296. package/src/agent-tooling/route-emit.ts +0 -305
  297. package/src/agent-tooling/types.ts +0 -390
  298. package/src/components/artifact-card.tsx +0 -120
  299. package/src/components/artifact.tsx +0 -914
  300. package/src/components/attachment-types.ts +0 -66
  301. package/src/components/attachments.tsx +0 -536
  302. package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
  303. package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
  304. package/src/components/audio-visualizer/fit-scale.ts +0 -112
  305. package/src/components/audio-visualizer/index.tsx +0 -528
  306. package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
  307. package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
  308. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
  309. package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
  310. package/src/components/audio-visualizer/sizes.ts +0 -54
  311. package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
  312. package/src/components/audio-visualizer/variant-bar.tsx +0 -175
  313. package/src/components/audio-visualizer/variant-custom.tsx +0 -344
  314. package/src/components/audio-visualizer/variant-grid.tsx +0 -175
  315. package/src/components/audio-visualizer/variant-radial.tsx +0 -163
  316. package/src/components/audio-visualizer/variant-wave.tsx +0 -130
  317. package/src/components/audio-visualizer/wave.glsl.ts +0 -130
  318. package/src/components/card-fallback.tsx +0 -60
  319. package/src/components/card-renderer.tsx +0 -220
  320. package/src/components/card.tsx +0 -212
  321. package/src/components/chain-of-thought.tsx +0 -348
  322. package/src/components/chat-container.tsx +0 -89
  323. package/src/components/chat-scope-picker.tsx +0 -57
  324. package/src/components/chat-thread.tsx +0 -1014
  325. package/src/components/checkpoint.tsx +0 -88
  326. package/src/components/choice-card.tsx +0 -743
  327. package/src/components/coachmark.tsx +0 -249
  328. package/src/components/code-block.tsx +0 -181
  329. package/src/components/composer-dom.ts +0 -159
  330. package/src/components/composer-highlight.ts +0 -242
  331. package/src/components/composer-history.ts +0 -82
  332. package/src/components/composer.tsx +0 -1075
  333. package/src/components/confirm-card.tsx +0 -402
  334. package/src/components/context.tsx +0 -377
  335. package/src/components/conversation-item.tsx +0 -241
  336. package/src/components/conversation-list.tsx +0 -429
  337. package/src/components/conversation-panel.tsx +0 -118
  338. package/src/components/dismissed-stub.tsx +0 -80
  339. package/src/components/embed.tsx +0 -200
  340. package/src/components/empty.tsx +0 -177
  341. package/src/components/feedback-bar.tsx +0 -166
  342. package/src/components/file-tree.tsx +0 -530
  343. package/src/components/file-upload.tsx +0 -167
  344. package/src/components/form-widgets.tsx +0 -525
  345. package/src/components/form.tsx +0 -1296
  346. package/src/components/home-panel.tsx +0 -159
  347. package/src/components/image.tsx +0 -65
  348. package/src/components/link-preview.tsx +0 -195
  349. package/src/components/loader.tsx +0 -367
  350. package/src/components/markdown.tsx +0 -162
  351. package/src/components/message-skills.tsx +0 -40
  352. package/src/components/message.tsx +0 -765
  353. package/src/components/model-switcher.tsx +0 -132
  354. package/src/components/prompt-input.tsx +0 -188
  355. package/src/components/prompt-suggestion.tsx +0 -150
  356. package/src/components/reasoning.tsx +0 -293
  357. package/src/components/response-compare-types.ts +0 -152
  358. package/src/components/response-compare.tsx +0 -455
  359. package/src/components/response-stream.tsx +0 -109
  360. package/src/components/screen.tsx +0 -181
  361. package/src/components/scroll-button.tsx +0 -93
  362. package/src/components/source.tsx +0 -192
  363. package/src/components/tasks-card.tsx +0 -801
  364. package/src/components/text-shimmer.tsx +0 -37
  365. package/src/components/thinking-bar.tsx +0 -50
  366. package/src/components/thread.tsx +0 -228
  367. package/src/components/toast.tsx +0 -503
  368. package/src/components/tool-classify.ts +0 -26
  369. package/src/components/tool-types.ts +0 -49
  370. package/src/components/tool.tsx +0 -190
  371. package/src/components/use-card-resolution.ts +0 -44
  372. package/src/components/voice-input.tsx +0 -222
  373. package/src/components/voice-output.tsx +0 -242
  374. package/src/components/widget-tab-bar.tsx +0 -73
  375. package/src/components/workspace-shell.tsx +0 -285
  376. package/src/diagnostics/hook.ts +0 -352
  377. package/src/diagnostics/index.ts +0 -82
  378. package/src/diagnostics/report-request.ts +0 -296
  379. package/src/elements/agent-card.tsx +0 -67
  380. package/src/elements/artifact.tsx +0 -194
  381. package/src/elements/attachments.tsx +0 -140
  382. package/src/elements/audio-visualizer.tsx +0 -227
  383. package/src/elements/autoloader.ts +0 -89
  384. package/src/elements/avatar.tsx +0 -33
  385. package/src/elements/badge.tsx +0 -32
  386. package/src/elements/button.tsx +0 -149
  387. package/src/elements/card.tsx +0 -133
  388. package/src/elements/cards.tsx +0 -266
  389. package/src/elements/chain-of-thought.tsx +0 -141
  390. package/src/elements/chat-scope-picker.tsx +0 -65
  391. package/src/elements/chat-types.ts +0 -102
  392. package/src/elements/chat-workspace.tsx +0 -188
  393. package/src/elements/chat.tsx +0 -304
  394. package/src/elements/checkbox-group.tsx +0 -164
  395. package/src/elements/checkbox.tsx +0 -134
  396. package/src/elements/checkpoint.tsx +0 -47
  397. package/src/elements/choice.tsx +0 -100
  398. package/src/elements/coachmark.tsx +0 -90
  399. package/src/elements/code-block.tsx +0 -60
  400. package/src/elements/command.tsx +0 -197
  401. package/src/elements/compare.tsx +0 -111
  402. package/src/elements/compiled.css +0 -2
  403. package/src/elements/composer.tsx +0 -162
  404. package/src/elements/confirm-card.tsx +0 -76
  405. package/src/elements/context-meter.tsx +0 -107
  406. package/src/elements/conversation-item.tsx +0 -120
  407. package/src/elements/conversation-list.tsx +0 -203
  408. package/src/elements/css.ts +0 -5
  409. package/src/elements/default-input.tsx +0 -392
  410. package/src/elements/define-entry.ts +0 -12
  411. package/src/elements/define.tsx +0 -563
  412. package/src/elements/diagnostic-events.ts +0 -114
  413. package/src/elements/dialog.tsx +0 -145
  414. package/src/elements/disclosure.ts +0 -95
  415. package/src/elements/dock.tsx +0 -215
  416. package/src/elements/dropdown.tsx +0 -123
  417. package/src/elements/editable-label.tsx +0 -140
  418. package/src/elements/element-data-types.ts +0 -152
  419. package/src/elements/element-diagnostics.ts +0 -392
  420. package/src/elements/element-manifest.json +0 -354
  421. package/src/elements/element-nonscalar.json +0 -187
  422. package/src/elements/element-types.d.ts +0 -4353
  423. package/src/elements/embed.tsx +0 -35
  424. package/src/elements/empty.tsx +0 -29
  425. package/src/elements/feedback-bar.tsx +0 -66
  426. package/src/elements/file-tree.tsx +0 -62
  427. package/src/elements/file-upload.tsx +0 -44
  428. package/src/elements/form.tsx +0 -94
  429. package/src/elements/hover-card.tsx +0 -80
  430. package/src/elements/icon.tsx +0 -41
  431. package/src/elements/image.tsx +0 -32
  432. package/src/elements/input.tsx +0 -492
  433. package/src/elements/kbd.tsx +0 -45
  434. package/src/elements/link-preview.tsx +0 -34
  435. package/src/elements/loader.tsx +0 -25
  436. package/src/elements/markdown.tsx +0 -38
  437. package/src/elements/menu.tsx +0 -241
  438. package/src/elements/message-skills.tsx +0 -83
  439. package/src/elements/message.tsx +0 -361
  440. package/src/elements/model-switcher.tsx +0 -121
  441. package/src/elements/nav.tsx +0 -87
  442. package/src/elements/notice.tsx +0 -53
  443. package/src/elements/pane-grid.tsx +0 -111
  444. package/src/elements/pane-group.tsx +0 -119
  445. package/src/elements/pane.tsx +0 -129
  446. package/src/elements/popover.tsx +0 -81
  447. package/src/elements/progress-bar.tsx +0 -39
  448. package/src/elements/prompt-dock.tsx +0 -82
  449. package/src/elements/prompt-input.tsx +0 -240
  450. package/src/elements/prompt-suggestions.tsx +0 -113
  451. package/src/elements/radio-group.tsx +0 -129
  452. package/src/elements/reasoning.tsx +0 -71
  453. package/src/elements/register-impl.ts +0 -148
  454. package/src/elements/register.ts +0 -76
  455. package/src/elements/remote.tsx +0 -225
  456. package/src/elements/resizable.globals.d.ts +0 -36
  457. package/src/elements/resizable.tsx +0 -704
  458. package/src/elements/response-stream.tsx +0 -40
  459. package/src/elements/screen.tsx +0 -90
  460. package/src/elements/scroll-area.tsx +0 -33
  461. package/src/elements/scroll-button.tsx +0 -179
  462. package/src/elements/search.tsx +0 -185
  463. package/src/elements/segmented.tsx +0 -129
  464. package/src/elements/select.tsx +0 -165
  465. package/src/elements/separator.tsx +0 -36
  466. package/src/elements/setting-item.tsx +0 -50
  467. package/src/elements/settings-group.tsx +0 -37
  468. package/src/elements/skeleton.tsx +0 -45
  469. package/src/elements/slider.tsx +0 -171
  470. package/src/elements/slot-text.ts +0 -73
  471. package/src/elements/slots.ts +0 -787
  472. package/src/elements/source.tsx +0 -126
  473. package/src/elements/status.tsx +0 -42
  474. package/src/elements/switch.tsx +0 -118
  475. package/src/elements/tabs.tsx +0 -95
  476. package/src/elements/tasks.tsx +0 -103
  477. package/src/elements/text-shimmer.tsx +0 -28
  478. package/src/elements/thinking-bar.tsx +0 -43
  479. package/src/elements/thread.tsx +0 -139
  480. package/src/elements/toast.tsx +0 -106
  481. package/src/elements/tool.tsx +0 -78
  482. package/src/elements/tooltip.tsx +0 -85
  483. package/src/elements/validate-messages.ts +0 -76
  484. package/src/elements/voice-input.tsx +0 -100
  485. package/src/elements/voice-output.tsx +0 -82
  486. package/src/index.ts +0 -430
  487. package/src/primitives/audio-bands.ts +0 -174
  488. package/src/primitives/card-component-types.ts +0 -63
  489. package/src/primitives/card-contract.ts +0 -80
  490. package/src/primitives/card-data-types.ts +0 -361
  491. package/src/primitives/card-host.tsx +0 -37
  492. package/src/primitives/card-recovery.ts +0 -160
  493. package/src/primitives/card-registry.tsx +0 -78
  494. package/src/primitives/card-resolution.ts +0 -36
  495. package/src/primitives/card-routing.ts +0 -85
  496. package/src/primitives/card-schemas/artifact.schema.json +0 -92
  497. package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
  498. package/src/primitives/card-schemas/card-event.schema.json +0 -12
  499. package/src/primitives/card-schemas/choice.schema.json +0 -75
  500. package/src/primitives/card-schemas/confirm.schema.json +0 -65
  501. package/src/primitives/card-schemas/embed.schema.json +0 -63
  502. package/src/primitives/card-schemas/form.result.schema.json +0 -7
  503. package/src/primitives/card-schemas/form.schema.json +0 -53
  504. package/src/primitives/card-schemas/link.schema.json +0 -54
  505. package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
  506. package/src/primitives/card-schemas/tasks.schema.json +0 -83
  507. package/src/primitives/card-tags.ts +0 -61
  508. package/src/primitives/card-validate-cards.ts +0 -255
  509. package/src/primitives/card-validate-schemas.ts +0 -58
  510. package/src/primitives/card-validate.ts +0 -131
  511. package/src/primitives/chat-config.tsx +0 -103
  512. package/src/primitives/composer-model.ts +0 -49
  513. package/src/primitives/composer-triggers.ts +0 -35
  514. package/src/primitives/controllable.ts +0 -21
  515. package/src/primitives/conversation-store.ts +0 -248
  516. package/src/primitives/create-kai-chat.ts +0 -66
  517. package/src/primitives/create-tween.ts +0 -266
  518. package/src/primitives/embed-providers.ts +0 -254
  519. package/src/primitives/field-mask.ts +0 -256
  520. package/src/primitives/field-semantics.ts +0 -115
  521. package/src/primitives/highlighter.ts +0 -157
  522. package/src/primitives/input-mask.ts +0 -853
  523. package/src/primitives/link-preview.ts +0 -87
  524. package/src/primitives/message-feedback.ts +0 -124
  525. package/src/primitives/pdf-preview.ts +0 -121
  526. package/src/primitives/toast-store.ts +0 -338
  527. package/src/primitives/url-scheme-policy.ts +0 -70
  528. package/src/primitives/use-audio-analysis.ts +0 -340
  529. package/src/primitives/use-auto-resize.ts +0 -31
  530. package/src/primitives/use-resize-observer.ts +0 -45
  531. package/src/primitives/use-sequencer.ts +0 -72
  532. package/src/primitives/use-speech-recognition.ts +0 -146
  533. package/src/primitives/use-stick-to-bottom.ts +0 -75
  534. package/src/primitives/use-text-stream.ts +0 -143
  535. package/src/primitives/use-voice-recorder.ts +0 -62
  536. package/src/primitives/visualizer-sequences.ts +0 -350
  537. package/src/remote/host-embed.ts +0 -345
  538. package/src/remote/index.ts +0 -2
  539. package/src/remote/origin.ts +0 -30
  540. package/src/remote/provider-runtime.ts +0 -262
  541. package/src/remote/provider.ts +0 -2
  542. package/src/remote/validate.ts +0 -22
  543. package/src/remote/version.ts +0 -12
  544. package/src/remote/wire.ts +0 -48
  545. package/src/schemas/from-tool-call.ts +0 -151
  546. package/src/schemas/index.ts +0 -341
  547. package/src/schemas/provider-subsets.ts +0 -538
  548. package/src/schemas/registry.ts +0 -355
  549. package/src/schemas/tool-defs.ts +0 -793
  550. package/src/solid.ts +0 -173
  551. package/src/state/index.ts +0 -44
  552. package/src/state/messages.ts +0 -53
  553. package/src/state/mock.ts +0 -297
  554. package/src/state/parts.ts +0 -295
  555. package/src/state/persistence.ts +0 -180
  556. package/src/state/stream.ts +0 -246
  557. package/src/state/suggestions.ts +0 -9
  558. package/src/state/threads.ts +0 -142
  559. package/src/test-utils/fake-clock.ts +0 -88
  560. package/src/types.ts +0 -95
  561. package/src/ui/action-icons.ts +0 -53
  562. package/src/ui/agent-card.tsx +0 -218
  563. package/src/ui/avatar.tsx +0 -23
  564. package/src/ui/badge.tsx +0 -21
  565. package/src/ui/button.tsx +0 -49
  566. package/src/ui/card.tsx +0 -245
  567. package/src/ui/checkbox-group.tsx +0 -153
  568. package/src/ui/checkbox.tsx +0 -63
  569. package/src/ui/collapsible.tsx +0 -163
  570. package/src/ui/command.tsx +0 -103
  571. package/src/ui/dialog.tsx +0 -223
  572. package/src/ui/dock.tsx +0 -630
  573. package/src/ui/dropdown.tsx +0 -636
  574. package/src/ui/editable-label.tsx +0 -112
  575. package/src/ui/hover-card.tsx +0 -345
  576. package/src/ui/icon.tsx +0 -167
  577. package/src/ui/input.tsx +0 -391
  578. package/src/ui/kbd.tsx +0 -118
  579. package/src/ui/nav.tsx +0 -282
  580. package/src/ui/notice.tsx +0 -84
  581. package/src/ui/overlay.tsx +0 -277
  582. package/src/ui/pane-grid.tsx +0 -117
  583. package/src/ui/pane-group.tsx +0 -291
  584. package/src/ui/pane.tsx +0 -193
  585. package/src/ui/popover.tsx +0 -106
  586. package/src/ui/progress-bar.tsx +0 -83
  587. package/src/ui/prompt-dock.tsx +0 -145
  588. package/src/ui/radio.tsx +0 -150
  589. package/src/ui/resizable.tsx +0 -693
  590. package/src/ui/scroll-area.tsx +0 -26
  591. package/src/ui/segmented.tsx +0 -109
  592. package/src/ui/select.tsx +0 -168
  593. package/src/ui/separator.tsx +0 -10
  594. package/src/ui/settings-group.tsx +0 -67
  595. package/src/ui/skeleton.tsx +0 -73
  596. package/src/ui/slider.tsx +0 -178
  597. package/src/ui/status.tsx +0 -48
  598. package/src/ui/switch.tsx +0 -119
  599. package/src/ui/tabs.tsx +0 -168
  600. package/src/ui/textarea.tsx +0 -21
  601. package/src/ui/tooltip.tsx +0 -118
  602. package/src/utils/cn.ts +0 -30
  603. package/src/wire/chunk.ts +0 -248
  604. package/src/wire/consume.ts +0 -599
  605. package/src/wire/diagnostics.ts +0 -727
  606. package/src/wire/encode-probe.ts +0 -214
  607. package/src/wire/encode.ts +0 -947
  608. package/src/wire/files.ts +0 -342
  609. package/src/wire/formats/anthropic.ts +0 -274
  610. package/src/wire/formats/openai.ts +0 -228
  611. package/src/wire/index.ts +0 -95
  612. package/src/wire/media-types.ts +0 -344
  613. package/src/wire/read.ts +0 -396
  614. package/src/wire/sink-helpers.ts +0 -50
  615. package/src/wire/sse.ts +0 -153
package/src/wire/files.ts DELETED
@@ -1,342 +0,0 @@
1
- // Attachment -> wire classification, shared by both encoders.
2
- //
3
- // Split out of encode.ts because the two wires disagree about attachments in a
4
- // way that is worth stating once: WHAT a file is (an image, a PDF, or something
5
- // neither API takes as message content) is provider-neutral and decided here;
6
- // HOW it rides on the wire is provider-specific and decided in encode.ts. The
7
- // one gap that falls out of that split is OpenAI's, and it is real: a remote PDF
8
- // has no representation in chat-completions at all.
9
- //
10
- // No I/O, exactly like the rest of this layer. Nothing here fetches a URL,
11
- // reads a File, or base64s anything: an attachment either already carries bytes
12
- // (a `data:` URI) or already carries an address the provider can resolve
13
- // itself. That constraint is what makes a `blob:` URL unencodable rather than
14
- // merely inconvenient -- resolving one requires the browser tab that minted it.
15
- import type { AttachmentData } from '../components/attachment-types';
16
- import {
17
- DEFAULT_MEDIA_POLICY,
18
- UNNAMED_TEXT_MEDIA_TYPE,
19
- namesNothing,
20
- type MediaPolicy,
21
- } from './media-types';
22
-
23
- /** `data:<media type>;base64,<data>`. Base64 is required -- both APIs need it,
24
- * and a `data:` URI without it cannot become a content block without guessing.
25
- * The media type is NOT required, because a browser omits it for a file it
26
- * could not name: the File API says to emit a `data:` URL with no media type,
27
- * and Chrome and jsdom both write `application/octet-stream` there instead.
28
- * Either way there is no type to read, which `decide()` answers with
29
- * `undetermined` and this file settles by decoding. */
30
- const BASE64_DATA_URI = /^data:([^;,]*);base64,([\s\S]*)$/;
31
-
32
- const SCHEME = /^([a-z][a-z0-9+.-]*):/i;
33
-
34
- /** Where the bytes live. `base64` carries them inline; `remote` is an address
35
- * the PROVIDER dereferences, never us. */
36
- export type FileSource =
37
- | { type: 'base64'; mediaType: string; data: string; dataUri: string }
38
- | { type: 'remote'; url: string };
39
-
40
- /** Bytes already in hand, shaped for the provider. A union rather than an
41
- * optional `text` field so neither encoder can reach for text that is not
42
- * there, and so adding a kind is a compile error at both wires rather than a
43
- * silently unhandled branch. */
44
- export type ClassifiedFile =
45
- /** Named for the Anthropic blocks they become. `document` is PDF-only. */
46
- | { kind: 'image'; mediaType: string; source: FileSource; filename?: string }
47
- | { kind: 'document'; mediaType: string; source: FileSource; filename?: string }
48
- /** The bytes, decoded. A text file rides as TEXT CONTENT on both wires --
49
- * neither API has an arbitrary-file block, so this is the only representation
50
- * the wire can express, not a preference. `source` is narrowed to `base64`
51
- * because the text has to be in hand to inline it, and fetching a remote one
52
- * would put I/O in the encoder. */
53
- | {
54
- kind: 'text';
55
- mediaType: string;
56
- source: Extract<FileSource, { type: 'base64' }>;
57
- filename?: string;
58
- text: string;
59
- };
60
-
61
- export type FileClassification =
62
- /** Ready for either wire to shape. A wire may still refuse it -- see
63
- * OpenAI and remote PDFs -- but the attachment itself is sound. */
64
- | { status: 'encodable'; file: ClassifiedFile }
65
- /** Not an upload at all. A `source-document` is the citation chip an app
66
- * renders next to a RAG answer, not something the user staged to send, and
67
- * its content is already in the prompt that produced the answer. Encoding it
68
- * would send the same text twice. */
69
- | { status: 'kit-side' }
70
- /** Cannot reach a model. `reason` completes the sentence "Cannot encode file
71
- * part N of message X: ...", so it explains AND says what to do. */
72
- | { status: 'unencodable'; reason: string };
73
-
74
- const quotedList = (values: readonly string[]): string => values.map((v) => `"${v}"`).join(', ');
75
-
76
- /**
77
- * Base64 to the bytes it stands for.
78
- *
79
- * NOT a violation of this file's no-I/O rule. The bytes are already inline in
80
- * the `data:` URI the host staged; this decodes what is in hand and reaches for
81
- * nothing. `atob` yields a binary string (one char per byte), which is then read
82
- * as UTF-8 -- going straight from `atob` to text would mangle every non-ASCII
83
- * character in the file.
84
- *
85
- * ★ WHAT A CLEAN DECODE PROVES, AND WHAT IT DOES NOT. It proves the bytes are
86
- * well-formed UTF-8. It does not prove they are meaningful text, and the gap is
87
- * not hypothetical: every byte below 0x80 is valid UTF-8 on its own, so a small
88
- * binary made of low bytes decodes cleanly. A bare zip header -- `50 4b 03 04`
89
- * followed by NULs -- is exactly that. This matters most on the path where
90
- * nothing named the file, because there the decode is the ONLY evidence there is.
91
- *
92
- * A NUL-byte heuristic (git's rule for "is this binary") would catch most of
93
- * them, and it is deliberately NOT here. This same function serves the LABELLED
94
- * text path, where a host that said `text/plain` has asserted something the kit
95
- * has no business overruling, and a text file that legitimately contains a NUL
96
- * would start being refused on a rule nobody asked for. Weigh the two failures:
97
- * being wrong the current way sends a block of gibberish the model can see and
98
- * describe, and being wrong the other way silently refuses a real text file.
99
- * Only the first is recoverable by the person it happens to.
100
- */
101
- function decodeBase64Text(data: string): { ok: true; text: string; bytes: number } | { ok: false } {
102
- try {
103
- const binary = atob(data);
104
- const bytes = new Uint8Array(binary.length);
105
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
106
- // `fatal` so mislabelled binary (a .zip renamed .txt) is refused with a
107
- // reason instead of silently becoming a screenful of replacement characters.
108
- return { ok: true, text: new TextDecoder('utf-8', { fatal: true }).decode(bytes), bytes: binary.length };
109
- } catch {
110
- return { ok: false };
111
- }
112
- }
113
-
114
- /**
115
- * XML attribute escaping, for the two attributes the envelope carries.
116
- *
117
- * A filename is whatever the user called their file, and it lands between double
118
- * quotes: `notes" x="` would otherwise rewrite the header into attributes of its
119
- * own choosing. Newlines are escaped for the same reason and not for tidiness --
120
- * a raw one splits the header across lines, which is how a filename gets to look
121
- * like the start of the content.
122
- *
123
- * The media type goes through the same function, which is not symmetry for its
124
- * own sake: it comes from a `data:` URI, where it is anything up to the first
125
- * `;`, and `text/pl"ain` matches the `text/*` capability and arrives here whole.
126
- */
127
- const escapeAttribute = (value: string): string =>
128
- value
129
- .replace(/&/g, '&amp;')
130
- .replace(/</g, '&lt;')
131
- .replace(/>/g, '&gt;')
132
- .replace(/"/g, '&quot;')
133
- .replace(/\r/g, '&#13;')
134
- .replace(/\n/g, '&#10;');
135
-
136
- /** The only sequence in the body that could end the block early, and so the only
137
- * thing in the body that gets touched. Whitespace-tolerant and case-insensitive
138
- * because the reader here is a model, and `</file >` reads as the end to one
139
- * just as readily as `</file>` does. */
140
- const CLOSING_DELIMITER = /<(\/file\s*)>/gi;
141
-
142
- /**
143
- * The text content a text attachment contributes to the prompt.
144
- *
145
- * ★ THE SWAP POINT for how a text file appears in a message, and the shape is
146
- * SETTLED: `<file name="..." type="...">…</file>`. Two alternatives were weighed
147
- * and rejected. A bare `filename:\n` prefix marks where the file BEGINS and not
148
- * where it ends, so the next part of the turn reads as more file. An Anthropic
149
- * `document` block would buy citations, but it is Anthropic-specific -- the
150
- * OpenAI wire has no equivalent, so the two wires would disagree about one
151
- * attachment -- and it needs a Files API upload round trip, which is I/O, in a
152
- * layer that by design has none. Changing the envelope is still a change to this
153
- * function and nothing else; it just is not an open question.
154
- *
155
- * ★ WHY THE BODY IS BARELY TOUCHED. Both attributes are escaped in full, as
156
- * attributes always are. The body is not, and that is deliberate: these are
157
- * source files, a reader will diff what they attached against what arrived, and
158
- * XML-escaping every `<` in a TSX file would mangle the exact thing this feature
159
- * exists to send and pay tokens to do it. So the body transform is the smallest
160
- * one that makes the delimiter unforgeable -- the end tag, and nothing else.
161
- *
162
- * Left alone, that end tag is a way out of the block. A file containing `</file>`
163
- * closes it early, and everything after that point reads to the model as the turn
164
- * AROUND the file rather than as file content: user-supplied bytes in instruction
165
- * position, reachable by anyone who can get a file in front of the composer.
166
- * Escaped, it stays where it belongs. `&lt;/file&gt;` ends nothing, and it is
167
- * visible in the output and reversible by eye, which a deletion or a silent
168
- * substitution would not be -- a reader who spots it can say exactly what the
169
- * original byte was. The OPENING tag is left untouched on purpose: it cannot end
170
- * the block, and escaping it would corrupt every HTML file anyone ever attaches.
171
- */
172
- export function textFileContent(file: Extract<ClassifiedFile, { kind: 'text' }>): string {
173
- const name = escapeAttribute(file.filename ?? 'attachment');
174
- const type = escapeAttribute(file.mediaType);
175
- const text = file.text.replace(CLOSING_DELIMITER, '&lt;$1&gt;');
176
- return `<file name="${name}" type="${type}">\n${text}\n</file>`;
177
- }
178
-
179
- /**
180
- * One attachment to the provider-neutral facts both encoders need.
181
- *
182
- * A `data:` URI's OWN media type wins over `attachment.mediaType` when they
183
- * disagree: the URI describes the bytes actually present, while the field is a
184
- * label the host set, and it is the bytes the provider will decode. The one
185
- * exception is a URI whose media type names nothing, where there is no answer to
186
- * prefer -- see below.
187
- *
188
- * When NOTHING names the file, it is settled by DECODING it rather than by
189
- * reading its filename. That path can only ever produce text, and only when the
190
- * policy still allows text, so it cannot be used to get around `accept`.
191
- *
192
- * `policy` narrows what counts as encodable. It defaults to the kit's full
193
- * capability set, so an omitted policy behaves exactly as before for images and
194
- * PDFs. It is the SAME object the composer resolves for its picker -- see
195
- * `media-types.ts` for why that sharing is the point rather than a convenience.
196
- */
197
- export function classifyAttachment(
198
- attachment: AttachmentData,
199
- policy: MediaPolicy = DEFAULT_MEDIA_POLICY,
200
- ): FileClassification {
201
- if (attachment.type === 'source-document') return { status: 'kit-side' };
202
-
203
- const url = attachment.url;
204
- if (url === undefined || url === '') {
205
- return {
206
- status: 'unencodable',
207
- reason:
208
- 'it has no `url`, so there are no bytes and no address to send. Set `url` to a `data:` URI (read the File with FileReader.readAsDataURL before you stage it) or to an https URL the provider can fetch.',
209
- };
210
- }
211
-
212
- let source: FileSource;
213
- let mediaType: string;
214
-
215
- const asData = BASE64_DATA_URI.exec(url);
216
- if (asData) {
217
- const inUri = asData[1].toLowerCase();
218
- // The URI's own media type wins -- but only when it NAMES something. A
219
- // browser writes `application/octet-stream` (or nothing) for a file it could
220
- // not identify, and a non-answer describes the bytes no better than the
221
- // host's `mediaType` field does. In that one case the field is the only
222
- // label anybody actually wrote down, so it is read rather than overridden.
223
- mediaType = namesNothing(inUri) ? (attachment.mediaType?.toLowerCase() ?? inUri) : inUri;
224
- source = { type: 'base64', mediaType, data: asData[2], dataUri: url };
225
- } else if (/^https?:\/\//i.test(url)) {
226
- const declared = attachment.mediaType?.toLowerCase();
227
- if (declared === undefined || declared === '') {
228
- return {
229
- status: 'unencodable',
230
- reason: `its \`url\` is remote ("${url}") but it has no \`mediaType\`, so there is no way to tell an image from a document without fetching it -- and this layer does no I/O. Set \`mediaType\` when you stage the attachment.`,
231
- };
232
- }
233
- mediaType = declared;
234
- source = { type: 'remote', url };
235
- } else if (url.startsWith('data:')) {
236
- return {
237
- status: 'unencodable',
238
- reason:
239
- 'its `url` is a `data:` URI that is not base64-encoded with an explicit media type. Both APIs need `data:<media type>;base64,<data>`.',
240
- };
241
- } else {
242
- const scheme = SCHEME.exec(url)?.[1].toLowerCase();
243
- // blob: is the one people hit, because it is what URL.createObjectURL and
244
- // every drag-and-drop example hand you. It resolves only inside the tab that
245
- // created it, so it looks perfect in the thread and is meaningless to a model.
246
- const detail =
247
- scheme === 'blob'
248
- ? 'a `blob:` URL resolves only inside the browser tab that created it, so a model can never fetch it. Read the File with FileReader.readAsDataURL and stage the `data:` URI instead, or upload it and stage the resulting https URL'
249
- : `a "${scheme ?? url}" URL is not something a provider can fetch. Use a \`data:\` URI or an https URL`;
250
- return { status: 'unencodable', reason: `its \`url\` is "${url}": ${detail}.` };
251
- }
252
-
253
- const decision = policy.decide(mediaType);
254
-
255
- if (decision.status === 'undetermined') {
256
- // ★ NOBODY NAMED THIS FILE, SO READ IT. Seven of the file types a developer
257
- // is likeliest to attach to a coding chat arrive from Chrome with no media
258
- // type at all (the table in media-types.ts), and the tempting fix -- map
259
- // `.rs` to text -- is a filename talking, which is the one thing this design
260
- // refuses. The bytes are already in hand, so ask them instead: a clean UTF-8
261
- // decode IS the evidence that this is text, and it is evidence about the
262
- // actual file rather than about its name.
263
- //
264
- // The developer's filter is already enforced: `undetermined` comes back only
265
- // when the effective policy still admits plain text, so reaching this line at
266
- // all means a text file is something this policy would take. An
267
- // images-only `accept` gets `unsupported` and never arrives here.
268
- if (source.type !== 'base64') {
269
- return {
270
- status: 'unencodable',
271
- reason: `it is at a remote URL ("${source.url}") and its media type "${mediaType}" says nothing about the bytes -- that is the label for "arbitrary binary", so it separates an image from a document not at all. Settling it by reading the bytes would need a fetch, and this layer does no I/O. Set \`mediaType\` to what the file actually is when you stage it.`,
272
- };
273
- }
274
- const decoded = decodeBase64Text(source.data);
275
- if (!decoded.ok) {
276
- return {
277
- status: 'unencodable',
278
- reason: `nothing names it -- ${mediaType === '' ? 'it carries no media type' : `its media type is "${mediaType}"`}, so the only way to tell what it is was to read it -- and its bytes are not valid UTF-8, so it is binary of some unidentified kind. Neither API has an arbitrary-file block to carry that. Set \`mediaType\` if you know what it is, or hand the file to the model through a tool.`,
279
- };
280
- }
281
- // `text/plain` and not the media type it arrived with: a decode establishes
282
- // "this is text" and nothing more specific, and that is exactly what
283
- // `text/plain` means. See UNNAMED_TEXT_MEDIA_TYPE.
284
- return {
285
- status: 'encodable',
286
- file: {
287
- kind: 'text',
288
- mediaType: UNNAMED_TEXT_MEDIA_TYPE,
289
- source,
290
- filename: attachment.filename,
291
- text: decoded.text,
292
- },
293
- };
294
- }
295
-
296
- if (decision.status === 'filtered') {
297
- return {
298
- status: 'unencodable',
299
- reason: `its media type "${mediaType}" is one this kit can encode, but your \`accept\` filter excludes it. The types you allowed are: ${quotedList(policy.types)}. Widen \`accept\` to include it, or stop staging it.`,
300
- };
301
- }
302
-
303
- if (decision.status === 'unsupported') {
304
- return {
305
- status: 'unencodable',
306
- reason: `its media type "${mediaType}" is not one either API accepts as message content. Supported: ${quotedList(policy.types)}. Extract the content yourself and send it as text, or hand it to the model through a tool.`,
307
- };
308
- }
309
-
310
- if (decision.kind === 'text') {
311
- // A remote text file would have to be FETCHED to be inlined, and this layer
312
- // does no I/O. Refused with the fix rather than silently dropped.
313
- if (source.type !== 'base64') {
314
- return {
315
- status: 'unencodable',
316
- reason: `it is a text file at a remote URL ("${source.url}"), and text has to ride as text CONTENT -- neither API has an arbitrary-file block to point at a URL with. Reading it here would put I/O in the encoder. Fetch it yourself and stage the \`data:\` URI, or paste the contents as a text part.`,
317
- };
318
- }
319
- const decoded = decodeBase64Text(source.data);
320
- if (!decoded.ok) {
321
- return {
322
- status: 'unencodable',
323
- reason: `its media type "${mediaType}" says text, but its bytes are not valid UTF-8 -- so it is binary wearing a text label, and inlining it would send the model garbage. Send it under its real media type, or extract the text yourself.`,
324
- };
325
- }
326
- return {
327
- status: 'encodable',
328
- file: {
329
- kind: 'text',
330
- mediaType,
331
- source,
332
- filename: attachment.filename,
333
- text: decoded.text,
334
- },
335
- };
336
- }
337
-
338
- return {
339
- status: 'encodable',
340
- file: { kind: decision.kind, mediaType, source, filename: attachment.filename },
341
- };
342
- }
@@ -1,274 +0,0 @@
1
- // Anthropic Messages SSE.
2
- //
3
- // This format is STATEFUL. `content_block_delta` names the delta kind
4
- // (`thinking_delta`, `input_json_delta`, ...) but not which block kind the
5
- // fragment belongs to, so the block map is populated at `content_block_start`
6
- // and read on every later event for that index.
7
- //
8
- // It is also the only format in the kit carrying a VERBATIM requirement:
9
- // Anthropic returns 400 if a `thinking` block is modified, reordered or
10
- // reconstructed on the way back in. The block emitted at `content_block_stop`
11
- // is ASSEMBLED, not invented: `thinking` is the concatenation of the provider's
12
- // own thinking_delta payloads and `signature` is the provider's signature_delta,
13
- // so every byte came off the wire. Nothing is derived from the reasoning PART's
14
- // text, which a consumer can edit.
15
- //
16
- // Three of the chunks below carry NO reasoning text (the block start, every
17
- // signature_delta, the block stop). They depend on consume.ts gating reasoning
18
- // on `reasoning !== undefined || reasoningRaw || reasoningSignature` rather than
19
- // on truthiness. Under the old guard all three vanish.
20
- import type { MessageSource } from '../../elements/chat-types';
21
- import type { ModelStreamChunk, ModelUsage, WireFormat, WireFormatReader } from '../chunk';
22
-
23
- function isRecord(v: unknown): v is Record<string, unknown> {
24
- return typeof v === 'object' && v !== null && !Array.isArray(v);
25
- }
26
-
27
- function str(v: unknown): string | undefined {
28
- return typeof v === 'string' ? v : undefined;
29
- }
30
-
31
- function num(v: unknown): number | undefined {
32
- return typeof v === 'number' ? v : undefined;
33
- }
34
-
35
- type BlockKind = 'text' | 'thinking' | 'redacted_thinking' | 'tool_use' | 'other';
36
-
37
- interface BlockState {
38
- kind: BlockKind;
39
- /** Accumulated thinking_delta payloads, for the verbatim block at stop. */
40
- thinking: string;
41
- /** Accumulated signature_delta payloads. */
42
- signature?: string;
43
- }
44
-
45
- function usageOf(raw: unknown): ModelUsage | undefined {
46
- if (!isRecord(raw)) return undefined;
47
- const out: ModelUsage = {};
48
- const input = num(raw.input_tokens);
49
- if (input !== undefined) out.inputTokens = input;
50
- const output = num(raw.output_tokens);
51
- if (output !== undefined) out.outputTokens = output;
52
- const cached = num(raw.cache_read_input_tokens);
53
- if (cached !== undefined) out.cachedInputTokens = cached;
54
- return Object.keys(out).length > 0 ? out : undefined;
55
- }
56
-
57
- function blockStart(
58
- frame: Record<string, unknown>,
59
- blocks: Map<number, BlockState>,
60
- toolIndexById: Map<string, number>,
61
- ): ModelStreamChunk[] {
62
- const index = num(frame.index) ?? 0;
63
- const block = frame.content_block;
64
- if (!isRecord(block)) return [];
65
-
66
- switch (str(block.type)) {
67
- case 'text': {
68
- blocks.set(index, { kind: 'text', thinking: '' });
69
- const text = str(block.text);
70
- return text ? [{ text }] : [];
71
- }
72
- case 'thinking': {
73
- const seed = str(block.thinking) ?? '';
74
- blocks.set(index, { kind: 'thinking', thinking: seed });
75
- // An EMPTY reasoning delta on purpose: it opens the reasoning part at the
76
- // point in the stream where the block started, so block order in `parts`
77
- // matches block order on the wire. The encoder round-trips that order.
78
- return [{ reasoning: seed, reasoningIndex: index }];
79
- }
80
- case 'redacted_thinking': {
81
- blocks.set(index, { kind: 'redacted_thinking', thinking: '' });
82
- // The WHOLE block arrives here; there are no deltas and there is no
83
- // readable text. It must still round-trip: the docs require sending back
84
- // every block "including any blocks with empty thinking fields".
85
- return [
86
- {
87
- reasoning: '',
88
- reasoningIndex: index,
89
- reasoningRaw: { source: 'anthropic.content_block', payload: block },
90
- },
91
- ];
92
- }
93
- case 'tool_use':
94
- case 'server_tool_use': {
95
- const id = str(block.id);
96
- const name = str(block.name);
97
- blocks.set(index, { kind: 'tool_use', thinking: '' });
98
- if (id) toolIndexById.set(id, index);
99
- return [{ toolCalls: [{ index, ...(id ? { id } : {}), ...(name ? { name } : {}) }] }];
100
- }
101
- case 'web_search_tool_result': {
102
- // A result the PROVIDER executed. It correlates by `tool_use_id`, NOT by
103
- // its own block index, so it is routed back to the index of the
104
- // server_tool_use block that opened the call. With no such block the
105
- // result has nothing to complete and is dropped rather than inventing a
106
- // panel.
107
- blocks.set(index, { kind: 'other', thinking: '' });
108
- const toolUseId = str(block.tool_use_id);
109
- const target = toolUseId !== undefined ? toolIndexById.get(toolUseId) : undefined;
110
- if (target === undefined) return [];
111
- const content = block.content;
112
- if (isRecord(content) && (str(content.type) ?? '').endsWith('_error')) {
113
- return [
114
- {
115
- toolCalls: [
116
- {
117
- index: target,
118
- ...(toolUseId ? { id: toolUseId } : {}),
119
- outputError: str(content.error_code) ?? 'web_search_tool_result_error',
120
- },
121
- ],
122
- },
123
- ];
124
- }
125
- return [
126
- {
127
- toolCalls: [
128
- { index: target, ...(toolUseId ? { id: toolUseId } : {}), output: { content } },
129
- ],
130
- },
131
- ];
132
- }
133
- default:
134
- blocks.set(index, { kind: 'other', thinking: '' });
135
- return [];
136
- }
137
- }
138
-
139
- function blockDelta(
140
- frame: Record<string, unknown>,
141
- blocks: Map<number, BlockState>,
142
- ): ModelStreamChunk[] {
143
- const index = num(frame.index) ?? 0;
144
- const delta = frame.delta;
145
- if (!isRecord(delta)) return [];
146
-
147
- switch (str(delta.type)) {
148
- case 'text_delta': {
149
- const text = str(delta.text);
150
- return text ? [{ text }] : [];
151
- }
152
- case 'thinking_delta': {
153
- const text = str(delta.thinking) ?? '';
154
- const state = blocks.get(index);
155
- if (state) state.thinking += text;
156
- return [{ reasoning: text, reasoningIndex: index }];
157
- }
158
- case 'signature_delta': {
159
- const signature = str(delta.signature) ?? '';
160
- const state = blocks.get(index);
161
- // Concatenated rather than assigned: a split signature must reassemble.
162
- if (state) state.signature = (state.signature ?? '') + signature;
163
- // No text. Carried so the part's informational `signature` is populated;
164
- // the round-trip payload lands at content_block_stop.
165
- return [{ reasoning: '', reasoningIndex: index, reasoningSignature: signature }];
166
- }
167
- case 'input_json_delta': {
168
- return [{ toolCalls: [{ index, arguments: str(delta.partial_json) ?? '' }] }];
169
- }
170
- case 'citations_delta': {
171
- const citation = delta.citation;
172
- if (!isRecord(citation)) return [];
173
- const source: MessageSource = {};
174
- const url = str(citation.url);
175
- if (url) source.url = url;
176
- const title = str(citation.title);
177
- if (title) source.title = title;
178
- const snippet = str(citation.cited_text);
179
- if (snippet) source.snippet = snippet;
180
- return Object.keys(source).length > 0 ? [{ sources: [source] }] : [];
181
- }
182
- default:
183
- return [];
184
- }
185
- }
186
-
187
- function blockStop(
188
- frame: Record<string, unknown>,
189
- blocks: Map<number, BlockState>,
190
- ): ModelStreamChunk[] {
191
- const index = num(frame.index) ?? 0;
192
- const state = blocks.get(index);
193
- // Only a streamed `thinking` block needs assembling. `redacted_thinking`
194
- // already emitted its whole payload at start, and text and tool blocks have
195
- // no verbatim requirement.
196
- if (!state || state.kind !== 'thinking') return [];
197
- const payload: Record<string, unknown> = { type: 'thinking', thinking: state.thinking };
198
- if (state.signature !== undefined) payload.signature = state.signature;
199
- return [
200
- {
201
- reasoning: '',
202
- reasoningIndex: index,
203
- reasoningRaw: { source: 'anthropic.content_block', payload },
204
- },
205
- ];
206
- }
207
-
208
- function messageDelta(frame: Record<string, unknown>): ModelStreamChunk[] {
209
- const out: ModelStreamChunk = {};
210
- const delta = frame.delta;
211
- if (isRecord(delta)) {
212
- const stop = str(delta.stop_reason);
213
- if (stop) out.finishReason = stop;
214
- }
215
- const usage = usageOf(frame.usage);
216
- if (usage) out.usage = usage;
217
- return Object.keys(out).length > 0 ? [out] : [];
218
- }
219
-
220
- function errorFrame(frame: Record<string, unknown>): ModelStreamChunk[] {
221
- const err = frame.error;
222
- const message = isRecord(err) ? str(err.message) : undefined;
223
- const code = isRecord(err) ? str(err.type) : undefined;
224
- return [
225
- {
226
- error: {
227
- message: message ?? 'The provider sent an error frame with no message.',
228
- ...(code ? { code } : {}),
229
- },
230
- },
231
- ];
232
- }
233
-
234
- export const anthropicMessagesFormat: WireFormat = {
235
- id: 'anthropic.messages',
236
- open(): WireFormatReader {
237
- // Per-stream state, created HERE so two open() calls share nothing.
238
- const blocks = new Map<number, BlockState>();
239
- const toolIndexById = new Map<string, number>();
240
- return {
241
- push(frame: unknown): ModelStreamChunk[] {
242
- if (!isRecord(frame)) return [];
243
- switch (str(frame.type)) {
244
- case 'message_start': {
245
- const message = frame.message;
246
- if (!isRecord(message)) return [];
247
- // `message.model` sits right beside the `message.usage` this handler
248
- // already destructures. Anthropic states it once, here, and nowhere
249
- // else in the stream.
250
- const out: ModelStreamChunk = {};
251
- const usage = usageOf(message.usage);
252
- if (usage) out.usage = usage;
253
- const model = str(message.model);
254
- if (model) out.model = model;
255
- return Object.keys(out).length > 0 ? [out] : [];
256
- }
257
- case 'content_block_start':
258
- return blockStart(frame, blocks, toolIndexById);
259
- case 'content_block_delta':
260
- return blockDelta(frame, blocks);
261
- case 'content_block_stop':
262
- return blockStop(frame, blocks);
263
- case 'message_delta':
264
- return messageDelta(frame);
265
- case 'error':
266
- return errorFrame(frame);
267
- default:
268
- // ping, message_stop, and anything Anthropic adds later.
269
- return [];
270
- }
271
- },
272
- };
273
- },
274
- };