@kitn.ai/ui 0.27.0 → 0.29.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 (612) hide show
  1. package/README.md +10 -2
  2. package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
  3. package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.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-CjRU3JgV.js +1 -0
  7. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  8. package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
  9. package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
  10. package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
  11. package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
  12. package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
  13. package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
  14. package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
  15. package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
  16. package/dist/check-njkVdZu2.js +1 -0
  17. package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
  18. package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
  19. package/dist/chevron-down-B72s6PXR.js +1 -0
  20. package/dist/chevron-right-BatuHzUm.js +1 -0
  21. package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
  22. package/dist/circle-check-B62pODB3.js +1 -0
  23. package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
  24. package/dist/circle-zx0ByzY9.js +1 -0
  25. package/dist/code-block-ClMLKb7C.js +1 -0
  26. package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
  27. package/dist/components/chat-thread.d.ts +89 -1
  28. package/dist/components/conversation-item.d.ts +16 -0
  29. package/dist/components/conversation-panel.d.ts +29 -0
  30. package/dist/components/home-panel.d.ts +34 -0
  31. package/dist/components/widget-tab-bar.d.ts +16 -0
  32. package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
  33. package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
  34. package/dist/construct-cli.es.js +185 -17
  35. package/dist/construct.d.ts +5 -0
  36. package/dist/construct.js +327 -0
  37. package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
  38. package/dist/controllable-CnGpMF6r.js +1 -0
  39. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  40. package/dist/conversation-list-BCfGN1JU.js +1 -0
  41. package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
  42. package/dist/core-C8fzo39E.js +1 -12
  43. package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
  44. package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
  45. package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
  46. package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
  47. package/dist/custom-elements.json +51 -2
  48. package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
  49. package/dist/define-By-uL588.js +1 -0
  50. package/dist/define.js +2 -2
  51. package/dist/define.server.js +2 -2
  52. package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
  53. package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.js} +1 -1
  54. package/dist/elements/agent-card.js +1 -1
  55. package/dist/elements/artifact.js +1 -1
  56. package/dist/elements/attachments.js +1 -1
  57. package/dist/elements/audio-visualizer.js +1 -1
  58. package/dist/elements/avatar.js +1 -1
  59. package/dist/elements/badge.js +1 -1
  60. package/dist/elements/button.js +1 -1
  61. package/dist/elements/card.js +1 -1
  62. package/dist/elements/cards.js +1 -1
  63. package/dist/elements/chain-of-thought.js +1 -1
  64. package/dist/elements/chat-scope-picker.js +1 -1
  65. package/dist/elements/chat-workspace.js +1 -1
  66. package/dist/elements/chat.js +1 -1
  67. package/dist/elements/checkbox-group.js +1 -1
  68. package/dist/elements/checkbox.js +1 -1
  69. package/dist/elements/checkpoint.js +1 -1
  70. package/dist/elements/choice.js +1 -1
  71. package/dist/elements/coachmark.js +1 -1
  72. package/dist/elements/code-block.js +1 -1
  73. package/dist/elements/command.js +1 -1
  74. package/dist/elements/compare.js +1 -1
  75. package/dist/elements/composer.js +1 -1
  76. package/dist/elements/confirm-card.js +1 -1
  77. package/dist/elements/context-meter.js +1 -1
  78. package/dist/elements/conversation-item.js +1 -1
  79. package/dist/elements/conversation-list.js +1 -1
  80. package/dist/elements/dialog.js +1 -1
  81. package/dist/elements/dock.js +3 -3
  82. package/dist/elements/dropdown.js +1 -1
  83. package/dist/elements/editable-label.js +1 -1
  84. package/dist/elements/embed.js +1 -1
  85. package/dist/elements/empty.js +1 -1
  86. package/dist/elements/feedback-bar.js +1 -1
  87. package/dist/elements/file-tree.js +1 -1
  88. package/dist/elements/file-upload.js +1 -1
  89. package/dist/elements/form.js +1 -1
  90. package/dist/elements/hover-card.js +1 -1
  91. package/dist/elements/icon.js +1 -1
  92. package/dist/elements/image.js +1 -1
  93. package/dist/elements/input.js +1 -1
  94. package/dist/elements/kbd.js +1 -1
  95. package/dist/elements/link-preview.js +1 -1
  96. package/dist/elements/loader.js +1 -1
  97. package/dist/elements/markdown.js +1 -1
  98. package/dist/elements/menu.js +1 -1
  99. package/dist/elements/message-skills.js +1 -1
  100. package/dist/elements/message.js +1 -1
  101. package/dist/elements/model-switcher.js +1 -1
  102. package/dist/elements/nav.js +1 -1
  103. package/dist/elements/notice.js +1 -1
  104. package/dist/elements/pane-grid.js +1 -1
  105. package/dist/elements/pane-group.js +1 -1
  106. package/dist/elements/pane.js +1 -1
  107. package/dist/elements/popover.js +1 -1
  108. package/dist/elements/progress-bar.js +1 -1
  109. package/dist/elements/prompt-dock.js +1 -1
  110. package/dist/elements/prompt-input.js +1 -1
  111. package/dist/elements/prompt-suggestions.js +1 -1
  112. package/dist/elements/radio-group.js +1 -1
  113. package/dist/elements/reasoning.js +1 -1
  114. package/dist/elements/remote.js +1 -1
  115. package/dist/elements/resizable.js +1 -1
  116. package/dist/elements/response-stream.js +1 -1
  117. package/dist/elements/screen.js +1 -1
  118. package/dist/elements/scroll-area.js +1 -1
  119. package/dist/elements/scroll-button.js +1 -1
  120. package/dist/elements/search.js +1 -1
  121. package/dist/elements/segmented.js +1 -1
  122. package/dist/elements/select.js +1 -1
  123. package/dist/elements/separator.js +1 -1
  124. package/dist/elements/setting-item.js +1 -1
  125. package/dist/elements/settings-group.js +1 -1
  126. package/dist/elements/skeleton.js +1 -1
  127. package/dist/elements/slider.js +1 -1
  128. package/dist/elements/source.js +1 -1
  129. package/dist/elements/status.js +1 -1
  130. package/dist/elements/switch.js +1 -1
  131. package/dist/elements/tabs.js +1 -1
  132. package/dist/elements/tasks.js +1 -1
  133. package/dist/elements/text-shimmer.js +1 -1
  134. package/dist/elements/thinking-bar.js +1 -1
  135. package/dist/elements/thread.js +1 -1
  136. package/dist/elements/toast.js +1 -1
  137. package/dist/elements/tool.js +1 -1
  138. package/dist/elements/tooltip.js +1 -1
  139. package/dist/elements/voice-input.js +1 -1
  140. package/dist/elements/voice-output.js +1 -1
  141. package/dist/elements.d.ts +20 -4
  142. package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
  143. package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
  144. package/dist/engine-javascript-C1x7zo1_.js +1 -141
  145. package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
  146. package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
  147. package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
  148. package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
  149. package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
  150. package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
  151. package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
  152. package/dist/index.d.ts +3 -1
  153. package/dist/index.js +2842 -2703
  154. package/dist/index.server.js +2820 -2681
  155. package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
  156. package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
  157. package/dist/kai.es.js +1 -1
  158. package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
  159. package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
  160. package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
  161. package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
  162. package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
  163. package/dist/mcp.es.js +79 -5
  164. package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
  165. package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
  166. package/dist/message-circle-DruwObfX.js +1 -0
  167. package/dist/message-square-BG6q6mlm.js +1 -0
  168. package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
  169. package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
  170. package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
  171. package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
  172. package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
  173. package/dist/play-BvKKq3fX.js +1 -0
  174. package/dist/primitives/conversation-store.d.ts +54 -0
  175. package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
  176. package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
  177. package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
  178. package/dist/react/index.d.ts +393 -0
  179. package/dist/react.js +20 -20
  180. package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
  181. package/dist/register-impl-B1hLkrI8.js +424 -0
  182. package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
  183. package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
  184. package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
  185. package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
  186. package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
  187. package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
  188. package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
  189. package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
  190. package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
  191. package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
  192. package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
  193. package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
  194. package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
  195. package/dist/solid.d.ts +6 -2
  196. package/dist/solid.js +217 -210
  197. package/dist/solid.server.js +217 -210
  198. package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
  199. package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
  200. package/dist/store-Ciyk6eZG.js +1 -0
  201. package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
  202. package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
  203. package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
  204. package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
  205. package/dist/theme.tokens.css +28 -0
  206. package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
  207. package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
  208. package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
  209. package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
  210. package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
  211. package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
  212. package/dist/types.d.ts +48 -3
  213. package/dist/ui/dock.d.ts +29 -0
  214. package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
  215. package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
  216. package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
  217. package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
  218. package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
  219. package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
  220. package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
  221. package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
  222. package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
  223. package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
  224. package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
  225. package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
  226. package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
  227. package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
  228. package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
  229. package/dist/x-Z5UntkIJ.js +1 -0
  230. package/frameworks/react/index.tsx +14 -4
  231. package/llms-full.txt +7 -2
  232. package/package.json +16 -16
  233. package/src/elements/element-meta.json +49 -6
  234. package/theme.css +28 -0
  235. package/bin/route.test.js +0 -58
  236. package/dist/arrow-down-Br0qtpsz.js +0 -1
  237. package/dist/arrow-left-Dj7xgE12.js +0 -1
  238. package/dist/check-DPeeMUYx.js +0 -1
  239. package/dist/chevron-down-CHSWk7ZT.js +0 -1
  240. package/dist/chevron-right-B7l_fMgx.js +0 -1
  241. package/dist/circle-Bb0yOpqM.js +0 -1
  242. package/dist/circle-check-BGZpCiz7.js +0 -1
  243. package/dist/code-block-CUQ5mtv0.js +0 -1
  244. package/dist/controllable-D43BKmtX.js +0 -1
  245. package/dist/conversation-list-D4lLU_yS.js +0 -1
  246. package/dist/define-CGGX-7Vg.js +0 -1
  247. package/dist/message-circle-Xf8Q-vZp.js +0 -1
  248. package/dist/message-square-Cxnwgkns.js +0 -1
  249. package/dist/play-OFIvYXUQ.js +0 -1
  250. package/dist/register-impl-C7rENvPK.js +0 -424
  251. package/dist/store-7eoadydQ.js +0 -1
  252. package/dist/x-C5m1JFgi.js +0 -1
  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 -131
  263. package/src/agent-tooling/construct/codegen.ts +0 -1353
  264. package/src/agent-tooling/construct/construct.v1.schema.json +0 -250
  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 -23
  269. package/src/agent-tooling/construct/schema.ts +0 -371
  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 -518
  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 -218
  336. package/src/components/conversation-list.tsx +0 -429
  337. package/src/components/dismissed-stub.tsx +0 -80
  338. package/src/components/embed.tsx +0 -200
  339. package/src/components/empty.tsx +0 -177
  340. package/src/components/feedback-bar.tsx +0 -166
  341. package/src/components/file-tree.tsx +0 -530
  342. package/src/components/file-upload.tsx +0 -167
  343. package/src/components/form-widgets.tsx +0 -525
  344. package/src/components/form.tsx +0 -1296
  345. package/src/components/image.tsx +0 -65
  346. package/src/components/link-preview.tsx +0 -195
  347. package/src/components/loader.tsx +0 -367
  348. package/src/components/markdown.tsx +0 -162
  349. package/src/components/message-skills.tsx +0 -40
  350. package/src/components/message.tsx +0 -765
  351. package/src/components/model-switcher.tsx +0 -132
  352. package/src/components/prompt-input.tsx +0 -188
  353. package/src/components/prompt-suggestion.tsx +0 -150
  354. package/src/components/reasoning.tsx +0 -293
  355. package/src/components/response-compare-types.ts +0 -152
  356. package/src/components/response-compare.tsx +0 -455
  357. package/src/components/response-stream.tsx +0 -109
  358. package/src/components/screen.tsx +0 -181
  359. package/src/components/scroll-button.tsx +0 -93
  360. package/src/components/source.tsx +0 -192
  361. package/src/components/tasks-card.tsx +0 -801
  362. package/src/components/text-shimmer.tsx +0 -37
  363. package/src/components/thinking-bar.tsx +0 -50
  364. package/src/components/thread.tsx +0 -228
  365. package/src/components/toast.tsx +0 -503
  366. package/src/components/tool-classify.ts +0 -26
  367. package/src/components/tool-types.ts +0 -49
  368. package/src/components/tool.tsx +0 -190
  369. package/src/components/use-card-resolution.ts +0 -44
  370. package/src/components/voice-input.tsx +0 -222
  371. package/src/components/voice-output.tsx +0 -242
  372. package/src/components/workspace-shell.tsx +0 -285
  373. package/src/diagnostics/hook.ts +0 -352
  374. package/src/diagnostics/index.ts +0 -82
  375. package/src/diagnostics/report-request.ts +0 -296
  376. package/src/elements/agent-card.tsx +0 -67
  377. package/src/elements/artifact.tsx +0 -194
  378. package/src/elements/attachments.tsx +0 -140
  379. package/src/elements/audio-visualizer.tsx +0 -227
  380. package/src/elements/autoloader.ts +0 -89
  381. package/src/elements/avatar.tsx +0 -33
  382. package/src/elements/badge.tsx +0 -32
  383. package/src/elements/button.tsx +0 -149
  384. package/src/elements/card.tsx +0 -133
  385. package/src/elements/cards.tsx +0 -266
  386. package/src/elements/chain-of-thought.tsx +0 -141
  387. package/src/elements/chat-scope-picker.tsx +0 -65
  388. package/src/elements/chat-types.ts +0 -102
  389. package/src/elements/chat-workspace.tsx +0 -188
  390. package/src/elements/chat.tsx +0 -212
  391. package/src/elements/checkbox-group.tsx +0 -164
  392. package/src/elements/checkbox.tsx +0 -134
  393. package/src/elements/checkpoint.tsx +0 -47
  394. package/src/elements/choice.tsx +0 -100
  395. package/src/elements/coachmark.tsx +0 -90
  396. package/src/elements/code-block.tsx +0 -60
  397. package/src/elements/command.tsx +0 -197
  398. package/src/elements/compare.tsx +0 -111
  399. package/src/elements/compiled.css +0 -2
  400. package/src/elements/composer.tsx +0 -162
  401. package/src/elements/confirm-card.tsx +0 -76
  402. package/src/elements/context-meter.tsx +0 -107
  403. package/src/elements/conversation-item.tsx +0 -120
  404. package/src/elements/conversation-list.tsx +0 -203
  405. package/src/elements/css.ts +0 -5
  406. package/src/elements/default-input.tsx +0 -392
  407. package/src/elements/define-entry.ts +0 -12
  408. package/src/elements/define.tsx +0 -563
  409. package/src/elements/diagnostic-events.ts +0 -114
  410. package/src/elements/dialog.tsx +0 -145
  411. package/src/elements/disclosure.ts +0 -95
  412. package/src/elements/dock.tsx +0 -215
  413. package/src/elements/dropdown.tsx +0 -123
  414. package/src/elements/editable-label.tsx +0 -140
  415. package/src/elements/element-data-types.ts +0 -152
  416. package/src/elements/element-diagnostics.ts +0 -392
  417. package/src/elements/element-manifest.json +0 -354
  418. package/src/elements/element-nonscalar.json +0 -185
  419. package/src/elements/element-types.d.ts +0 -4337
  420. package/src/elements/embed.tsx +0 -35
  421. package/src/elements/empty.tsx +0 -29
  422. package/src/elements/feedback-bar.tsx +0 -66
  423. package/src/elements/file-tree.tsx +0 -62
  424. package/src/elements/file-upload.tsx +0 -44
  425. package/src/elements/form.tsx +0 -94
  426. package/src/elements/hover-card.tsx +0 -80
  427. package/src/elements/icon.tsx +0 -41
  428. package/src/elements/image.tsx +0 -32
  429. package/src/elements/input.tsx +0 -492
  430. package/src/elements/kbd.tsx +0 -45
  431. package/src/elements/link-preview.tsx +0 -34
  432. package/src/elements/loader.tsx +0 -25
  433. package/src/elements/markdown.tsx +0 -38
  434. package/src/elements/menu.tsx +0 -241
  435. package/src/elements/message-skills.tsx +0 -83
  436. package/src/elements/message.tsx +0 -361
  437. package/src/elements/model-switcher.tsx +0 -121
  438. package/src/elements/nav.tsx +0 -87
  439. package/src/elements/notice.tsx +0 -53
  440. package/src/elements/pane-grid.tsx +0 -111
  441. package/src/elements/pane-group.tsx +0 -119
  442. package/src/elements/pane.tsx +0 -129
  443. package/src/elements/popover.tsx +0 -81
  444. package/src/elements/progress-bar.tsx +0 -39
  445. package/src/elements/prompt-dock.tsx +0 -82
  446. package/src/elements/prompt-input.tsx +0 -240
  447. package/src/elements/prompt-suggestions.tsx +0 -113
  448. package/src/elements/radio-group.tsx +0 -129
  449. package/src/elements/reasoning.tsx +0 -71
  450. package/src/elements/register-impl.ts +0 -148
  451. package/src/elements/register.ts +0 -76
  452. package/src/elements/remote.tsx +0 -225
  453. package/src/elements/resizable.globals.d.ts +0 -36
  454. package/src/elements/resizable.tsx +0 -704
  455. package/src/elements/response-stream.tsx +0 -40
  456. package/src/elements/screen.tsx +0 -90
  457. package/src/elements/scroll-area.tsx +0 -33
  458. package/src/elements/scroll-button.tsx +0 -179
  459. package/src/elements/search.tsx +0 -185
  460. package/src/elements/segmented.tsx +0 -129
  461. package/src/elements/select.tsx +0 -165
  462. package/src/elements/separator.tsx +0 -36
  463. package/src/elements/setting-item.tsx +0 -50
  464. package/src/elements/settings-group.tsx +0 -37
  465. package/src/elements/skeleton.tsx +0 -45
  466. package/src/elements/slider.tsx +0 -171
  467. package/src/elements/slot-text.ts +0 -73
  468. package/src/elements/slots.ts +0 -787
  469. package/src/elements/source.tsx +0 -126
  470. package/src/elements/status.tsx +0 -42
  471. package/src/elements/styles.css +0 -328
  472. package/src/elements/switch.tsx +0 -118
  473. package/src/elements/tabs.tsx +0 -95
  474. package/src/elements/tasks.tsx +0 -103
  475. package/src/elements/text-shimmer.tsx +0 -28
  476. package/src/elements/thinking-bar.tsx +0 -43
  477. package/src/elements/thread.tsx +0 -139
  478. package/src/elements/toast.tsx +0 -106
  479. package/src/elements/tool.tsx +0 -78
  480. package/src/elements/tooltip.tsx +0 -85
  481. package/src/elements/validate-messages.ts +0 -76
  482. package/src/elements/voice-input.tsx +0 -100
  483. package/src/elements/voice-output.tsx +0 -82
  484. package/src/index.ts +0 -428
  485. package/src/primitives/audio-bands.ts +0 -174
  486. package/src/primitives/card-component-types.ts +0 -63
  487. package/src/primitives/card-contract.ts +0 -80
  488. package/src/primitives/card-data-types.ts +0 -361
  489. package/src/primitives/card-host.tsx +0 -37
  490. package/src/primitives/card-recovery.ts +0 -160
  491. package/src/primitives/card-registry.tsx +0 -78
  492. package/src/primitives/card-resolution.ts +0 -36
  493. package/src/primitives/card-routing.ts +0 -85
  494. package/src/primitives/card-schemas/artifact.schema.json +0 -92
  495. package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
  496. package/src/primitives/card-schemas/card-event.schema.json +0 -12
  497. package/src/primitives/card-schemas/choice.schema.json +0 -75
  498. package/src/primitives/card-schemas/confirm.schema.json +0 -65
  499. package/src/primitives/card-schemas/embed.schema.json +0 -63
  500. package/src/primitives/card-schemas/form.result.schema.json +0 -7
  501. package/src/primitives/card-schemas/form.schema.json +0 -53
  502. package/src/primitives/card-schemas/link.schema.json +0 -54
  503. package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
  504. package/src/primitives/card-schemas/tasks.schema.json +0 -83
  505. package/src/primitives/card-tags.ts +0 -61
  506. package/src/primitives/card-validate-cards.ts +0 -255
  507. package/src/primitives/card-validate-schemas.ts +0 -58
  508. package/src/primitives/card-validate.ts +0 -131
  509. package/src/primitives/chat-config.tsx +0 -103
  510. package/src/primitives/composer-model.ts +0 -49
  511. package/src/primitives/composer-triggers.ts +0 -35
  512. package/src/primitives/controllable.ts +0 -21
  513. package/src/primitives/create-kai-chat.ts +0 -66
  514. package/src/primitives/create-tween.ts +0 -266
  515. package/src/primitives/embed-providers.ts +0 -254
  516. package/src/primitives/field-mask.ts +0 -256
  517. package/src/primitives/field-semantics.ts +0 -115
  518. package/src/primitives/highlighter.ts +0 -157
  519. package/src/primitives/input-mask.ts +0 -853
  520. package/src/primitives/link-preview.ts +0 -87
  521. package/src/primitives/message-feedback.ts +0 -124
  522. package/src/primitives/pdf-preview.ts +0 -121
  523. package/src/primitives/toast-store.ts +0 -338
  524. package/src/primitives/url-scheme-policy.ts +0 -70
  525. package/src/primitives/use-audio-analysis.ts +0 -340
  526. package/src/primitives/use-auto-resize.ts +0 -31
  527. package/src/primitives/use-resize-observer.ts +0 -45
  528. package/src/primitives/use-sequencer.ts +0 -72
  529. package/src/primitives/use-speech-recognition.ts +0 -146
  530. package/src/primitives/use-stick-to-bottom.ts +0 -75
  531. package/src/primitives/use-text-stream.ts +0 -143
  532. package/src/primitives/use-voice-recorder.ts +0 -62
  533. package/src/primitives/visualizer-sequences.ts +0 -350
  534. package/src/remote/host-embed.ts +0 -345
  535. package/src/remote/index.ts +0 -2
  536. package/src/remote/origin.ts +0 -30
  537. package/src/remote/provider-runtime.ts +0 -262
  538. package/src/remote/provider.ts +0 -2
  539. package/src/remote/validate.ts +0 -22
  540. package/src/remote/version.ts +0 -12
  541. package/src/remote/wire.ts +0 -48
  542. package/src/schemas/from-tool-call.ts +0 -151
  543. package/src/schemas/index.ts +0 -341
  544. package/src/schemas/provider-subsets.ts +0 -538
  545. package/src/schemas/registry.ts +0 -355
  546. package/src/schemas/tool-defs.ts +0 -793
  547. package/src/solid.ts +0 -165
  548. package/src/state/index.ts +0 -44
  549. package/src/state/messages.ts +0 -53
  550. package/src/state/mock.ts +0 -297
  551. package/src/state/parts.ts +0 -295
  552. package/src/state/persistence.ts +0 -180
  553. package/src/state/stream.ts +0 -246
  554. package/src/state/suggestions.ts +0 -9
  555. package/src/state/threads.ts +0 -142
  556. package/src/test-utils/fake-clock.ts +0 -88
  557. package/src/types.ts +0 -53
  558. package/src/ui/action-icons.ts +0 -53
  559. package/src/ui/agent-card.tsx +0 -218
  560. package/src/ui/avatar.tsx +0 -23
  561. package/src/ui/badge.tsx +0 -21
  562. package/src/ui/button.tsx +0 -49
  563. package/src/ui/card.tsx +0 -245
  564. package/src/ui/checkbox-group.tsx +0 -153
  565. package/src/ui/checkbox.tsx +0 -63
  566. package/src/ui/collapsible.tsx +0 -163
  567. package/src/ui/command.tsx +0 -103
  568. package/src/ui/dialog.tsx +0 -223
  569. package/src/ui/dock.tsx +0 -584
  570. package/src/ui/dropdown.tsx +0 -636
  571. package/src/ui/editable-label.tsx +0 -112
  572. package/src/ui/hover-card.tsx +0 -345
  573. package/src/ui/icon.tsx +0 -167
  574. package/src/ui/input.tsx +0 -391
  575. package/src/ui/kbd.tsx +0 -118
  576. package/src/ui/nav.tsx +0 -282
  577. package/src/ui/notice.tsx +0 -84
  578. package/src/ui/overlay.tsx +0 -277
  579. package/src/ui/pane-grid.tsx +0 -117
  580. package/src/ui/pane-group.tsx +0 -291
  581. package/src/ui/pane.tsx +0 -193
  582. package/src/ui/popover.tsx +0 -106
  583. package/src/ui/progress-bar.tsx +0 -83
  584. package/src/ui/prompt-dock.tsx +0 -145
  585. package/src/ui/radio.tsx +0 -150
  586. package/src/ui/resizable.tsx +0 -693
  587. package/src/ui/scroll-area.tsx +0 -26
  588. package/src/ui/segmented.tsx +0 -109
  589. package/src/ui/select.tsx +0 -168
  590. package/src/ui/separator.tsx +0 -10
  591. package/src/ui/settings-group.tsx +0 -67
  592. package/src/ui/skeleton.tsx +0 -73
  593. package/src/ui/slider.tsx +0 -178
  594. package/src/ui/status.tsx +0 -48
  595. package/src/ui/switch.tsx +0 -119
  596. package/src/ui/tabs.tsx +0 -168
  597. package/src/ui/textarea.tsx +0 -21
  598. package/src/ui/tooltip.tsx +0 -118
  599. package/src/utils/cn.ts +0 -30
  600. package/src/wire/chunk.ts +0 -248
  601. package/src/wire/consume.ts +0 -599
  602. package/src/wire/diagnostics.ts +0 -727
  603. package/src/wire/encode-probe.ts +0 -214
  604. package/src/wire/encode.ts +0 -947
  605. package/src/wire/files.ts +0 -342
  606. package/src/wire/formats/anthropic.ts +0 -274
  607. package/src/wire/formats/openai.ts +0 -228
  608. package/src/wire/index.ts +0 -95
  609. package/src/wire/media-types.ts +0 -344
  610. package/src/wire/read.ts +0 -396
  611. package/src/wire/sink-helpers.ts +0 -50
  612. 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
- };