@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
@@ -1,133 +0,0 @@
1
- import type { Integration } from '../types';
2
-
3
- const langgraph: Integration = {
4
- id: 'langgraph',
5
- title: 'LangGraph',
6
- category: 'framework',
7
- language: 'ts',
8
- streamFormat: 'openai-sse',
9
- envVars: ['OPENAI_API_KEY'],
10
- // No per-framework templates: the handler below is web-standard, so the
11
- // scaffolder wraps it in the target framework's own route declaration.
12
- routeTemplates: {},
13
- webRoute: `import { createReactAgent } from '@langchain/langgraph/prebuilt';
14
- import { ChatOpenAI } from '@langchain/openai';
15
- import { tool } from '@langchain/core/tools';
16
- import { z } from 'zod';
17
-
18
- const getWeather = tool(
19
- async ({ city }) => \`It's 18°C and clear in \${city}.\`,
20
- {
21
- name: 'get_weather',
22
- description: 'Get the current weather for a city.',
23
- schema: z.object({ city: z.string() }),
24
- },
25
- );
26
-
27
- const agent = createReactAgent({
28
- llm: new ChatOpenAI({ model: 'gpt-4o' }),
29
- tools: [getWeather],
30
- });
31
-
32
- // Stream a compiled LangGraph agent to the browser as OpenAI-format SSE.
33
- async function chatHandler(request: Request): Promise<Response> {
34
- let chatBody: ChatRequestBody;
35
- try {
36
- chatBody = await readChatRequest(request);
37
- } catch (error) {
38
- return toChatErrorResponse(error);
39
- }
40
- const { messages } = chatBody;
41
-
42
- // agent.stream() coerces plain {role, content} objects into BaseMessage
43
- // instances itself, including OpenAI-shaped tool_calls, so the wire messages
44
- // can be passed through almost as-is. The one incompatible bit is content:
45
- // OpenAI represents a tool-calls-only assistant turn as content: null, and
46
- // LangChain's MessageContent type (and runtime coercion) only accepts string.
47
- const agentMessages = messages.map((m) => ({ ...m, content: m.content ?? '' }));
48
-
49
- // Let TS infer the stream's element type from this call instead of hand
50
- // writing it: the real type is a [BaseMessage, metadata] tuple, keyed off the
51
- // streamMode: 'messages' literal, not the plain object shape it looks like.
52
- const startStream = () => agent.stream({ messages: agentMessages }, { streamMode: 'messages' });
53
-
54
- let stream: Awaited<ReturnType<typeof startStream>>;
55
- try {
56
- stream = await startStream();
57
- } catch (err) {
58
- // A REAL status, before a byte is streamed: a missing OPENAI_API_KEY fails
59
- // here. Returning 200 would send this JSON out labelled text/event-stream,
60
- // the SSE reader would find no frame, and the turn would resolve empty with
61
- // nothing logged and no bubble.
62
- return new Response(
63
- JSON.stringify({ error: { message: err instanceof Error ? err.message : 'Agent failed to start' } }),
64
- { status: 502, headers: { 'Content-Type': 'application/json' } },
65
- );
66
- }
67
-
68
- const encoder = new TextEncoder();
69
- const body = new ReadableStream({
70
- async start(controller) {
71
- const send = (obj: unknown) =>
72
- controller.enqueue(encoder.encode(\`data: \${JSON.stringify(obj)}\\n\\n\`));
73
-
74
- try {
75
- for await (const [chunk] of stream) {
76
- if (typeof chunk.content === 'string' && chunk.content) {
77
- send({ choices: [{ delta: { content: chunk.content } }] });
78
- }
79
- }
80
- } catch (err) {
81
- // The status is spent once the stream started, so report IN BAND:
82
- // readOpenAIStream lands this on turn.error and keeps what streamed.
83
- send({ error: { message: err instanceof Error ? err.message : 'Agent stream failed' } });
84
- }
85
- controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));
86
- controller.close();
87
- },
88
- });
89
-
90
- return new Response(body, {
91
- status: 200,
92
- headers: {
93
- 'Content-Type': 'text/event-stream; charset=utf-8',
94
- // no-transform stops a proxy buffering the stream into one blob.
95
- 'Cache-Control': 'no-cache, no-transform',
96
- Connection: 'keep-alive',
97
- },
98
- });
99
- }`,
100
- streamMapping: "Use graph.stream(input, { streamMode: 'messages' }) to get [messageChunk, metadata] tuples. Extract chunk.content (string) and forward as OpenAI-format SSE frames: data: {choices:[{delta:{content}}]}. Close with data: [DONE]. readOpenAIStream from @kitn.ai/ui/wire parses tool calls and reasoning too, but the route template forwards chunk.content only, which is text: the same message chunks carry the tool-call fragments on chunk.tool_call_chunks, so re-frame those onto delta.tool_calls to fill kai-tool.",
101
- // No install list here: `deps` below is the one, and the scaffolder emits it.
102
- // This sentence used to end "Install @langchain/langgraph, @langchain/openai,
103
- // @langchain/core." — three of the four packages, for as long as nobody was
104
- // comparing it to anything.
105
- runNote: 'Set OPENAI_API_KEY (or the key for your chosen model provider).',
106
- docsSlug: 'integrations/langgraph',
107
- // Nothing. The agent owns both: ChatOpenAI({ model: 'gpt-4o' }) and the tools
108
- // array passed to createReactAgent are server-side.
109
- forwardsFromClient: [],
110
- // Four, one per import in the route above. `zod` is the one the deleted prose
111
- // forgot: the tool's `schema:` is a z.object(), so an app installed from that
112
- // sentence alone fails to build. Deriving this from the imports rather than
113
- // from a sentence is the point of the field.
114
- deps: { npm: ['@langchain/langgraph', '@langchain/openai', '@langchain/core', 'zod'], pip: [] },
115
- // No key appears in the route: `new ChatOpenAI(...)` reads OPENAI_API_KEY from
116
- // the environment itself. Same invisible-key shape as vercel-ai-sdk.
117
- keyExposure: 'needs-proxy',
118
- // 'none', and this is the entry most likely to be "corrected" to something
119
- // else, so the reason is here rather than assumed. The create-kai spec lists
120
- // LangGraph under "Bring a server or runtime". That is WRONG for this route:
121
- // the graph is built and compiled IN PROCESS above (`createReactAgent` over a
122
- // `new ChatOpenAI(...)`), so there is no LangGraph server, no port and no
123
- // second process — the four packages in `deps` are the whole install and
124
- // `runNote` asks for a key and nothing else.
125
- //
126
- // LangGraph Platform / `langgraph dev` IS a server, and an integration that
127
- // talked to one over HTTP would be 'local-server'. That is a different route
128
- // than the one above, and if it is ever added it must be added as its own
129
- // catalog entry rather than by changing this line.
130
- outOfBand: 'none',
131
- };
132
-
133
- export default langgraph;
@@ -1,182 +0,0 @@
1
- import type { Integration } from '../types';
2
-
3
- const mastra: Integration = {
4
- id: 'mastra',
5
- title: 'Mastra',
6
- category: 'harness',
7
- language: 'ts',
8
- streamFormat: 'openai-sse',
9
- envVars: ['MASTRA_URL'],
10
- // No per-framework templates. The old `express` entry was a fragment, not a
11
- // route: it referenced `messages` and `res` without declaring either, and
12
- // every non-express framework inherited it anyway. The handler below is
13
- // web-standard, so the scaffolder wraps it per framework.
14
- routeTemplates: {},
15
- webRoute: `import { MastraClient } from '@mastra/client-js';
16
-
17
- // MASTRA_URL is required, not defaulted to localhost: a deployed consumer app
18
- // that forgets to set it would otherwise construct a client that silently
19
- // points a production Worker/serverless function at 127.0.0.1, then fail deep
20
- // inside a fetch call with a confusing connection error. Failing at import
21
- // time, with a message that names the fix, is louder and cheaper to debug.
22
- const MASTRA_URL = process.env.MASTRA_URL;
23
- if (!MASTRA_URL) {
24
- throw new Error('MASTRA_URL is not set. Point it at your Mastra server, e.g. http://localhost:4111 for \`mastra dev\`.');
25
- }
26
-
27
- const mastra = new MastraClient({ baseUrl: MASTRA_URL });
28
-
29
- // Proxy a Mastra agent to the browser as OpenAI-format SSE.
30
- async function chatHandler(request: Request): Promise<Response> {
31
- let chatBody: ChatRequestBody;
32
- try {
33
- chatBody = await readChatRequest(request);
34
- } catch (error) {
35
- return toChatErrorResponse(error);
36
- }
37
- const { messages } = chatBody;
38
-
39
- // MastraClient's Agent.stream() takes AI-SDK CoreMessage[], not the OpenAI
40
- // wire format: each message has ONE literal role (not a union) and content
41
- // is never null. A 'tool' wire message is OUR client-side tool bookkeeping;
42
- // this agent owns its tools server-side (forwardsFromClient is empty), so it
43
- // has no schema for that shape and the entry is dropped rather than guessed.
44
- //
45
- // Only the USER role takes content parts: a system prompt is text by
46
- // definition, and an assistant turn here is replayed history, not a new
47
- // upload. \`data\` uses the bare base64-or-URL shorthand, which every AI SDK
48
- // major Mastra accepts understands.
49
- type MastraFilePart = { type: 'file'; data: string | URL; mediaType: string; filename?: string };
50
- type MastraUserContent = string | Array<{ type: 'text'; text: string } | MastraFilePart>;
51
- type MastraMessage = { role: 'system'; content: string } | { role: 'user'; content: MastraUserContent } | { role: 'assistant'; content: string };
52
- const mastraMessages: MastraMessage[] = [];
53
- for (const m of messages) {
54
- // Each branch constructs a literal with ONE fixed role, not m.role (which is
55
- // still typed as the 4-way union): a union-VALUED field on a single object
56
- // does not structurally match a union of role-discriminated objects, so
57
- // widening back to m.role here would reintroduce the original TS2345.
58
- if (m.role === 'system') mastraMessages.push({ role: 'system', content: wireText(m.content) });
59
- else if (m.role === 'assistant') mastraMessages.push({ role: 'assistant', content: wireText(m.content) });
60
- else if (m.role === 'user') {
61
- const parts = wireParts(m.content);
62
- // Plain string unless the turn actually carries an attachment.
63
- if (parts.every((p) => p.kind === 'text')) {
64
- mastraMessages.push({ role: 'user', content: wireText(m.content) });
65
- } else {
66
- mastraMessages.push({
67
- role: 'user',
68
- content: parts.map((p) =>
69
- p.kind === 'text'
70
- ? { type: 'text' as const, text: p.text }
71
- : {
72
- type: 'file' as const,
73
- mediaType: p.mediaType,
74
- ...(p.filename === undefined ? {} : { filename: p.filename }),
75
- data: p.source.type === 'data' ? p.source.data : new URL(p.source.url),
76
- },
77
- ),
78
- });
79
- }
80
- }
81
- }
82
-
83
- let agentStream: Awaited<ReturnType<ReturnType<typeof mastra.getAgent>['stream']>>;
84
- try {
85
- agentStream = await mastra.getAgent('supportAgent').stream(mastraMessages);
86
- } catch (err) {
87
- // A REAL status, before a byte is streamed: an unreachable MASTRA_URL or an
88
- // unknown agent id fails here. Returning 200 would send this JSON out
89
- // labelled text/event-stream, the SSE reader would find no frame, and the
90
- // turn would resolve empty with nothing logged and no bubble.
91
- return new Response(
92
- JSON.stringify({ error: { message: err instanceof Error ? err.message : 'Mastra agent failed to start' } }),
93
- { status: 502, headers: { 'Content-Type': 'application/json' } },
94
- );
95
- }
96
-
97
- const encoder = new TextEncoder();
98
- const body = new ReadableStream({
99
- async start(controller) {
100
- try {
101
- // The client SDK has no textStream: it hands back a Response wrapped
102
- // with processDataStream, which replays the agent's SSE body as typed
103
- // chunks. Only text-delta carries browser-facing content; tool-call and
104
- // reasoning chunks exist here too but are out of scope for this route
105
- // (see streamMapping) and are left unhandled rather than half-wired.
106
- await agentStream.processDataStream({
107
- onChunk: (chunk) => {
108
- if (chunk.type === 'text-delta') {
109
- const openaiChunk = { choices: [{ delta: { content: chunk.payload.text } }] };
110
- controller.enqueue(encoder.encode(\`data: \${JSON.stringify(openaiChunk)}\\n\\n\`));
111
- } else if (chunk.type === 'error') {
112
- // Mastra reports some failures IN BAND as an 'error' chunk instead
113
- // of rejecting the stream; fold it into the same frame the catch
114
- // below emits so readOpenAIStream lands it on turn.error either way.
115
- const message = chunk.payload.error instanceof Error ? chunk.payload.error.message : 'Mastra agent reported an error';
116
- controller.enqueue(encoder.encode(\`data: \${JSON.stringify({ error: { message } })}\\n\\n\`));
117
- }
118
- },
119
- });
120
- } catch (err) {
121
- // The status is spent once the stream started, so report IN BAND:
122
- // readOpenAIStream lands this on turn.error and keeps what streamed.
123
- const message = err instanceof Error ? err.message : 'Mastra stream failed';
124
- controller.enqueue(encoder.encode(\`data: \${JSON.stringify({ error: { message } })}\\n\\n\`));
125
- }
126
- controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));
127
- controller.close();
128
- },
129
- });
130
-
131
- return new Response(body, {
132
- status: 200,
133
- headers: {
134
- 'Content-Type': 'text/event-stream; charset=utf-8',
135
- // no-transform stops a proxy buffering the stream into one blob.
136
- 'Cache-Control': 'no-cache, no-transform',
137
- Connection: 'keep-alive',
138
- },
139
- });
140
- }`,
141
- streamMapping: "Mastra's client SDK has no textStream: agent.stream() returns a Response wrapped with processDataStream({ onChunk }), which replays the agent's SSE body as typed chunks (text-delta, tool-call, reasoning-delta, error, finish, ...). Filter to type === 'text-delta' and emit data: {choices:[{delta:{content:payload.text}}]} frames; close with data: [DONE]. readOpenAIStream from @kitn.ai/ui/wire parses that, including tool calls and reasoning, but this route only wires text-delta: re-frame tool-call/tool-result and reasoning-delta chunks onto delta.tool_calls and delta.reasoning to get them too.",
142
- // No install list here: `deps` below is the one, and the scaffolder emits it.
143
- // This sentence used to end "Install @mastra/client-js." — right on the day it
144
- // was written, and unchecked against the route's imports ever after.
145
- runNote: 'Set MASTRA_URL to your Mastra server base URL (mastra dev exposes POST /api/agents/:agentId/stream on port 4111).',
146
- docsSlug: 'integrations/harnesses',
147
- // Nothing. The Mastra agent owns its model and its tools server-side.
148
- forwardsFromClient: [],
149
- // The route's one import.
150
- deps: { npm: ['@mastra/client-js'], pip: [] },
151
- // THE JUDGEMENT CALL IN THIS TABLE, so it is argued rather than asserted.
152
- //
153
- // MASTRA_URL is not a secret — it is a base URL, and the schema's SECRET_ENV_VAR
154
- // net deliberately does not match it. So the automatic check cannot decide this
155
- // one, and 'frontend-safe' would parse cleanly.
156
- //
157
- // It is still 'needs-proxy', on what the route actually is: this integration
158
- // ships a server `chatHandler` that reads `process.env` at module scope, and
159
- // nothing else. There is no browser-direct path in it. Declaring it
160
- // 'frontend-safe' would have the CLI point a public bundle at an unauthenticated
161
- // agent endpoint — a decision a scaffolder must not make silently, even though
162
- // no key leaks. The conservative direction is the cheap one: a needless server
163
- // hop costs a process, the other error costs the endpoint.
164
- keyExposure: 'needs-proxy',
165
- // THE JUDGEMENT CALL FOR THIS FIELD, exactly as keyExposure above is, and for
166
- // a related reason: no automatic check can decide it. MASTRA_URL is a base URL
167
- // for a server this integration does not ship and cannot start; the route's
168
- // only mention of loopback is inside a `throw new Error(...)` string, which
169
- // LOOPBACK_FETCH deliberately does not match (a net that fired on prose would
170
- // be right here by accident and wrong elsewhere). So 'none' would parse
171
- // cleanly.
172
- //
173
- // It is 'local-server' on what the integration actually requires: a Mastra
174
- // server has to be reachable at MASTRA_URL before the first message works,
175
- // `mastra dev` is how a developer gets one (port 4111), and `@mastra/client-js`
176
- // is a CLIENT for it, not the server itself. Printing "start your Mastra
177
- // server" costs a line; omitting it produces a scaffold that fetches a URL
178
- // nothing answers.
179
- outOfBand: 'local-server',
180
- };
181
-
182
- export default mastra;
@@ -1,148 +0,0 @@
1
- import type { Integration } from '../types';
2
-
3
- /**
4
- * mock: the zero-config first-win.
5
- *
6
- * No provider, no API key, no `/api` route, no network. The scaffolder
7
- * special-cases `integration === 'mock'` and emits a front-end whose `onSubmit`
8
- * calls `createMockResponder()` from `@kitn.ai/ui/state` where a real
9
- * integration calls `fetch('/api/chat', …)`. That is the ONLY difference between
10
- * the two emitted handlers. Everything after that expression is already the real
11
- * path: `readOpenAIStream` parses the frames, `createAssistantStream` folds them
12
- * onto the message parts, and the try/catch/finally and abort handling are
13
- * byte-identical. The zero-config preview therefore exercises the kit's own SSE
14
- * reader rather than a hand-rolled fold that merely resembles it.
15
- *
16
- * WHY OPENAI-SHAPED FRAMES. The mock stands in for the consumer's ROUTE, not for
17
- * a provider. Every other integration in this catalog re-frames its provider to
18
- * the OpenAI chat-completions shape server-side before the browser sees it
19
- * (`anthropic`'s route converts the Messages dialect frame by frame, `pi`'s
20
- * bridge converts Pi's stdout JSON, `vercel-ai-sdk` wraps `result.textStream`),
21
- * which is why `readOpenAIStream` is the only reader the scaffolder emits.
22
- * Matching that shape is what keeps "swap the mock for a real backend" a
23
- * one-expression change instead of a rewrite of the submit handler.
24
- *
25
- * WHY YOU CAN ALWAYS TELL. Sharing a real provider's frame shape means shape
26
- * alone no longer marks the reply as fake, so the tells are explicit: the stream
27
- * opens with a `: kai-mock` SSE comment, every frame carries a `_kai_mock` field
28
- * naming the function that produced it, `model` reports as `kai-mock` (no
29
- * provider serves that, so an echoed mock frame is rejected upstream rather than
30
- * quietly believed), and usage is all zeros. `src/state/mock.ts` records why each
31
- * tell sits at a different altitude; do not remove one without reading it.
32
- *
33
- * This lets `scaffold(useCase, integration: 'mock', framework: 'react')` run with
34
- * zero config so a developer sees a live, streaming chat before wiring a model.
35
- * Swap `integration` for a real provider (openai, anthropic, openrouter, ollama,
36
- * …) when ready.
37
- *
38
- * THE ROUTE IS OPTIONAL, AND IT EXISTS ANYWAY (rung-2 finding G-04, recurring
39
- * since rung 1). Two clean-room builders in a row were told "replies come from a
40
- * local dev endpoint that streams a mocked response" and had to hand-invent the
41
- * server side, because this was the one integration whose block (2) held prose
42
- * where every other integration ships code. So `webRoute` below is the mock's
43
- * server half: the SAME `createMockResponder()` frames, written to the wire by a
44
- * portable `chatHandler(Request) => Response` that the scaffolder wraps with the
45
- * identical per-framework adapters a real integration gets (Vite dev middleware
46
- * for the SPA frameworks, POST exports for next/svelte/tanstack, the
47
- * Express/Worker/Angular hosts). Nothing about the emitted app REQUIRES it — the
48
- * front end streams locally and never fetches — which the emitted block states,
49
- * along with the one-expression swap that points onSubmit at it.
50
- *
51
- * `routeTemplates` stays empty: the handler is web-standard, so there is no
52
- * framework whose declaration it cannot be wrapped in. `category: 'mock'` keeps
53
- * it out of the real provider/gateway/framework/harness catalogs.
54
- */
55
- const mock: Integration = {
56
- id: 'mock',
57
- title: 'Mock (local preview)',
58
- category: 'mock',
59
- language: 'ts',
60
- streamFormat: 'native',
61
- envVars: [],
62
- routeTemplates: {},
63
- webRoute: `import { createMockResponder } from '@kitn.ai/ui/state';
64
-
65
- // The kit's own mock responder — no provider, no key, no upstream. MODULE
66
- // scope, not per-request: the responder owns the cursor into its canned
67
- // replies, so rebuilding it per turn would answer with the first one forever.
68
- const mockResponse = createMockResponder();
69
-
70
- async function chatHandler(request: Request): Promise<Response> {
71
- // The responder cycles its replies whatever you send, so the prompt is a
72
- // courtesy — but the body is still read exactly the way a real route reads
73
- // it, so swapping this handler for a provider's changes nothing upstream of
74
- // this file.
75
- let chatBody: ChatRequestBody;
76
- try {
77
- chatBody = await readChatRequest(request);
78
- } catch (error) {
79
- return toChatErrorResponse(error);
80
- }
81
- const { messages } = chatBody;
82
- const last = [...messages].reverse().find((m) => m.role === 'user');
83
- const prompt = last && typeof last.content === 'string' ? last.content : '';
84
-
85
- // createMockResponder() yields COMPLETE OpenAI chat-completions SSE frames —
86
- // the same strings the front end's local preview streams — so this route only
87
- // writes them out verbatim. No framing is built here; the browser parses them
88
- // with readOpenAIStream from @kitn.ai/ui/wire, exactly as it would a real
89
- // route's response. Every frame is marked as a mock (a ': kai-mock' banner, a
90
- // _kai_mock field, model 'kai-mock', zero usage).
91
- const encoder = new TextEncoder();
92
- let open = true;
93
- const body = new ReadableStream<Uint8Array>({
94
- async start(controller) {
95
- for await (const frame of mockResponse(prompt)) {
96
- // The browser hangs up when the user asks a new question mid-answer;
97
- // stop producing frames rather than writing into a cancelled stream.
98
- if (!open) return;
99
- controller.enqueue(encoder.encode(frame));
100
- }
101
- controller.close();
102
- },
103
- cancel() {
104
- open = false;
105
- },
106
- });
107
-
108
- return new Response(body, {
109
- status: 200,
110
- headers: {
111
- 'Content-Type': 'text/event-stream; charset=utf-8',
112
- // no-transform stops a proxy buffering the stream into one blob.
113
- 'Cache-Control': 'no-cache, no-transform',
114
- Connection: 'keep-alive',
115
- // A proxy in front of a preview build would otherwise buffer the whole
116
- // stream and the reply would land all at once instead of streaming.
117
- 'X-Accel-Buffering': 'no',
118
- },
119
- });
120
- }`,
121
- streamMapping:
122
- "No backend and no provider, but a real wire. createMockResponder() from @kitn.ai/ui/state yields canned SSE frames and the scaffold reads them with readOpenAIStream from @kitn.ai/ui/wire, on the same code path a real route's response takes: same reader, same part folding, same abort handling. The frames carry the OpenAI chat-completions shape because the mock stands in for your /api/chat ROUTE, not for a provider (every other integration here re-frames its provider to that shape server-side), so going live replaces ONE expression: mockResponse(value) becomes the awaited response from your own chat route, and nothing else in the handler changes. Nothing here can be mistaken for a real turn: the stream opens with a ': kai-mock' SSE comment, every frame carries a _kai_mock field naming createMockResponder, model reports as 'kai-mock' (no provider serves it), and usage is all zeros. Block (2) serves the same frames over HTTP as an OPTIONAL route, so the /api/chat seam can be stood up before any provider exists.",
123
- runNote:
124
- 'No backend or API key needed: the reply is generated in the browser and parsed by the same reader a real route feeds. Run the front-end as-is; swap `integration` for a real provider (openai, anthropic, openrouter, ollama) when ready, and the emitted handler differs by one expression. Block (2) is the OPTIONAL server half: the same mock frames served over HTTP, for standing up the /api/chat seam before any provider exists.',
125
- docsSlug: 'integrations/mock',
126
- // Nothing: the front end makes no HTTP request at all, and the optional route
127
- // reads only `messages` — and only as a courtesy prompt the responder is free
128
- // to ignore. There is no model to pick and no tools array anything would run.
129
- forwardsFromClient: [],
130
- // Nothing to install: the route's one import is the kit itself, which every
131
- // scaffold already depends on (registry.test.ts pins deps.npm to the route's
132
- // imports minus @kitn.ai/ui).
133
- deps: { npm: [], pip: [] },
134
- // The other 'frontend-safe' entry. The route now exists (G-04) but changes
135
- // nothing here: it holds no credential, sends no auth header and reaches no
136
- // upstream, so there is still nothing a public bundle could give away. The
137
- // schema's own refinement re-checks that claim against the route source.
138
- keyExposure: 'frontend-safe',
139
- // Nothing to supply out of band: no upstream, no process, no runtime. The
140
- // route is optional — the emitted app streams locally without it — which is
141
- // what keeps mock in the "No backend" group of create-kai's gateway prompt
142
- // (listGatewayGroups derives that from frontend-safe + outOfBand 'none', not
143
- // from the absence of a route, precisely because this route is one nobody
144
- // NEEDS).
145
- outOfBand: 'none',
146
- };
147
-
148
- export default mock;
@@ -1,97 +0,0 @@
1
- import type { Integration } from '../types';
2
-
3
- const ollama: Integration = {
4
- id: 'ollama',
5
- title: 'Ollama',
6
- category: 'provider',
7
- language: 'ts',
8
- streamFormat: 'openai-sse',
9
- envVars: [],
10
- // No per-framework templates. The handler below is web-standard, so the
11
- // scaffolder wraps it in the target framework's own route declaration.
12
- //
13
- // There was never an `html` entry and there must not be one: routeTemplates
14
- // keyed by 'html' are selected as the BACKEND ROUTE for framework: 'html', and
15
- // this integration's used to be a second <kai-chat id="chat"> plus a second
16
- // kai-submit listener, so pasting both blocks gave a duplicate id and two
17
- // fetches per submit. chooseRoute refuses an 'html' key outright.
18
- routeTemplates: {},
19
- webRoute: `async function chatHandler(request: Request): Promise<Response> {
20
- // The model is pinned here, not sent by the browser. tools IS forwarded:
21
- // it is undefined unless the front end declared any, and JSON.stringify
22
- // drops it, so the same handler serves a tool archetype and a plain chat.
23
- let chatBody: ChatRequestBody;
24
- try {
25
- chatBody = await readChatRequest(request);
26
- } catch (error) {
27
- return toChatErrorResponse(error);
28
- }
29
- const { messages, tools } = chatBody;
30
-
31
- const upstream = await fetch('http://localhost:11434/v1/chat/completions', {
32
- method: 'POST',
33
- headers: { 'Content-Type': 'application/json' },
34
- body: JSON.stringify({ model: 'llama3.2', messages, tools, stream: true }),
35
- });
36
-
37
- // FORWARD THE STATUS. Returning 200 for a failed upstream is how "ollama is
38
- // not running" or "that model was never pulled" turns into silence: the error
39
- // body is JSON, it goes out labelled text/event-stream, the SSE reader finds
40
- // no frame, and the turn resolves empty with nothing logged and no bubble.
41
- if (!upstream.ok) {
42
- return new Response(await upstream.text(), {
43
- status: upstream.status,
44
- headers: {
45
- 'Content-Type': upstream.headers.get('content-type') ?? 'application/json',
46
- },
47
- });
48
- }
49
- if (!upstream.body) {
50
- return new Response(JSON.stringify({ error: { message: 'Ollama returned no body to stream.' } }), {
51
- status: 502,
52
- headers: { 'Content-Type': 'application/json' },
53
- });
54
- }
55
-
56
- // Ollama returns OpenAI-format SSE. Stream it straight to the browser.
57
- return new Response(upstream.body, {
58
- status: 200,
59
- headers: {
60
- 'Content-Type': 'text/event-stream; charset=utf-8',
61
- // no-transform stops a proxy buffering the stream into one blob.
62
- 'Cache-Control': 'no-cache, no-transform',
63
- Connection: 'keep-alive',
64
- },
65
- });
66
- }`,
67
- streamMapping:
68
- "Ollama's OpenAI-compatible endpoint (http://localhost:11434/v1/chat/completions) returns OpenAI-format SSE. Pipe upstream.body straight to the browser; readOpenAIStream from @kitn.ai/ui/wire parses it, including tool calls and reasoning. No API key needed; pass any string if a client requires one (Ollama ignores it).",
69
- runNote: 'No API key required. Run: ollama serve (starts on 127.0.0.1:11434), then ollama pull <model>. For browser-direct access, set OLLAMA_ORIGINS to allow the page origin; restart Ollama after any env change.',
70
- docsSlug: 'integrations/ollama',
71
- // No 'model': the route pins llama3.2, so a front-end model const would be an
72
- // editable value the route throws away. Change the model in the route. 'tools'
73
- // IS forwarded, which is what lets an agentic scaffold fill its kai-tool panel.
74
- forwardsFromClient: ['tools'],
75
- // Ollama's OpenAI-compatible endpoint, and the handler forwards `tools`
76
- // verbatim into that body — so the client sends OpenAI's function envelope.
77
- clientToolFormat: 'openai',
78
- // Nothing. The route is global `fetch` and imports no module; the `ollama`
79
- // npm package is not used, and the server itself is installed out of band.
80
- deps: { npm: [], pip: [] },
81
- // One of the two 'frontend-safe' entries, and it is read off the route rather
82
- // than off "it's local, so it's fine": the fetch to localhost:11434 sends
83
- // Content-Type and NOTHING else — no Authorization, no key — and envVars is
84
- // empty, so there is no secret for a bundle to leak. runNote already documents
85
- // the browser-direct path (set OLLAMA_ORIGINS to allow the page origin), which
86
- // is the path this value unlocks.
87
- keyExposure: 'frontend-safe',
88
- // The route fetches http://localhost:11434, so Ollama must ALREADY be running:
89
- // `ollama serve`, then `ollama pull <model>` for the model the route pins.
90
- // Nothing in package.json installs or starts it — `deps.npm` is empty because
91
- // the route is bare `fetch`, which is exactly why this cannot be inferred from
92
- // the dependency list. The schema's LOOPBACK_FETCH net catches this one
93
- // independently, so a later edit to 'none' fails at the catalog boundary.
94
- outOfBand: 'local-server',
95
- };
96
-
97
- export default ollama;
@@ -1,95 +0,0 @@
1
- import type { Integration } from '../types';
2
-
3
- const openai: Integration = {
4
- id: 'openai',
5
- title: 'OpenAI',
6
- category: 'provider',
7
- language: 'ts',
8
- streamFormat: 'openai-sse',
9
- envVars: ['OPENAI_API_KEY'],
10
- // No per-framework templates: the handler below is web-standard, so the
11
- // scaffolder wraps it in whatever the target framework routes with.
12
- routeTemplates: {},
13
- webRoute: `async function chatHandler(request: Request): Promise<Response> {
14
- // Both model and tools come from the browser. \`tools\` is undefined unless the
15
- // front end declared any, and JSON.stringify drops it, so the same handler
16
- // serves a tool archetype and a plain chat.
17
- let chatBody: ChatRequestBody;
18
- try {
19
- chatBody = await readChatRequest(request);
20
- } catch (error) {
21
- return toChatErrorResponse(error);
22
- }
23
- const { model, messages, tools } = chatBody;
24
-
25
- const upstream = await fetch('https://api.openai.com/v1/chat/completions', {
26
- method: 'POST',
27
- headers: {
28
- Authorization: \`Bearer \${process.env.OPENAI_API_KEY}\`,
29
- 'Content-Type': 'application/json',
30
- },
31
- // Model ids here carry NO vendor prefix: 'gpt-4o-mini', never
32
- // 'openai/gpt-4o-mini' — the prefixed form is an OpenRouter slug and this
33
- // host answers it with a 404. The front end's \`model\` const is the one to
34
- // edit; it is seeded from CLIENT_MODEL_IDS.openai.
35
- body: JSON.stringify({ model, messages, tools, stream: true }),
36
- });
37
-
38
- // FORWARD THE STATUS. Returning 200 here is how a missing key turns into
39
- // silence: the 401 body is JSON, it goes out labelled text/event-stream, the
40
- // SSE reader finds no frame, and the turn resolves empty with nothing logged
41
- // and no bubble. With the status intact readOpenAIStream throws a WireError
42
- // carrying OpenAI's own message, which is the most useful thing you can be
43
- // handed on a first run.
44
- if (!upstream.ok) {
45
- return new Response(await upstream.text(), {
46
- status: upstream.status,
47
- headers: {
48
- 'Content-Type': upstream.headers.get('content-type') ?? 'application/json',
49
- },
50
- });
51
- }
52
- if (!upstream.body) {
53
- return new Response(JSON.stringify({ error: { message: 'OpenAI returned no body to stream.' } }), {
54
- status: 502,
55
- headers: { 'Content-Type': 'application/json' },
56
- });
57
- }
58
-
59
- // OpenAI IS the format readOpenAIStream parses. Pass it straight through.
60
- return new Response(upstream.body, {
61
- status: 200,
62
- headers: {
63
- 'Content-Type': 'text/event-stream; charset=utf-8',
64
- // no-transform stops a proxy buffering the stream into one blob.
65
- 'Cache-Control': 'no-cache, no-transform',
66
- Connection: 'keep-alive',
67
- },
68
- });
69
- }`,
70
- streamMapping:
71
- "OpenAI's /v1/chat/completions is the reference OpenAI-format SSE stream — this is the one integration with no re-framing at all. Pipe upstream.body straight to the browser; readOpenAIStream from @kitn.ai/ui/wire parses it, including tool calls (delta.tool_calls) and reasoning (delta.reasoning on the reasoning models). Set stream_options: { include_usage: true } in the body if you want a final usage frame; readOpenAIStream reads prompt_tokens/completion_tokens off it.",
72
- runNote:
73
- "Set OPENAI_API_KEY (platform.openai.com). Model ids have NO vendor prefix: 'gpt-4o-mini', not 'openai/gpt-4o-mini' — the prefixed form is an OpenRouter slug and api.openai.com answers it with a 404. Change the pinned model in the route.",
74
- docsSlug: 'integrations/connect-any-model',
75
- // 'model' was withheld until scaffold.ts could seed it correctly: the shared
76
- // fallback is 'openai/gpt-4o-mini', an OpenRouter slug that api.openai.com
77
- // 404s, and shipping an editable const with a broken default is the exact
78
- // dead-const defect forwardsFromClient exists to prevent. CLIENT_MODEL_IDS now
79
- // carries a per-integration entry ('gpt-4o-mini'), so the const is real and the
80
- // route reads it. 'tools' is what lets an agentic scaffold fill its kai-tool
81
- // panel.
82
- forwardsFromClient: ['model', 'tools'],
83
- // The handler forwards `tools` unconverted to /v1/chat/completions — this IS
84
- // the OpenAI wire, so the client sends OpenAI's own function envelope.
85
- clientToolFormat: 'openai',
86
- // Nothing to install. The route is global `fetch` and imports no module at all.
87
- deps: { npm: [], pip: [] },
88
- // The route reads OPENAI_API_KEY and puts it in an `Authorization: Bearer`
89
- // header. A static bundle carrying that is a published key.
90
- keyExposure: 'needs-proxy',
91
- // A remote HTTPS endpoint and a key. Nothing to install, nothing to start.
92
- outOfBand: 'none',
93
- };
94
-
95
- export default openai;