tulingcode 0.1.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 (1119) hide show
  1. package/AGENTS.md +134 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/bin/tuling +179 -0
  5. package/bunfig.toml +7 -0
  6. package/drizzle.config.ts +10 -0
  7. package/git +0 -0
  8. package/migration/20260127222353_familiar_lady_ursula/migration.sql +90 -0
  9. package/migration/20260127222353_familiar_lady_ursula/snapshot.json +796 -0
  10. package/migration/20260211171708_add_project_commands/migration.sql +1 -0
  11. package/migration/20260211171708_add_project_commands/snapshot.json +806 -0
  12. package/migration/20260213144116_wakeful_the_professor/migration.sql +11 -0
  13. package/migration/20260213144116_wakeful_the_professor/snapshot.json +897 -0
  14. package/migration/20260225215848_workspace/migration.sql +7 -0
  15. package/migration/20260225215848_workspace/snapshot.json +959 -0
  16. package/migration/20260227213759_add_session_workspace_id/migration.sql +2 -0
  17. package/migration/20260227213759_add_session_workspace_id/snapshot.json +983 -0
  18. package/migration/20260228203230_blue_harpoon/migration.sql +17 -0
  19. package/migration/20260228203230_blue_harpoon/snapshot.json +1102 -0
  20. package/migration/20260303231226_add_workspace_fields/migration.sql +5 -0
  21. package/migration/20260303231226_add_workspace_fields/snapshot.json +1013 -0
  22. package/migration/20260309230000_move_org_to_state/migration.sql +3 -0
  23. package/migration/20260309230000_move_org_to_state/snapshot.json +1156 -0
  24. package/migration/20260312043431_session_message_cursor/migration.sql +4 -0
  25. package/migration/20260312043431_session_message_cursor/snapshot.json +1168 -0
  26. package/migration/20260323234822_events/migration.sql +13 -0
  27. package/migration/20260323234822_events/snapshot.json +1271 -0
  28. package/migration/20260410174513_workspace-name/migration.sql +16 -0
  29. package/migration/20260410174513_workspace-name/snapshot.json +1271 -0
  30. package/migration/20260413175956_chief_energizer/migration.sql +13 -0
  31. package/migration/20260413175956_chief_energizer/snapshot.json +1399 -0
  32. package/migration/20260422160000_context_inheritance/migration.sql +3 -0
  33. package/migration/20260422170000_task_registry/migration.sql +18 -0
  34. package/migration/20260423145421_remove_session_entry/migration.sql +4 -0
  35. package/migration/20260515000000_actor_rename/migration.sql +7 -0
  36. package/migration/20260515010000_memory_fts/migration.sql +33 -0
  37. package/migration/20260515020000_user_task/migration.sql +29 -0
  38. package/migration/20260519000000_last_checkpoint_message_id/migration.sql +1 -0
  39. package/migration/20260521000000_message_agent_id/migration.sql +2 -0
  40. package/migration/20260521000100_actor_registry_v6/migration.sql +25 -0
  41. package/migration/20260521010000_memory_fts_v6/migration.sql +33 -0
  42. package/migration/20260521020000_memory_fts_triggers/migration.sql +17 -0
  43. package/migration/20260526000000_agent_id_main/migration.sql +14 -0
  44. package/migration/20260527000000_actor_lifecycle/migration.sql +8 -0
  45. package/migration/20260527000100_inbox/migration.sql +12 -0
  46. package/migration/20260529000000_task_todo_redesign/migration.sql +16 -0
  47. package/migration/20260603000000_task_in_progress_owner/migration.sql +1 -0
  48. package/migration/20260603000000_workflow_run/migration.sql +17 -0
  49. package/migration/20260604000000_workflow_script_sha/migration.sql +1 -0
  50. package/migration/20260608000000_claude_import/migration.sql +7 -0
  51. package/migration/20260608010000_claude_import_message_ids/migration.sql +1 -0
  52. package/migration/20260609000000_history_fts/migration.sql +29 -0
  53. package/migration/20260609230000_workflow_agent_timeout/migration.sql +1 -0
  54. package/package.json +196 -0
  55. package/parsers-config.ts +290 -0
  56. package/script/build.ts +267 -0
  57. package/script/check-migrations.ts +16 -0
  58. package/script/fix-node-pty.ts +28 -0
  59. package/script/generate.ts +23 -0
  60. package/script/postinstall.mjs +102 -0
  61. package/script/publish.ts +60 -0
  62. package/script/run-workspace-server +106 -0
  63. package/script/schema.ts +63 -0
  64. package/script/time.ts +6 -0
  65. package/script/trace-imports.ts +153 -0
  66. package/script/upgrade-opentui.ts +64 -0
  67. package/src/account/account.sql.ts +39 -0
  68. package/src/account/account.ts +456 -0
  69. package/src/account/repo.ts +166 -0
  70. package/src/account/schema.ts +99 -0
  71. package/src/account/url.ts +8 -0
  72. package/src/acp/README.md +174 -0
  73. package/src/acp/agent.ts +1783 -0
  74. package/src/acp/session.ts +116 -0
  75. package/src/acp/types.ts +24 -0
  76. package/src/actor/actor.sql.ts +38 -0
  77. package/src/actor/events.ts +67 -0
  78. package/src/actor/index.ts +2 -0
  79. package/src/actor/registry.ts +412 -0
  80. package/src/actor/return-header.ts +24 -0
  81. package/src/actor/schema.ts +47 -0
  82. package/src/actor/spawn-ref.ts +16 -0
  83. package/src/actor/spawn.ts +741 -0
  84. package/src/actor/turn.ts +49 -0
  85. package/src/actor/waiter.ts +166 -0
  86. package/src/agent/agent.ts +554 -0
  87. package/src/agent/config.ts +5 -0
  88. package/src/agent/generate.txt +75 -0
  89. package/src/agent/prompt/checkpoint-writer.txt +167 -0
  90. package/src/agent/prompt/compaction.txt +9 -0
  91. package/src/agent/prompt/distill.txt +199 -0
  92. package/src/agent/prompt/dream.txt +155 -0
  93. package/src/agent/prompt/explore.txt +18 -0
  94. package/src/agent/prompt/summary.txt +11 -0
  95. package/src/agent/prompt/title.txt +44 -0
  96. package/src/audio.d.ts +9 -0
  97. package/src/auth/index.ts +97 -0
  98. package/src/bus/bus-event.ts +33 -0
  99. package/src/bus/global.ts +12 -0
  100. package/src/bus/index.ts +193 -0
  101. package/src/cli/bootstrap.ts +33 -0
  102. package/src/cli/cmd/account.ts +258 -0
  103. package/src/cli/cmd/acp.ts +70 -0
  104. package/src/cli/cmd/agent.ts +248 -0
  105. package/src/cli/cmd/cmd.ts +7 -0
  106. package/src/cli/cmd/db.ts +120 -0
  107. package/src/cli/cmd/debug/agent.ts +192 -0
  108. package/src/cli/cmd/debug/config.ts +17 -0
  109. package/src/cli/cmd/debug/file.ts +100 -0
  110. package/src/cli/cmd/debug/index.ts +48 -0
  111. package/src/cli/cmd/debug/lsp.ts +61 -0
  112. package/src/cli/cmd/debug/ripgrep.ts +105 -0
  113. package/src/cli/cmd/debug/scrap.ts +16 -0
  114. package/src/cli/cmd/debug/skill.ts +23 -0
  115. package/src/cli/cmd/debug/snapshot.ts +53 -0
  116. package/src/cli/cmd/export.ts +306 -0
  117. package/src/cli/cmd/generate.ts +50 -0
  118. package/src/cli/cmd/github.ts +1647 -0
  119. package/src/cli/cmd/import.ts +208 -0
  120. package/src/cli/cmd/mcp.ts +812 -0
  121. package/src/cli/cmd/models.ts +88 -0
  122. package/src/cli/cmd/plug.ts +233 -0
  123. package/src/cli/cmd/pr.ts +138 -0
  124. package/src/cli/cmd/providers.ts +705 -0
  125. package/src/cli/cmd/run-completion.ts +77 -0
  126. package/src/cli/cmd/run.ts +694 -0
  127. package/src/cli/cmd/serve.ts +21 -0
  128. package/src/cli/cmd/session.ts +181 -0
  129. package/src/cli/cmd/stats.ts +413 -0
  130. package/src/cli/cmd/tui/app.tsx +1130 -0
  131. package/src/cli/cmd/tui/asset/TEN_VAD_LICENSE +12 -0
  132. package/src/cli/cmd/tui/asset/charge.wav +0 -0
  133. package/src/cli/cmd/tui/asset/pulse-a.wav +0 -0
  134. package/src/cli/cmd/tui/asset/pulse-b.wav +0 -0
  135. package/src/cli/cmd/tui/asset/pulse-c.wav +0 -0
  136. package/src/cli/cmd/tui/asset/ten_vad.wasm +0 -0
  137. package/src/cli/cmd/tui/asset/ten_vad_loader.js +30 -0
  138. package/src/cli/cmd/tui/attach.ts +83 -0
  139. package/src/cli/cmd/tui/component/background-image.tsx +150 -0
  140. package/src/cli/cmd/tui/component/bg-pulse.tsx +130 -0
  141. package/src/cli/cmd/tui/component/border.tsx +21 -0
  142. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  143. package/src/cli/cmd/tui/component/dialog-command.tsx +208 -0
  144. package/src/cli/cmd/tui/component/dialog-console-org.tsx +103 -0
  145. package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +157 -0
  146. package/src/cli/cmd/tui/component/dialog-image-list.tsx +111 -0
  147. package/src/cli/cmd/tui/component/dialog-logo-design.tsx +37 -0
  148. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  149. package/src/cli/cmd/tui/component/dialog-mimo-login.tsx +224 -0
  150. package/src/cli/cmd/tui/component/dialog-model.tsx +253 -0
  151. package/src/cli/cmd/tui/component/dialog-provider.tsx +490 -0
  152. package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +101 -0
  153. package/src/cli/cmd/tui/component/dialog-session-list.tsx +269 -0
  154. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  155. package/src/cli/cmd/tui/component/dialog-skill.tsx +42 -0
  156. package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
  157. package/src/cli/cmd/tui/component/dialog-status.tsx +170 -0
  158. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  159. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  160. package/src/cli/cmd/tui/component/dialog-variant.tsx +39 -0
  161. package/src/cli/cmd/tui/component/dialog-workflows.tsx +62 -0
  162. package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +289 -0
  163. package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +81 -0
  164. package/src/cli/cmd/tui/component/dialog-worktree.tsx +90 -0
  165. package/src/cli/cmd/tui/component/error-component.tsx +92 -0
  166. package/src/cli/cmd/tui/component/logo.tsx +961 -0
  167. package/src/cli/cmd/tui/component/plugin-route-missing.tsx +14 -0
  168. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +684 -0
  169. package/src/cli/cmd/tui/component/prompt/cwd.ts +0 -0
  170. package/src/cli/cmd/tui/component/prompt/frecency.tsx +90 -0
  171. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  172. package/src/cli/cmd/tui/component/prompt/index.tsx +1812 -0
  173. package/src/cli/cmd/tui/component/prompt/part.ts +16 -0
  174. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  175. package/src/cli/cmd/tui/component/spinner.tsx +24 -0
  176. package/src/cli/cmd/tui/component/starry-background.tsx +305 -0
  177. package/src/cli/cmd/tui/component/startup-loading.tsx +67 -0
  178. package/src/cli/cmd/tui/component/task-item.tsx +63 -0
  179. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  180. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  181. package/src/cli/cmd/tui/config/cwd.ts +5 -0
  182. package/src/cli/cmd/tui/config/tui-migrate.ts +151 -0
  183. package/src/cli/cmd/tui/config/tui-schema.ts +38 -0
  184. package/src/cli/cmd/tui/config/tui.ts +219 -0
  185. package/src/cli/cmd/tui/context/args.tsx +16 -0
  186. package/src/cli/cmd/tui/context/directory.ts +15 -0
  187. package/src/cli/cmd/tui/context/event.ts +45 -0
  188. package/src/cli/cmd/tui/context/exit.tsx +65 -0
  189. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  190. package/src/cli/cmd/tui/context/keybind.tsx +105 -0
  191. package/src/cli/cmd/tui/context/kv.tsx +76 -0
  192. package/src/cli/cmd/tui/context/language.tsx +91 -0
  193. package/src/cli/cmd/tui/context/local.tsx +455 -0
  194. package/src/cli/cmd/tui/context/plugin-keybinds.ts +41 -0
  195. package/src/cli/cmd/tui/context/project.tsx +109 -0
  196. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  197. package/src/cli/cmd/tui/context/route.tsx +61 -0
  198. package/src/cli/cmd/tui/context/sdk.tsx +150 -0
  199. package/src/cli/cmd/tui/context/sync.tsx +828 -0
  200. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  201. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  202. package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
  203. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +230 -0
  204. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +230 -0
  205. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  206. package/src/cli/cmd/tui/context/theme/cobalt2.json +225 -0
  207. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  208. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  209. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  210. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  211. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  212. package/src/cli/cmd/tui/context/theme/gruvbox.json +242 -0
  213. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  214. package/src/cli/cmd/tui/context/theme/lucent-orng.json +234 -0
  215. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  216. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  217. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  218. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  219. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  220. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  221. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  222. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  223. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  224. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  225. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  226. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  227. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  228. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  229. package/src/cli/cmd/tui/context/theme/tulingcode.json +245 -0
  230. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  231. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  232. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  233. package/src/cli/cmd/tui/context/theme.tsx +1298 -0
  234. package/src/cli/cmd/tui/context/thinking.ts +48 -0
  235. package/src/cli/cmd/tui/context/tui-config.tsx +9 -0
  236. package/src/cli/cmd/tui/event.ts +56 -0
  237. package/src/cli/cmd/tui/feature-plugins/home/footer.tsx +93 -0
  238. package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +193 -0
  239. package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +54 -0
  240. package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +114 -0
  241. package/src/cli/cmd/tui/feature-plugins/sidebar/cwd.tsx +45 -0
  242. package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +62 -0
  243. package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +93 -0
  244. package/src/cli/cmd/tui/feature-plugins/sidebar/goal.tsx +84 -0
  245. package/src/cli/cmd/tui/feature-plugins/sidebar/instructions.tsx +54 -0
  246. package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +66 -0
  247. package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +98 -0
  248. package/src/cli/cmd/tui/feature-plugins/sidebar/task.tsx +95 -0
  249. package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +51 -0
  250. package/src/cli/cmd/tui/feature-plugins/sidebar/tps.ts +31 -0
  251. package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +274 -0
  252. package/src/cli/cmd/tui/i18n/en.ts +397 -0
  253. package/src/cli/cmd/tui/i18n/es.ts +433 -0
  254. package/src/cli/cmd/tui/i18n/fr.ts +440 -0
  255. package/src/cli/cmd/tui/i18n/ja.ts +392 -0
  256. package/src/cli/cmd/tui/i18n/locales.ts +82 -0
  257. package/src/cli/cmd/tui/i18n/ru.ts +452 -0
  258. package/src/cli/cmd/tui/i18n/zh.ts +390 -0
  259. package/src/cli/cmd/tui/i18n/zht.ts +360 -0
  260. package/src/cli/cmd/tui/layer.ts +6 -0
  261. package/src/cli/cmd/tui/plugin/api.tsx +402 -0
  262. package/src/cli/cmd/tui/plugin/index.ts +3 -0
  263. package/src/cli/cmd/tui/plugin/internal.ts +35 -0
  264. package/src/cli/cmd/tui/plugin/runtime.ts +1030 -0
  265. package/src/cli/cmd/tui/plugin/slots.tsx +60 -0
  266. package/src/cli/cmd/tui/routes/home.tsx +165 -0
  267. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +76 -0
  268. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +116 -0
  269. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +47 -0
  270. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  271. package/src/cli/cmd/tui/routes/session/footer.tsx +91 -0
  272. package/src/cli/cmd/tui/routes/session/index.tsx +2532 -0
  273. package/src/cli/cmd/tui/routes/session/permission.tsx +691 -0
  274. package/src/cli/cmd/tui/routes/session/question.tsx +488 -0
  275. package/src/cli/cmd/tui/routes/session/sidebar.tsx +97 -0
  276. package/src/cli/cmd/tui/routes/session/subagent-footer.tsx +142 -0
  277. package/src/cli/cmd/tui/thread.ts +246 -0
  278. package/src/cli/cmd/tui/ui/dialog-alert.tsx +61 -0
  279. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +95 -0
  280. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +223 -0
  281. package/src/cli/cmd/tui/ui/dialog-help.tsx +42 -0
  282. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +123 -0
  283. package/src/cli/cmd/tui/ui/dialog-select.tsx +452 -0
  284. package/src/cli/cmd/tui/ui/dialog.tsx +207 -0
  285. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  286. package/src/cli/cmd/tui/ui/spinner.ts +378 -0
  287. package/src/cli/cmd/tui/ui/toast.tsx +102 -0
  288. package/src/cli/cmd/tui/util/clipboard.ts +203 -0
  289. package/src/cli/cmd/tui/util/editor.ts +35 -0
  290. package/src/cli/cmd/tui/util/image-protocol.ts +35 -0
  291. package/src/cli/cmd/tui/util/index.ts +6 -0
  292. package/src/cli/cmd/tui/util/model.ts +23 -0
  293. package/src/cli/cmd/tui/util/provider-origin.ts +7 -0
  294. package/src/cli/cmd/tui/util/revert-diff.ts +18 -0
  295. package/src/cli/cmd/tui/util/scroll.ts +23 -0
  296. package/src/cli/cmd/tui/util/selection.ts +23 -0
  297. package/src/cli/cmd/tui/util/signal.ts +41 -0
  298. package/src/cli/cmd/tui/util/sound.ts +154 -0
  299. package/src/cli/cmd/tui/util/system-locale.ts +209 -0
  300. package/src/cli/cmd/tui/util/terminal.ts +110 -0
  301. package/src/cli/cmd/tui/util/transcript.ts +112 -0
  302. package/src/cli/cmd/tui/util/vad.ts +229 -0
  303. package/src/cli/cmd/tui/util/voice.ts +360 -0
  304. package/src/cli/cmd/tui/win32.ts +130 -0
  305. package/src/cli/cmd/tui/worker.ts +104 -0
  306. package/src/cli/cmd/uninstall.ts +351 -0
  307. package/src/cli/cmd/upgrade.ts +79 -0
  308. package/src/cli/cmd/web.ts +81 -0
  309. package/src/cli/effect/prompt.ts +25 -0
  310. package/src/cli/error.ts +82 -0
  311. package/src/cli/heap.ts +59 -0
  312. package/src/cli/i18n.ts +15 -0
  313. package/src/cli/logo.ts +53 -0
  314. package/src/cli/network.ts +62 -0
  315. package/src/cli/ui.ts +133 -0
  316. package/src/cli/upgrade.ts +41 -0
  317. package/src/command/index.ts +276 -0
  318. package/src/command/template/initialize.txt +66 -0
  319. package/src/command/template/review.txt +101 -0
  320. package/src/config/agent.ts +197 -0
  321. package/src/config/command.ts +69 -0
  322. package/src/config/config.ts +1024 -0
  323. package/src/config/console-state.ts +16 -0
  324. package/src/config/entry-name.ts +16 -0
  325. package/src/config/error.ts +21 -0
  326. package/src/config/formatter.ts +17 -0
  327. package/src/config/history.ts +21 -0
  328. package/src/config/index.ts +16 -0
  329. package/src/config/keybinds.ts +127 -0
  330. package/src/config/layout.ts +10 -0
  331. package/src/config/lsp.ts +45 -0
  332. package/src/config/managed.ts +70 -0
  333. package/src/config/markdown.ts +97 -0
  334. package/src/config/mcp.ts +172 -0
  335. package/src/config/model-id.ts +14 -0
  336. package/src/config/parse.ts +44 -0
  337. package/src/config/paths.ts +73 -0
  338. package/src/config/permission.ts +76 -0
  339. package/src/config/plugin.ts +88 -0
  340. package/src/config/provider.ts +118 -0
  341. package/src/config/server.ts +20 -0
  342. package/src/config/skills.ts +16 -0
  343. package/src/config/variable.ts +90 -0
  344. package/src/control-plane/adaptors/index.ts +52 -0
  345. package/src/control-plane/adaptors/worktree.ts +47 -0
  346. package/src/control-plane/dev/debug-workspace-plugin.ts +73 -0
  347. package/src/control-plane/schema.ts +19 -0
  348. package/src/control-plane/sse.ts +66 -0
  349. package/src/control-plane/types.ts +34 -0
  350. package/src/control-plane/util.ts +37 -0
  351. package/src/control-plane/workspace-context.ts +26 -0
  352. package/src/control-plane/workspace.sql.ts +17 -0
  353. package/src/control-plane/workspace.ts +615 -0
  354. package/src/effect/app-runtime.ts +146 -0
  355. package/src/effect/bootstrap-runtime.ts +33 -0
  356. package/src/effect/bridge.ts +48 -0
  357. package/src/effect/cross-spawn-spawner.ts +514 -0
  358. package/src/effect/index.ts +5 -0
  359. package/src/effect/instance-ref.ts +11 -0
  360. package/src/effect/instance-registry.ts +12 -0
  361. package/src/effect/instance-state.ts +81 -0
  362. package/src/effect/logger.ts +73 -0
  363. package/src/effect/memo-map.ts +3 -0
  364. package/src/effect/observability.ts +107 -0
  365. package/src/effect/run-service.ts +52 -0
  366. package/src/effect/runner.ts +210 -0
  367. package/src/effect/runtime.ts +19 -0
  368. package/src/env/index.ts +37 -0
  369. package/src/file/ignore.ts +81 -0
  370. package/src/file/index.ts +664 -0
  371. package/src/file/protected.ts +59 -0
  372. package/src/file/ripgrep.ts +485 -0
  373. package/src/file/watcher.ts +163 -0
  374. package/src/flag/flag.ts +164 -0
  375. package/src/format/formatter.ts +403 -0
  376. package/src/format/index.ts +203 -0
  377. package/src/git/index.ts +260 -0
  378. package/src/global/index.ts +54 -0
  379. package/src/history/backfill.ts +162 -0
  380. package/src/history/extract.ts +67 -0
  381. package/src/history/fts-query.ts +15 -0
  382. package/src/history/fts.sql.ts +20 -0
  383. package/src/history/index.ts +10 -0
  384. package/src/history/resolve.ts +65 -0
  385. package/src/history/service.ts +258 -0
  386. package/src/history/writer.ts +112 -0
  387. package/src/id/id.ts +87 -0
  388. package/src/ide/index.ts +73 -0
  389. package/src/inbox/inbox-ref.ts +38 -0
  390. package/src/inbox/inbox.sql.ts +26 -0
  391. package/src/inbox/inbox.ts +223 -0
  392. package/src/inbox/index.ts +3 -0
  393. package/src/inbox/render.ts +40 -0
  394. package/src/index.ts +260 -0
  395. package/src/installation/index.ts +351 -0
  396. package/src/installation/version.ts +8 -0
  397. package/src/lsp/client.ts +249 -0
  398. package/src/lsp/diagnostic.ts +29 -0
  399. package/src/lsp/index.ts +3 -0
  400. package/src/lsp/language.ts +120 -0
  401. package/src/lsp/launch.ts +21 -0
  402. package/src/lsp/lsp.ts +519 -0
  403. package/src/lsp/server.ts +1956 -0
  404. package/src/mcp/auth.ts +144 -0
  405. package/src/mcp/index.ts +944 -0
  406. package/src/mcp/oauth-callback.ts +232 -0
  407. package/src/mcp/oauth-provider.ts +214 -0
  408. package/src/memory/fts-query.ts +37 -0
  409. package/src/memory/fts.sql.ts +19 -0
  410. package/src/memory/index.ts +1 -0
  411. package/src/memory/paths.ts +116 -0
  412. package/src/memory/reconcile.ts +144 -0
  413. package/src/memory/service.ts +144 -0
  414. package/src/metrics/client.ts +40 -0
  415. package/src/metrics/event.ts +43 -0
  416. package/src/metrics/index.ts +5 -0
  417. package/src/metrics/installation.ts +18 -0
  418. package/src/metrics/subscriber.ts +58 -0
  419. package/src/metrics/util.ts +9 -0
  420. package/src/node.ts +6 -0
  421. package/src/npm/config.ts +0 -0
  422. package/src/npm/index.ts +293 -0
  423. package/src/npmcli-config.d.ts +43 -0
  424. package/src/patch/index.ts +680 -0
  425. package/src/permission/arity.ts +163 -0
  426. package/src/permission/evaluate.ts +15 -0
  427. package/src/permission/index.ts +379 -0
  428. package/src/permission/schema.ts +17 -0
  429. package/src/plugin/checkpoint-splitover.ts +60 -0
  430. package/src/plugin/cloud-ai.ts +329 -0
  431. package/src/plugin/cloudflare.ts +76 -0
  432. package/src/plugin/codex.ts +607 -0
  433. package/src/plugin/github-copilot/copilot.ts +368 -0
  434. package/src/plugin/github-copilot/models.ts +153 -0
  435. package/src/plugin/index.ts +493 -0
  436. package/src/plugin/install.ts +439 -0
  437. package/src/plugin/loader.ts +216 -0
  438. package/src/plugin/matcher.ts +33 -0
  439. package/src/plugin/meta.ts +188 -0
  440. package/src/plugin/mimo-free.ts +153 -0
  441. package/src/plugin/mimo.ts +124 -0
  442. package/src/plugin/shared.ts +323 -0
  443. package/src/plugin/subagent-progress-checker.ts +147 -0
  444. package/src/project/bootstrap.ts +59 -0
  445. package/src/project/index.ts +2 -0
  446. package/src/project/instance.ts +190 -0
  447. package/src/project/project-id.ts +48 -0
  448. package/src/project/project.sql.ts +16 -0
  449. package/src/project/project.ts +501 -0
  450. package/src/project/schema.ts +15 -0
  451. package/src/project/vcs.ts +227 -0
  452. package/src/provider/auth.ts +234 -0
  453. package/src/provider/error.ts +216 -0
  454. package/src/provider/index.ts +5 -0
  455. package/src/provider/models.ts +180 -0
  456. package/src/provider/provider.ts +1782 -0
  457. package/src/provider/schema.ts +36 -0
  458. package/src/provider/sdk/copilot/README.md +5 -0
  459. package/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +170 -0
  460. package/src/provider/sdk/copilot/chat/get-response-metadata.ts +15 -0
  461. package/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
  462. package/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts +64 -0
  463. package/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts +815 -0
  464. package/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts +28 -0
  465. package/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +44 -0
  466. package/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts +83 -0
  467. package/src/provider/sdk/copilot/copilot-provider.ts +100 -0
  468. package/src/provider/sdk/copilot/index.ts +2 -0
  469. package/src/provider/sdk/copilot/openai-compatible-error.ts +27 -0
  470. package/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts +335 -0
  471. package/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts +22 -0
  472. package/src/provider/sdk/copilot/responses/openai-config.ts +18 -0
  473. package/src/provider/sdk/copilot/responses/openai-error.ts +22 -0
  474. package/src/provider/sdk/copilot/responses/openai-responses-api-types.ts +214 -0
  475. package/src/provider/sdk/copilot/responses/openai-responses-language-model.ts +1770 -0
  476. package/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts +173 -0
  477. package/src/provider/sdk/copilot/responses/openai-responses-settings.ts +1 -0
  478. package/src/provider/sdk/copilot/responses/tool/code-interpreter.ts +87 -0
  479. package/src/provider/sdk/copilot/responses/tool/file-search.ts +127 -0
  480. package/src/provider/sdk/copilot/responses/tool/image-generation.ts +114 -0
  481. package/src/provider/sdk/copilot/responses/tool/local-shell.ts +64 -0
  482. package/src/provider/sdk/copilot/responses/tool/web-search-preview.ts +103 -0
  483. package/src/provider/sdk/copilot/responses/tool/web-search.ts +102 -0
  484. package/src/provider/transform.ts +1322 -0
  485. package/src/pty/index.ts +364 -0
  486. package/src/pty/pty.bun.ts +26 -0
  487. package/src/pty/pty.node.ts +27 -0
  488. package/src/pty/pty.ts +25 -0
  489. package/src/pty/schema.ts +17 -0
  490. package/src/question/index.ts +252 -0
  491. package/src/question/schema.ts +17 -0
  492. package/src/server/adapter.bun.ts +40 -0
  493. package/src/server/adapter.node.ts +66 -0
  494. package/src/server/adapter.ts +21 -0
  495. package/src/server/error.ts +53 -0
  496. package/src/server/event.ts +7 -0
  497. package/src/server/fence.ts +81 -0
  498. package/src/server/mdns.ts +60 -0
  499. package/src/server/middleware.ts +92 -0
  500. package/src/server/projectors.ts +28 -0
  501. package/src/server/proxy.ts +171 -0
  502. package/src/server/routes/control/index.ts +160 -0
  503. package/src/server/routes/control/workspace.ts +203 -0
  504. package/src/server/routes/global.ts +287 -0
  505. package/src/server/routes/instance/bash-interactive.ts +82 -0
  506. package/src/server/routes/instance/config.ts +89 -0
  507. package/src/server/routes/instance/event.ts +88 -0
  508. package/src/server/routes/instance/experimental.ts +408 -0
  509. package/src/server/routes/instance/file.ts +190 -0
  510. package/src/server/routes/instance/httpapi/config.ts +51 -0
  511. package/src/server/routes/instance/httpapi/permission.ts +72 -0
  512. package/src/server/routes/instance/httpapi/project.ts +62 -0
  513. package/src/server/routes/instance/httpapi/provider.ts +142 -0
  514. package/src/server/routes/instance/httpapi/question.ts +121 -0
  515. package/src/server/routes/instance/httpapi/server.ts +136 -0
  516. package/src/server/routes/instance/index.ts +301 -0
  517. package/src/server/routes/instance/mcp.ts +260 -0
  518. package/src/server/routes/instance/middleware.ts +35 -0
  519. package/src/server/routes/instance/permission.ts +73 -0
  520. package/src/server/routes/instance/project.ts +122 -0
  521. package/src/server/routes/instance/provider.ts +158 -0
  522. package/src/server/routes/instance/pty.ts +247 -0
  523. package/src/server/routes/instance/question.ts +162 -0
  524. package/src/server/routes/instance/session.ts +1296 -0
  525. package/src/server/routes/instance/sync.ts +143 -0
  526. package/src/server/routes/instance/trace.ts +59 -0
  527. package/src/server/routes/instance/tui.ts +384 -0
  528. package/src/server/routes/instance/workflows.ts +72 -0
  529. package/src/server/routes/ui.ts +55 -0
  530. package/src/server/server.ts +136 -0
  531. package/src/server/workspace.ts +122 -0
  532. package/src/session/auto-dream.ts +123 -0
  533. package/src/session/boundary.ts +77 -0
  534. package/src/session/budgeted-read.ts +118 -0
  535. package/src/session/checkpoint-align.ts +29 -0
  536. package/src/session/checkpoint-context.ts +36 -0
  537. package/src/session/checkpoint-paths.ts +86 -0
  538. package/src/session/checkpoint-progress-reconcile.ts +111 -0
  539. package/src/session/checkpoint-retry.ts +192 -0
  540. package/src/session/checkpoint-templates.ts +114 -0
  541. package/src/session/checkpoint-validator.ts +259 -0
  542. package/src/session/checkpoint.ts +1478 -0
  543. package/src/session/classify.ts +92 -0
  544. package/src/session/claude-import.sql.ts +13 -0
  545. package/src/session/claude-import.ts +379 -0
  546. package/src/session/compaction.ts +543 -0
  547. package/src/session/goal.ts +232 -0
  548. package/src/session/index.ts +1 -0
  549. package/src/session/instruction.ts +276 -0
  550. package/src/session/last-message-info.ts +32 -0
  551. package/src/session/llm-request-prefix.ts +82 -0
  552. package/src/session/llm.ts +735 -0
  553. package/src/session/max-mode.ts +397 -0
  554. package/src/session/message-v2.ts +1136 -0
  555. package/src/session/message.ts +191 -0
  556. package/src/session/overflow.ts +53 -0
  557. package/src/session/prefix-capture-ref.ts +48 -0
  558. package/src/session/processor.ts +962 -0
  559. package/src/session/projectors.ts +137 -0
  560. package/src/session/prompt/anthropic.txt +154 -0
  561. package/src/session/prompt/beast.txt +155 -0
  562. package/src/session/prompt/build-switch.txt +5 -0
  563. package/src/session/prompt/codex.txt +79 -0
  564. package/src/session/prompt/compose.txt +115 -0
  565. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  566. package/src/session/prompt/default.txt +151 -0
  567. package/src/session/prompt/gemini.txt +155 -0
  568. package/src/session/prompt/gpt.txt +107 -0
  569. package/src/session/prompt/kimi.txt +95 -0
  570. package/src/session/prompt/max-steps.txt +16 -0
  571. package/src/session/prompt/trinity.txt +97 -0
  572. package/src/session/prompt.ts +3355 -0
  573. package/src/session/prune.ts +481 -0
  574. package/src/session/retry.ts +166 -0
  575. package/src/session/revert.ts +161 -0
  576. package/src/session/run-state.ts +135 -0
  577. package/src/session/schema.ts +36 -0
  578. package/src/session/session.sql.ts +110 -0
  579. package/src/session/session.ts +908 -0
  580. package/src/session/status.ts +89 -0
  581. package/src/session/summary.ts +163 -0
  582. package/src/session/system.ts +86 -0
  583. package/src/session/todo.ts +77 -0
  584. package/src/share/index.ts +2 -0
  585. package/src/share/session.ts +57 -0
  586. package/src/share/share-next.ts +381 -0
  587. package/src/share/share.sql.ts +13 -0
  588. package/src/shell/shell.ts +110 -0
  589. package/src/skill/compose/.bundle/ask/SKILL.md +58 -0
  590. package/src/skill/compose/.bundle/brainstorm/SKILL.md +220 -0
  591. package/src/skill/compose/.bundle/brainstorm/scripts/frame-template.html +214 -0
  592. package/src/skill/compose/.bundle/brainstorm/scripts/helper.js +88 -0
  593. package/src/skill/compose/.bundle/brainstorm/scripts/server.cjs +354 -0
  594. package/src/skill/compose/.bundle/brainstorm/scripts/start-server.sh +148 -0
  595. package/src/skill/compose/.bundle/brainstorm/scripts/stop-server.sh +56 -0
  596. package/src/skill/compose/.bundle/brainstorm/spec-document-reviewer-prompt.md +50 -0
  597. package/src/skill/compose/.bundle/brainstorm/visual-companion.md +287 -0
  598. package/src/skill/compose/.bundle/debug/CREATION-LOG.md +119 -0
  599. package/src/skill/compose/.bundle/debug/SKILL.md +297 -0
  600. package/src/skill/compose/.bundle/debug/condition-based-waiting-example.ts +158 -0
  601. package/src/skill/compose/.bundle/debug/condition-based-waiting.md +115 -0
  602. package/src/skill/compose/.bundle/debug/defense-in-depth.md +122 -0
  603. package/src/skill/compose/.bundle/debug/find-polluter.sh +63 -0
  604. package/src/skill/compose/.bundle/debug/root-cause-tracing.md +169 -0
  605. package/src/skill/compose/.bundle/debug/test-academic.md +14 -0
  606. package/src/skill/compose/.bundle/debug/test-pressure-1.md +58 -0
  607. package/src/skill/compose/.bundle/debug/test-pressure-2.md +68 -0
  608. package/src/skill/compose/.bundle/debug/test-pressure-3.md +69 -0
  609. package/src/skill/compose/.bundle/execute/SKILL.md +71 -0
  610. package/src/skill/compose/.bundle/feedback/SKILL.md +214 -0
  611. package/src/skill/compose/.bundle/merge/SKILL.md +252 -0
  612. package/src/skill/compose/.bundle/new-skill/SKILL.md +656 -0
  613. package/src/skill/compose/.bundle/new-skill/anthropic-best-practices.md +1150 -0
  614. package/src/skill/compose/.bundle/new-skill/examples/CLAUDE_MD_TESTING.md +189 -0
  615. package/src/skill/compose/.bundle/new-skill/graphviz-conventions.dot +172 -0
  616. package/src/skill/compose/.bundle/new-skill/persuasion-principles.md +187 -0
  617. package/src/skill/compose/.bundle/new-skill/render-graphs.js +168 -0
  618. package/src/skill/compose/.bundle/new-skill/testing-skills-with-subagents.md +384 -0
  619. package/src/skill/compose/.bundle/parallel/SKILL.md +182 -0
  620. package/src/skill/compose/.bundle/plan/SKILL.md +161 -0
  621. package/src/skill/compose/.bundle/plan/plan-document-reviewer-prompt.md +50 -0
  622. package/src/skill/compose/.bundle/report/SKILL.md +180 -0
  623. package/src/skill/compose/.bundle/review/SKILL.md +104 -0
  624. package/src/skill/compose/.bundle/review/code-reviewer.md +171 -0
  625. package/src/skill/compose/.bundle/subagent/SKILL.md +344 -0
  626. package/src/skill/compose/.bundle/subagent/code-quality-reviewer-prompt.md +24 -0
  627. package/src/skill/compose/.bundle/subagent/implementer-prompt.md +126 -0
  628. package/src/skill/compose/.bundle/subagent/spec-reviewer-prompt.md +112 -0
  629. package/src/skill/compose/.bundle/tdd/SKILL.md +372 -0
  630. package/src/skill/compose/.bundle/tdd/testing-anti-patterns.md +299 -0
  631. package/src/skill/compose/.bundle/verify/SKILL.md +140 -0
  632. package/src/skill/compose/.bundle/worktree/SKILL.md +234 -0
  633. package/src/skill/compose/LICENSE-karpathy +28 -0
  634. package/src/skill/compose/LICENSE-superpowers +26 -0
  635. package/src/skill/compose/bundle.macro.ts +30 -0
  636. package/src/skill/compose/extract.ts +85 -0
  637. package/src/skill/discovery.ts +116 -0
  638. package/src/skill/index.ts +311 -0
  639. package/src/snapshot/index.ts +777 -0
  640. package/src/sql.d.ts +4 -0
  641. package/src/storage/db.bun.ts +8 -0
  642. package/src/storage/db.node.ts +8 -0
  643. package/src/storage/db.ts +172 -0
  644. package/src/storage/index.ts +26 -0
  645. package/src/storage/json-migration.ts +426 -0
  646. package/src/storage/schema.sql.ts +10 -0
  647. package/src/storage/schema.ts +7 -0
  648. package/src/storage/storage.ts +331 -0
  649. package/src/sync/README.md +179 -0
  650. package/src/sync/event.sql.ts +16 -0
  651. package/src/sync/index.ts +278 -0
  652. package/src/sync/schema.ts +14 -0
  653. package/src/task/events.ts +28 -0
  654. package/src/task/gate-state.ts +54 -0
  655. package/src/task/gate.ts +116 -0
  656. package/src/task/index.ts +1 -0
  657. package/src/task/registry.ts +387 -0
  658. package/src/task/schema.ts +43 -0
  659. package/src/task/task.sql.ts +50 -0
  660. package/src/team/events.ts +22 -0
  661. package/src/team/index.ts +113 -0
  662. package/src/team/schema.ts +31 -0
  663. package/src/temporary.ts +33 -0
  664. package/src/tool/actor.shell.txt +72 -0
  665. package/src/tool/actor.ts +803 -0
  666. package/src/tool/actor.txt +103 -0
  667. package/src/tool/apply_patch.ts +308 -0
  668. package/src/tool/apply_patch.txt +33 -0
  669. package/src/tool/bash-interactive.ts +183 -0
  670. package/src/tool/bash.ts +696 -0
  671. package/src/tool/bash.txt +123 -0
  672. package/src/tool/change-directory.ts +91 -0
  673. package/src/tool/codesearch.ts +63 -0
  674. package/src/tool/codesearch.txt +12 -0
  675. package/src/tool/edit.ts +685 -0
  676. package/src/tool/edit.txt +10 -0
  677. package/src/tool/external-directory.ts +132 -0
  678. package/src/tool/glob.ts +100 -0
  679. package/src/tool/glob.txt +6 -0
  680. package/src/tool/grep.ts +145 -0
  681. package/src/tool/grep.txt +8 -0
  682. package/src/tool/history.ts +146 -0
  683. package/src/tool/history.txt +17 -0
  684. package/src/tool/index.ts +4 -0
  685. package/src/tool/invalid.ts +20 -0
  686. package/src/tool/invocation-style.ts +17 -0
  687. package/src/tool/lsp.ts +91 -0
  688. package/src/tool/lsp.txt +19 -0
  689. package/src/tool/mcp-exa.ts +78 -0
  690. package/src/tool/memory-path-guard.ts +162 -0
  691. package/src/tool/memory.ts +81 -0
  692. package/src/tool/memory.txt +69 -0
  693. package/src/tool/multiedit.ts +61 -0
  694. package/src/tool/multiedit.txt +41 -0
  695. package/src/tool/plan-enter.txt +14 -0
  696. package/src/tool/plan-exit.txt +13 -0
  697. package/src/tool/plan.ts +90 -0
  698. package/src/tool/question.ts +67 -0
  699. package/src/tool/question.txt +10 -0
  700. package/src/tool/read.ts +327 -0
  701. package/src/tool/read.txt +14 -0
  702. package/src/tool/registry.ts +413 -0
  703. package/src/tool/schema.ts +17 -0
  704. package/src/tool/session-cwd.ts +35 -0
  705. package/src/tool/shell-tokenize.ts +346 -0
  706. package/src/tool/shell-wrap.ts +190 -0
  707. package/src/tool/skill.ts +76 -0
  708. package/src/tool/skill.txt +5 -0
  709. package/src/tool/task.shell.txt +57 -0
  710. package/src/tool/task.ts +456 -0
  711. package/src/tool/task.txt +56 -0
  712. package/src/tool/tool.ts +153 -0
  713. package/src/tool/truncate.ts +201 -0
  714. package/src/tool/truncation-dir.ts +4 -0
  715. package/src/tool/webfetch.ts +199 -0
  716. package/src/tool/webfetch.txt +13 -0
  717. package/src/tool/websearch/index.ts +104 -0
  718. package/src/tool/websearch/mimo.ts +118 -0
  719. package/src/tool/websearch/websearch.txt +14 -0
  720. package/src/tool/workflow.ts +164 -0
  721. package/src/tool/workflow.txt +25 -0
  722. package/src/tool/write.ts +88 -0
  723. package/src/tool/write.txt +9 -0
  724. package/src/util/abort.ts +35 -0
  725. package/src/util/archive.ts +15 -0
  726. package/src/util/color.ts +17 -0
  727. package/src/util/data-url.ts +9 -0
  728. package/src/util/defer.ts +10 -0
  729. package/src/util/effect-http-client.ts +11 -0
  730. package/src/util/effect-zod.ts +367 -0
  731. package/src/util/error.ts +78 -0
  732. package/src/util/filesystem.ts +243 -0
  733. package/src/util/fn.ts +21 -0
  734. package/src/util/format.ts +20 -0
  735. package/src/util/iife.ts +3 -0
  736. package/src/util/index.ts +12 -0
  737. package/src/util/keybind.ts +101 -0
  738. package/src/util/lazy.ts +18 -0
  739. package/src/util/local-context.ts +23 -0
  740. package/src/util/locale.ts +79 -0
  741. package/src/util/lock.ts +96 -0
  742. package/src/util/log.ts +197 -0
  743. package/src/util/media.ts +26 -0
  744. package/src/util/mimo-process.ts +24 -0
  745. package/src/util/network.ts +9 -0
  746. package/src/util/process.ts +174 -0
  747. package/src/util/queue.ts +32 -0
  748. package/src/util/record.ts +3 -0
  749. package/src/util/rpc.ts +64 -0
  750. package/src/util/schema.ts +53 -0
  751. package/src/util/scrap.ts +10 -0
  752. package/src/util/signal.ts +12 -0
  753. package/src/util/timeout.ts +14 -0
  754. package/src/util/token.ts +5 -0
  755. package/src/util/update-schema.ts +13 -0
  756. package/src/util/which.ts +14 -0
  757. package/src/util/wildcard.ts +57 -0
  758. package/src/workflow/builtin/deep-research.js +391 -0
  759. package/src/workflow/builtin.ts +54 -0
  760. package/src/workflow/events.ts +72 -0
  761. package/src/workflow/meta.ts +335 -0
  762. package/src/workflow/persistence.ts +312 -0
  763. package/src/workflow/resolve.ts +45 -0
  764. package/src/workflow/runtime-ref.ts +18 -0
  765. package/src/workflow/runtime.ts +1234 -0
  766. package/src/workflow/sandbox.ts +280 -0
  767. package/src/workflow/workflow.sql.ts +31 -0
  768. package/src/workflow/workspace.ts +69 -0
  769. package/src/worktree/index.ts +614 -0
  770. package/sst-env.d.ts +10 -0
  771. package/test/AGENTS.md +133 -0
  772. package/test/account/repo.test.ts +352 -0
  773. package/test/account/service.test.ts +456 -0
  774. package/test/acp/agent-interface.test.ts +51 -0
  775. package/test/acp/event-subscription.test.ts +725 -0
  776. package/test/actor/cancel-cascade.test.ts +432 -0
  777. package/test/actor/no-completion-listener.test.ts +41 -0
  778. package/test/actor/poststop-progress-write-permission.repro.test.ts +414 -0
  779. package/test/actor/registry-render.test.ts +113 -0
  780. package/test/actor/registry-status.test.ts +111 -0
  781. package/test/actor/registry.test.ts +619 -0
  782. package/test/actor/return-header.test.ts +40 -0
  783. package/test/actor/spawn-lifecycle.test.ts +346 -0
  784. package/test/actor/spawn-no-deadlock.test.ts +340 -0
  785. package/test/actor/spawn-notification.test.ts +393 -0
  786. package/test/actor/spawn-task-autostart.test.ts +530 -0
  787. package/test/actor/spawn.test.ts +1072 -0
  788. package/test/actor/status-event-payload.test.ts +132 -0
  789. package/test/actor/terminology.test.ts +39 -0
  790. package/test/actor/turn.test.ts +125 -0
  791. package/test/actor/waiter.test.ts +246 -0
  792. package/test/agent/agent.test.ts +874 -0
  793. package/test/agent/allowlist.test.ts +45 -0
  794. package/test/auth/auth.test.ts +86 -0
  795. package/test/bus/bus-effect.test.ts +162 -0
  796. package/test/bus/bus-integration.test.ts +87 -0
  797. package/test/bus/bus.test.ts +219 -0
  798. package/test/cli/account.test.ts +26 -0
  799. package/test/cli/cmd/tui/prompt-part.test.ts +47 -0
  800. package/test/cli/error.test.ts +18 -0
  801. package/test/cli/github-action.test.ts +198 -0
  802. package/test/cli/github-remote.test.ts +80 -0
  803. package/test/cli/import.test.ts +54 -0
  804. package/test/cli/plugin-auth-picker.test.ts +120 -0
  805. package/test/cli/run-completion.test.ts +131 -0
  806. package/test/cli/tui/keybind-plugin.test.ts +90 -0
  807. package/test/cli/tui/plugin-add.test.ts +111 -0
  808. package/test/cli/tui/plugin-install.test.ts +87 -0
  809. package/test/cli/tui/plugin-lifecycle.test.ts +224 -0
  810. package/test/cli/tui/plugin-loader-entrypoint.test.ts +484 -0
  811. package/test/cli/tui/plugin-loader-pure.test.ts +71 -0
  812. package/test/cli/tui/plugin-loader.test.ts +816 -0
  813. package/test/cli/tui/plugin-toggle.test.ts +157 -0
  814. package/test/cli/tui/revert-diff.test.ts +35 -0
  815. package/test/cli/tui/route-agent-id.test.ts +26 -0
  816. package/test/cli/tui/sidebar-tps.test.ts +63 -0
  817. package/test/cli/tui/slot-replace.test.tsx +47 -0
  818. package/test/cli/tui/sync-bucket.test.ts +29 -0
  819. package/test/cli/tui/theme-store.test.ts +51 -0
  820. package/test/cli/tui/thread.test.ts +121 -0
  821. package/test/cli/tui/transcript.test.ts +426 -0
  822. package/test/cli/tui/use-event.test.tsx +175 -0
  823. package/test/cli/tui/voice.test.ts +269 -0
  824. package/test/command/deep-research-command.test.ts +16 -0
  825. package/test/config/agent-color.test.ts +77 -0
  826. package/test/config/checkpoint-fork.test.ts +21 -0
  827. package/test/config/config.test.ts +2577 -0
  828. package/test/config/fixtures/empty-frontmatter.md +4 -0
  829. package/test/config/fixtures/frontmatter.md +28 -0
  830. package/test/config/fixtures/markdown-header.md +11 -0
  831. package/test/config/fixtures/no-frontmatter.md +1 -0
  832. package/test/config/fixtures/weird-model-id.md +13 -0
  833. package/test/config/lsp.test.ts +87 -0
  834. package/test/config/markdown.test.ts +228 -0
  835. package/test/config/plugin.test.ts +0 -0
  836. package/test/config/tui.test.ts +627 -0
  837. package/test/control-plane/adaptors.test.ts +71 -0
  838. package/test/control-plane/sse.test.ts +56 -0
  839. package/test/effect/app-runtime-logger.test.ts +92 -0
  840. package/test/effect/cross-spawn-spawner.test.ts +411 -0
  841. package/test/effect/instance-state.test.ts +482 -0
  842. package/test/effect/observability.test.ts +46 -0
  843. package/test/effect/run-service.test.ts +46 -0
  844. package/test/effect/runner-warn-log.test.ts +111 -0
  845. package/test/effect/runner.test.ts +494 -0
  846. package/test/fake/provider.ts +90 -0
  847. package/test/file/fsmonitor.test.ts +68 -0
  848. package/test/file/ignore.test.ts +10 -0
  849. package/test/file/index.test.ts +956 -0
  850. package/test/file/path-traversal.test.ts +204 -0
  851. package/test/file/ripgrep.test.ts +214 -0
  852. package/test/file/watcher.test.ts +249 -0
  853. package/test/filesystem/filesystem.test.ts +319 -0
  854. package/test/fixture/db.ts +11 -0
  855. package/test/fixture/fixture.test.ts +58 -0
  856. package/test/fixture/fixture.ts +190 -0
  857. package/test/fixture/flock-worker.ts +72 -0
  858. package/test/fixture/lsp/fake-lsp-server.js +75 -0
  859. package/test/fixture/plug-worker.ts +93 -0
  860. package/test/fixture/plugin-meta-worker.ts +19 -0
  861. package/test/fixture/skills/agents-sdk/SKILL.md +152 -0
  862. package/test/fixture/skills/agents-sdk/references/callable.md +92 -0
  863. package/test/fixture/skills/cloudflare/SKILL.md +211 -0
  864. package/test/fixture/skills/index.json +6 -0
  865. package/test/fixture/tui-plugin.ts +328 -0
  866. package/test/fixture/tui-runtime.ts +31 -0
  867. package/test/format/format.test.ts +244 -0
  868. package/test/git/git.test.ts +128 -0
  869. package/test/global/fixture/global-paths-worker.ts +17 -0
  870. package/test/global/mimocode-home.test.ts +143 -0
  871. package/test/history/backfill.test.ts +149 -0
  872. package/test/history/extract.test.ts +106 -0
  873. package/test/history/fts-query.test.ts +30 -0
  874. package/test/history/resolve.test.ts +130 -0
  875. package/test/history/service.test.ts +210 -0
  876. package/test/history/writer.test.ts +163 -0
  877. package/test/ide/ide.test.ts +82 -0
  878. package/test/inbox/drain-in-loop.test.ts +230 -0
  879. package/test/inbox/fork-agent-compat.test.ts +387 -0
  880. package/test/inbox/gc-on-init.test.ts +167 -0
  881. package/test/inbox/send-no-block.test.ts +120 -0
  882. package/test/inbox/sender-cancel-independence.test.ts +160 -0
  883. package/test/inbox/wake-matrix.test.ts +141 -0
  884. package/test/installation/installation.test.ts +226 -0
  885. package/test/keybind.test.ts +421 -0
  886. package/test/lib/effect.ts +53 -0
  887. package/test/lib/filesystem.ts +10 -0
  888. package/test/lib/llm-server.ts +770 -0
  889. package/test/lib/scripted-llm-server.ts +245 -0
  890. package/test/lsp/client.test.ts +98 -0
  891. package/test/lsp/index.test.ts +109 -0
  892. package/test/lsp/launch.test.ts +22 -0
  893. package/test/lsp/lifecycle.test.ts +184 -0
  894. package/test/mcp/headers.test.ts +178 -0
  895. package/test/mcp/lifecycle.test.ts +824 -0
  896. package/test/mcp/oauth-auto-connect.test.ts +281 -0
  897. package/test/mcp/oauth-browser.test.ts +268 -0
  898. package/test/mcp/oauth-callback.test.ts +34 -0
  899. package/test/memory/abort-leak-webfetch.ts +49 -0
  900. package/test/memory/abort-leak.test.ts +127 -0
  901. package/test/memory/cc-frontmatter.test.ts +85 -0
  902. package/test/memory/cc-paths.test.ts +60 -0
  903. package/test/memory/cc-reconcile.test.ts +239 -0
  904. package/test/memory/cc-search.test.ts +151 -0
  905. package/test/memory/fts-query.test.ts +48 -0
  906. package/test/memory/fts-rowid-stability.test.ts +271 -0
  907. package/test/memory/paths.test.ts +210 -0
  908. package/test/memory/reconcile.test.ts +115 -0
  909. package/test/memory/service.test.ts +169 -0
  910. package/test/npm.test.ts +18 -0
  911. package/test/patch/patch.test.ts +348 -0
  912. package/test/permission/abort.test.ts +116 -0
  913. package/test/permission/arity.test.ts +33 -0
  914. package/test/permission/disabled.test.ts +51 -0
  915. package/test/permission/next.test.ts +1080 -0
  916. package/test/permission/non-interactive.test.ts +55 -0
  917. package/test/permission-task.test.ts +326 -0
  918. package/test/plugin/actor-hooks.test.ts +1471 -0
  919. package/test/plugin/auth-override.test.ts +79 -0
  920. package/test/plugin/checkpoint-splitover.test.ts +434 -0
  921. package/test/plugin/cloudflare.test.ts +68 -0
  922. package/test/plugin/codex.test.ts +123 -0
  923. package/test/plugin/github-copilot-models.test.ts +163 -0
  924. package/test/plugin/install-concurrency.test.ts +140 -0
  925. package/test/plugin/install.test.ts +570 -0
  926. package/test/plugin/loader-shared.test.ts +1169 -0
  927. package/test/plugin/matcher.test.ts +97 -0
  928. package/test/plugin/meta.test.ts +137 -0
  929. package/test/plugin/mimo.test.ts +257 -0
  930. package/test/plugin/shared.test.ts +88 -0
  931. package/test/plugin/subagent-progress-checker.test.ts +227 -0
  932. package/test/plugin/trigger.test.ts +116 -0
  933. package/test/plugin/workspace-adaptor.test.ts +109 -0
  934. package/test/preload.ts +102 -0
  935. package/test/project/migrate-global.test.ts +150 -0
  936. package/test/project/project-id.test.ts +64 -0
  937. package/test/project/project.test.ts +481 -0
  938. package/test/project/vcs.test.ts +286 -0
  939. package/test/project/worktree-remove.test.ts +126 -0
  940. package/test/project/worktree.test.ts +214 -0
  941. package/test/provider/amazon-bedrock.test.ts +462 -0
  942. package/test/provider/copilot/convert-to-copilot-messages.test.ts +523 -0
  943. package/test/provider/copilot/copilot-chat-model.test.ts +592 -0
  944. package/test/provider/error.test.ts +160 -0
  945. package/test/provider/gitlab-duo.test.ts +413 -0
  946. package/test/provider/model-groups.test.ts +389 -0
  947. package/test/provider/provider-chunk-timeout.test.ts +23 -0
  948. package/test/provider/provider.test.ts +2648 -0
  949. package/test/provider/transform.test.ts +3379 -0
  950. package/test/pty/pty-output-isolation.test.ts +146 -0
  951. package/test/pty/pty-session.test.ts +102 -0
  952. package/test/pty/pty-shell.test.ts +69 -0
  953. package/test/question/question.test.ts +464 -0
  954. package/test/server/global-session-list.test.ts +105 -0
  955. package/test/server/project-init-git.test.ts +122 -0
  956. package/test/server/session-actions.test.ts +49 -0
  957. package/test/server/session-list.test.ts +110 -0
  958. package/test/server/session-messages.test.ts +220 -0
  959. package/test/server/session-prompt-busy.test.ts +146 -0
  960. package/test/server/session-select.test.ts +100 -0
  961. package/test/server/session-task-route.test.ts +165 -0
  962. package/test/server/summarize-route-main-slice.test.ts +99 -0
  963. package/test/server/trace-attributes.test.ts +76 -0
  964. package/test/server/workflows-route.test.ts +279 -0
  965. package/test/session/bootstrap-skip-system.test.ts +121 -0
  966. package/test/session/boundary.test.ts +33 -0
  967. package/test/session/budgeted-read.test.ts +74 -0
  968. package/test/session/checkpoint-align.test.ts +58 -0
  969. package/test/session/checkpoint-boundary.test.ts +186 -0
  970. package/test/session/checkpoint-child-session.test.ts +508 -0
  971. package/test/session/checkpoint-context.test.ts +141 -0
  972. package/test/session/checkpoint-drain.test.ts +188 -0
  973. package/test/session/checkpoint-extract-titles.test.ts +58 -0
  974. package/test/session/checkpoint-fork-mode.test.ts +576 -0
  975. package/test/session/checkpoint-main-slice.test.ts +259 -0
  976. package/test/session/checkpoint-paths.test.ts +78 -0
  977. package/test/session/checkpoint-permission.test.ts +136 -0
  978. package/test/session/checkpoint-progress-reconcile.test.ts +219 -0
  979. package/test/session/checkpoint-rebuild-unify.test.ts +143 -0
  980. package/test/session/checkpoint-rebuild-v3.test.ts +248 -0
  981. package/test/session/checkpoint-render-verify.test.ts +512 -0
  982. package/test/session/checkpoint-retry.test.ts +150 -0
  983. package/test/session/checkpoint-splitover-integration.test.ts +533 -0
  984. package/test/session/checkpoint-templates.test.ts +51 -0
  985. package/test/session/checkpoint-thresholds.test.ts +120 -0
  986. package/test/session/checkpoint-validator.test.ts +189 -0
  987. package/test/session/classify-integration.test.ts +476 -0
  988. package/test/session/classify.test.ts +335 -0
  989. package/test/session/compaction-agent-scope.test.ts +164 -0
  990. package/test/session/context-inheritance.test.ts +46 -0
  991. package/test/session/fork-prefix-invariant.test.ts +116 -0
  992. package/test/session/goal.test.ts +106 -0
  993. package/test/session/instruction.test.ts +387 -0
  994. package/test/session/invalid-output-continuation.test.ts +150 -0
  995. package/test/session/last-message-info.test.ts +47 -0
  996. package/test/session/length-tool-safety.test.ts +121 -0
  997. package/test/session/llm-request-prefix.test.ts +197 -0
  998. package/test/session/llm-retry.test.ts +59 -0
  999. package/test/session/llm-system-prompt.test.ts +479 -0
  1000. package/test/session/llm.test.ts +1272 -0
  1001. package/test/session/main-lifecycle.test.ts +51 -0
  1002. package/test/session/main-runloop-history-invariant.test.ts +182 -0
  1003. package/test/session/max-mode-econnreset.test.ts +229 -0
  1004. package/test/session/max-mode.test.ts +54 -0
  1005. package/test/session/message-v2-filter.test.ts +197 -0
  1006. package/test/session/message-v2.test.ts +1119 -0
  1007. package/test/session/messages-default-main.test.ts +105 -0
  1008. package/test/session/messages-pagination.test.ts +888 -0
  1009. package/test/session/overflow.test.ts +576 -0
  1010. package/test/session/processor-effect.test.ts +853 -0
  1011. package/test/session/prompt-effect.test.ts +1574 -0
  1012. package/test/session/prompt-rebuild-loop.test.ts +108 -0
  1013. package/test/session/prompt-rebuild-reset.test.ts +67 -0
  1014. package/test/session/prompt-sweep.test.ts +145 -0
  1015. package/test/session/prompt-task-gate.test.ts +127 -0
  1016. package/test/session/prompt.test.ts +703 -0
  1017. package/test/session/prune-main-slice.test.ts +272 -0
  1018. package/test/session/prune-skip-system.test.ts +346 -0
  1019. package/test/session/prune.test.ts +419 -0
  1020. package/test/session/rebuild-microcompact.test.ts +318 -0
  1021. package/test/session/recall-reminder.test.ts +37 -0
  1022. package/test/session/retry.test.ts +410 -0
  1023. package/test/session/revert-compact.test.ts +639 -0
  1024. package/test/session/run-state-tuple-key.test.ts +152 -0
  1025. package/test/session/session-create-registers-main.test.ts +70 -0
  1026. package/test/session/session.test.ts +181 -0
  1027. package/test/session/snapshot-tool-race.test.ts +301 -0
  1028. package/test/session/structured-output-integration.test.ts +264 -0
  1029. package/test/session/structured-output-retry.test.ts +127 -0
  1030. package/test/session/structured-output.test.ts +397 -0
  1031. package/test/session/summary-main-slice.test.ts +170 -0
  1032. package/test/session/system.test.ts +72 -0
  1033. package/test/share/share-next.test.ts +332 -0
  1034. package/test/shell/shell.test.ts +73 -0
  1035. package/test/skill/compose-review.test.ts +141 -0
  1036. package/test/skill/discovery.test.ts +116 -0
  1037. package/test/skill/skill.test.ts +465 -0
  1038. package/test/snapshot/snapshot.test.ts +1531 -0
  1039. package/test/storage/db.test.ts +16 -0
  1040. package/test/storage/json-migration.test.ts +831 -0
  1041. package/test/storage/storage.test.ts +293 -0
  1042. package/test/sync/index.test.ts +237 -0
  1043. package/test/task/gate-state.test.ts +66 -0
  1044. package/test/task/gate.test.ts +167 -0
  1045. package/test/task/registry.test.ts +152 -0
  1046. package/test/task/state-machine.test.ts +292 -0
  1047. package/test/team/migrate-to-inbox.test.ts +124 -0
  1048. package/test/team/team.test.ts +75 -0
  1049. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  1050. package/test/tool/actor-cancel.test.ts +206 -0
  1051. package/test/tool/actor-recover.test.ts +50 -0
  1052. package/test/tool/actor-send.test.ts +200 -0
  1053. package/test/tool/actor-status.test.ts +296 -0
  1054. package/test/tool/actor-wait.test.ts +193 -0
  1055. package/test/tool/actor.shell.test.ts +250 -0
  1056. package/test/tool/actor.test.ts +748 -0
  1057. package/test/tool/apply_patch.test.ts +626 -0
  1058. package/test/tool/bash.test.ts +1195 -0
  1059. package/test/tool/describe-workflow.test.ts +12 -0
  1060. package/test/tool/edit.test.ts +691 -0
  1061. package/test/tool/external-directory.test.ts +207 -0
  1062. package/test/tool/fixtures/large-image.png +0 -0
  1063. package/test/tool/fixtures/models-api.json +65179 -0
  1064. package/test/tool/glob.test.ts +81 -0
  1065. package/test/tool/grep.test.ts +114 -0
  1066. package/test/tool/history.test.ts +144 -0
  1067. package/test/tool/invocation-style.test.ts +30 -0
  1068. package/test/tool/memory-edit-ask-skip.test.ts +62 -0
  1069. package/test/tool/memory-path-guard.test.ts +594 -0
  1070. package/test/tool/memory.test.ts +71 -0
  1071. package/test/tool/question.test.ts +167 -0
  1072. package/test/tool/read.test.ts +483 -0
  1073. package/test/tool/registry-invocation-style.test.ts +121 -0
  1074. package/test/tool/registry.test.ts +164 -0
  1075. package/test/tool/shell-tokenize.test.ts +273 -0
  1076. package/test/tool/shell-wrap-missing-script.test.ts +128 -0
  1077. package/test/tool/shell-wrap.test.ts +257 -0
  1078. package/test/tool/skill.test.ts +99 -0
  1079. package/test/tool/task-recover.test.ts +36 -0
  1080. package/test/tool/task.shell.test.ts +234 -0
  1081. package/test/tool/task.test.ts +296 -0
  1082. package/test/tool/tool-def-shell-shape.test.ts +23 -0
  1083. package/test/tool/tool-define.test.ts +59 -0
  1084. package/test/tool/truncation.test.ts +253 -0
  1085. package/test/tool/webfetch.test.ts +103 -0
  1086. package/test/tool/whitelist.test.ts +373 -0
  1087. package/test/tool/write.test.ts +244 -0
  1088. package/test/util/data-url.test.ts +14 -0
  1089. package/test/util/effect-zod.test.ts +869 -0
  1090. package/test/util/error.test.ts +38 -0
  1091. package/test/util/filesystem.test.ts +656 -0
  1092. package/test/util/format.test.ts +59 -0
  1093. package/test/util/glob.test.ts +164 -0
  1094. package/test/util/iife.test.ts +36 -0
  1095. package/test/util/lazy.test.ts +50 -0
  1096. package/test/util/lock.test.ts +72 -0
  1097. package/test/util/log.test.ts +44 -0
  1098. package/test/util/module.test.ts +59 -0
  1099. package/test/util/process.test.ts +128 -0
  1100. package/test/util/timeout.test.ts +21 -0
  1101. package/test/util/which.test.ts +100 -0
  1102. package/test/util/wildcard.test.ts +90 -0
  1103. package/test/workflow/builtin.test.ts +22 -0
  1104. package/test/workflow/deep-research-cluster.test.ts +47 -0
  1105. package/test/workflow/lib.ts +243 -0
  1106. package/test/workflow/meta.test.ts +142 -0
  1107. package/test/workflow/model-routing.test.ts +68 -0
  1108. package/test/workflow/persistence.test.ts +229 -0
  1109. package/test/workflow/resolve.test.ts +37 -0
  1110. package/test/workflow/runtime-nested.test.ts +419 -0
  1111. package/test/workflow/runtime-worktree.test.ts +261 -0
  1112. package/test/workflow/runtime.test.ts +1078 -0
  1113. package/test/workflow/sandbox.test.ts +259 -0
  1114. package/test/workflow/tool.test.ts +473 -0
  1115. package/test/workflow/verify-wow.test.ts +144 -0
  1116. package/test/workflow/workspace.test.ts +88 -0
  1117. package/test/workspace/workspace-restore.test.ts +281 -0
  1118. package/test/worktree/index.test.ts +30 -0
  1119. package/tsconfig.json +24 -0
@@ -0,0 +1,1322 @@
1
+ import type { ModelMessage } from "ai"
2
+ import { mergeDeep, unique } from "remeda"
3
+ import type { JSONSchema7 } from "@ai-sdk/provider"
4
+ import type { JSONSchema } from "zod/v4/core"
5
+ import type * as Provider from "./provider"
6
+ import type * as ModelsDev from "./models"
7
+ import { iife } from "@/util/iife"
8
+ import { Flag } from "@/flag/flag"
9
+
10
+ type Modality = NonNullable<ModelsDev.Model["modalities"]>["input"][number]
11
+
12
+ function mimeToModality(mime: string): Modality | undefined {
13
+ if (mime.startsWith("image/")) return "image"
14
+ if (mime.startsWith("audio/")) return "audio"
15
+ if (mime.startsWith("video/")) return "video"
16
+ if (mime === "application/pdf") return "pdf"
17
+ return undefined
18
+ }
19
+
20
+ // MiMo vision support isn't reflected in models.dev modality data, so the
21
+ // generic capability check would strip images before they reach the model.
22
+ // tuling-ai models support images
23
+ function supportsImageInput(model: Provider.Model): boolean {
24
+ if (model.providerID === "tuling-ai") {
25
+ const id = model.id.toLowerCase()
26
+ if (id.includes("v2.5-pro")) return false
27
+ if (id.includes("v2.5")) return true
28
+ }
29
+ // Claude and GPT models are all multimodal regardless of catalog data.
30
+ const id = model.id.toLowerCase()
31
+ const apiID = model.api.id.toLowerCase()
32
+ if (id.includes("claude") || apiID.includes("claude") || model.providerID === "anthropic") return true
33
+ if (id.includes("gpt") || apiID.includes("gpt")) return true
34
+ return model.capabilities.input.image
35
+ }
36
+
37
+ export const OUTPUT_TOKEN_MAX = Flag.tulingcode_EXPERIMENTAL_OUTPUT_TOKEN_MAX || 32_000
38
+ const MIMO_OUTPUT_TOKEN_MAX = 128_000
39
+
40
+ // Maps npm package to the key the AI SDK expects for providerOptions
41
+ function sdkKey(npm: string): string | undefined {
42
+ switch (npm) {
43
+ case "@ai-sdk/github-copilot":
44
+ return "copilot"
45
+ case "@ai-sdk/azure":
46
+ return "azure"
47
+ case "@ai-sdk/openai":
48
+ return "openai"
49
+ case "@ai-sdk/amazon-bedrock":
50
+ return "bedrock"
51
+ case "@ai-sdk/anthropic":
52
+ case "@ai-sdk/google-vertex/anthropic":
53
+ return "anthropic"
54
+ case "@ai-sdk/google-vertex":
55
+ return "vertex"
56
+ case "@ai-sdk/google":
57
+ return "google"
58
+ case "@ai-sdk/gateway":
59
+ return "gateway"
60
+ case "@openrouter/ai-sdk-provider":
61
+ return "openrouter"
62
+ }
63
+ return undefined
64
+ }
65
+
66
+ function normalizeMessages(
67
+ msgs: ModelMessage[],
68
+ model: Provider.Model,
69
+ _options: Record<string, unknown>,
70
+ ): ModelMessage[] {
71
+ // Anthropic rejects messages with empty content - filter out empty string messages
72
+ // and remove empty text/reasoning parts from array content
73
+ if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/amazon-bedrock") {
74
+ msgs = msgs
75
+ .map((msg) => {
76
+ if (typeof msg.content === "string") {
77
+ if (msg.content === "") return undefined
78
+ return msg
79
+ }
80
+ if (!Array.isArray(msg.content)) return msg
81
+ const filtered = msg.content.filter((part) => {
82
+ if (part.type === "text" || part.type === "reasoning") {
83
+ return part.text !== ""
84
+ }
85
+ return true
86
+ })
87
+ if (filtered.length === 0) return undefined
88
+ return { ...msg, content: filtered }
89
+ })
90
+ .filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "")
91
+ }
92
+
93
+ if (model.api.id.includes("claude")) {
94
+ const scrub = (id: string) => id.replace(/[^a-zA-Z0-9_-]/g, "_")
95
+ msgs = msgs.map((msg) => {
96
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
97
+ return {
98
+ ...msg,
99
+ content: msg.content.map((part) => {
100
+ if (part.type === "tool-call" || part.type === "tool-result") {
101
+ return { ...part, toolCallId: scrub(part.toolCallId) }
102
+ }
103
+ return part
104
+ }),
105
+ }
106
+ }
107
+ if (msg.role === "tool" && Array.isArray(msg.content)) {
108
+ return {
109
+ ...msg,
110
+ content: msg.content.map((part) => {
111
+ if (part.type === "tool-result") {
112
+ return { ...part, toolCallId: scrub(part.toolCallId) }
113
+ }
114
+ return part
115
+ }),
116
+ }
117
+ }
118
+ return msg
119
+ })
120
+ }
121
+ if (["@ai-sdk/anthropic", "@ai-sdk/google-vertex/anthropic"].includes(model.api.npm)) {
122
+ // Anthropic rejects assistant turns where tool_use blocks are followed by non-tool
123
+ // content, e.g. [tool_use, tool_use, text], with:
124
+ // `tool_use` ids were found without `tool_result` blocks immediately after...
125
+ //
126
+ // Reorder that invalid shape into [text] + [tool_use, tool_use]. Consecutive
127
+ // assistant messages are later merged by the provider/SDK, so preserving the
128
+ // original [tool_use...] then [text] order still produces the invalid payload.
129
+ //
130
+ // The root cause appears to be somewhere upstream where the stream is originally
131
+ // processed. We were unable to locate an exact narrower reproduction elsewhere,
132
+ // so we keep this transform in place for the time being.
133
+ msgs = msgs.flatMap((msg) => {
134
+ if (msg.role !== "assistant" || !Array.isArray(msg.content)) return [msg]
135
+
136
+ const parts = msg.content
137
+ const first = parts.findIndex((part) => part.type === "tool-call")
138
+ if (first === -1) return [msg]
139
+ if (!parts.slice(first).some((part) => part.type !== "tool-call")) return [msg]
140
+ return [
141
+ { ...msg, content: parts.filter((part) => part.type !== "tool-call") },
142
+ { ...msg, content: parts.filter((part) => part.type === "tool-call") },
143
+ ]
144
+ })
145
+ }
146
+ if (
147
+ model.providerID === "mistral" ||
148
+ model.api.id.toLowerCase().includes("mistral") ||
149
+ model.api.id.toLocaleLowerCase().includes("devstral")
150
+ ) {
151
+ const scrub = (id: string) => {
152
+ return id
153
+ .replace(/[^a-zA-Z0-9]/g, "") // Remove non-alphanumeric characters
154
+ .substring(0, 9) // Take first 9 characters
155
+ .padEnd(9, "0") // Pad with zeros if less than 9 characters
156
+ }
157
+ const result: ModelMessage[] = []
158
+ for (let i = 0; i < msgs.length; i++) {
159
+ const msg = msgs[i]
160
+ const nextMsg = msgs[i + 1]
161
+
162
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
163
+ msg.content = msg.content.map((part) => {
164
+ if (part.type === "tool-call" || part.type === "tool-result") {
165
+ return { ...part, toolCallId: scrub(part.toolCallId) }
166
+ }
167
+ return part
168
+ })
169
+ }
170
+ if (msg.role === "tool" && Array.isArray(msg.content)) {
171
+ msg.content = msg.content.map((part) => {
172
+ if (part.type === "tool-result") {
173
+ return { ...part, toolCallId: scrub(part.toolCallId) }
174
+ }
175
+ return part
176
+ })
177
+ }
178
+ result.push(msg)
179
+
180
+ // Fix message sequence: tool messages cannot be followed by user messages
181
+ if (msg.role === "tool" && nextMsg?.role === "user") {
182
+ result.push({
183
+ role: "assistant",
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: "Done.",
188
+ },
189
+ ],
190
+ })
191
+ }
192
+ }
193
+ return result
194
+ }
195
+
196
+ if (typeof model.capabilities.interleaved === "object" && model.capabilities.interleaved.field) {
197
+ const field = model.capabilities.interleaved.field
198
+ return msgs.map((msg) => {
199
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
200
+ const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
201
+ const reasoningText = reasoningParts.map((part: any) => part.text).join("")
202
+
203
+ // Filter out reasoning parts from content
204
+ const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
205
+
206
+ // Include reasoning_content | reasoning_details directly on the message for all assistant messages
207
+ if (reasoningText) {
208
+ return {
209
+ ...msg,
210
+ content: filteredContent,
211
+ providerOptions: {
212
+ ...msg.providerOptions,
213
+ openaiCompatible: {
214
+ ...msg.providerOptions?.openaiCompatible,
215
+ [field]: reasoningText,
216
+ },
217
+ },
218
+ }
219
+ }
220
+
221
+ return {
222
+ ...msg,
223
+ content: filteredContent,
224
+ }
225
+ }
226
+
227
+ return msg
228
+ })
229
+ }
230
+
231
+ return msgs
232
+ }
233
+
234
+ // Determines whether a model's provider respects inline cache_control / cachePoint
235
+ // markers. Pure name matching (model.api.id.includes("claude")) is fragile — a Claude
236
+ // model behind an OpenAI-compatible proxy gets matched but markers are silently dropped.
237
+ // See upstream opencode#26786.
238
+ function supportsCacheMarkers(model: Provider.Model): boolean {
239
+ // Anthropic-only SDKs — always support inline markers
240
+ if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/google-vertex/anthropic") return true
241
+ if (model.providerID === "anthropic" || model.providerID === "google-vertex-anthropic") return true
242
+ // Bedrock cachePoint is a Converse API feature, works across model families
243
+ if (model.api.npm === "@ai-sdk/amazon-bedrock") return true
244
+ // Multi-model providers: only Anthropic/Claude models support cache markers
245
+ if (
246
+ model.api.npm === "@openrouter/ai-sdk-provider" ||
247
+ model.api.npm === "@ai-sdk/github-copilot" ||
248
+ model.api.npm === "@ai-sdk/alibaba"
249
+ ) {
250
+ return (
251
+ model.api.id.includes("claude") ||
252
+ model.api.id.includes("anthropic") ||
253
+ model.id.includes("claude") ||
254
+ model.id.includes("anthropic")
255
+ )
256
+ }
257
+ return false
258
+ }
259
+
260
+ function applyCaching(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
261
+ // Only Anthropic and OpenRouter expose a cache-control TTL in their AI SDK;
262
+ // the other providers ignore an unknown `ttl` field, so we only thread it
263
+ // into those two branches. Default (unset) stays the provider 5m default.
264
+ const ttl = model.cachePromptTTL === "1h" ? { ttl: "1h" as const } : {}
265
+ const providerOptions = {
266
+ anthropic: {
267
+ cacheControl: { type: "ephemeral", ...ttl },
268
+ },
269
+ openrouter: {
270
+ cacheControl: { type: "ephemeral", ...ttl },
271
+ },
272
+ bedrock: {
273
+ cachePoint: { type: "default" },
274
+ },
275
+ openaiCompatible: {
276
+ cache_control: { type: "ephemeral" },
277
+ },
278
+ copilot: {
279
+ copilot_cache_control: { type: "ephemeral" },
280
+ },
281
+ alibaba: {
282
+ cacheControl: { type: "ephemeral" },
283
+ },
284
+ }
285
+
286
+ // Strategy: place cache breakpoints at stable prefix boundaries (max 4 allowed by Anthropic)
287
+ // 1. Last system message — system prompt never changes
288
+ // 2. Midpoint of conversation history — long prefix second-level cache
289
+ // 3. Message before the last user message — stable history boundary
290
+ const targets: ModelMessage[] = []
291
+
292
+ const systemMsgs = msgs.filter((msg) => msg.role === "system")
293
+ if (systemMsgs.length > 0) targets.push(systemMsgs[systemMsgs.length - 1])
294
+
295
+ const nonSystem = msgs.filter((msg) => msg.role !== "system")
296
+ const lastUserIdx = nonSystem.findLastIndex((msg) => msg.role === "user")
297
+ if (lastUserIdx >= 1) {
298
+ targets.push(nonSystem[lastUserIdx - 1])
299
+ const midpoint = Math.floor(lastUserIdx / 2)
300
+ if (midpoint > 0 && midpoint < lastUserIdx - 1) targets.push(nonSystem[midpoint])
301
+ } else if (lastUserIdx === 0) {
302
+ targets.push(nonSystem[0])
303
+ }
304
+
305
+ for (const msg of unique(targets)) {
306
+ const useMessageLevelOptions =
307
+ model.providerID === "anthropic" ||
308
+ model.providerID.includes("bedrock") ||
309
+ model.api.npm === "@ai-sdk/amazon-bedrock"
310
+ const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(msg.content) && msg.content.length > 0
311
+
312
+ if (shouldUseContentOptions) {
313
+ const lastContent = msg.content[msg.content.length - 1]
314
+ if (
315
+ lastContent &&
316
+ typeof lastContent === "object" &&
317
+ lastContent.type !== "tool-approval-request" &&
318
+ lastContent.type !== "tool-approval-response"
319
+ ) {
320
+ lastContent.providerOptions = mergeDeep(lastContent.providerOptions ?? {}, providerOptions)
321
+ continue
322
+ }
323
+ }
324
+
325
+ msg.providerOptions = mergeDeep(msg.providerOptions ?? {}, providerOptions)
326
+ }
327
+
328
+ return msgs
329
+ }
330
+
331
+ function unsupportedParts(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
332
+ return msgs.map((msg) => {
333
+ if (msg.role !== "user" || !Array.isArray(msg.content)) return msg
334
+
335
+ const filtered = msg.content.map((part) => {
336
+ if (part.type !== "file" && part.type !== "image") return part
337
+
338
+ // Check for empty base64 image data
339
+ if (part.type === "image") {
340
+ const imageStr = String(part.image)
341
+ if (imageStr.startsWith("data:")) {
342
+ const match = imageStr.match(/^data:([^;]+);base64,(.*)$/)
343
+ if (match && (!match[2] || match[2].length === 0)) {
344
+ return {
345
+ type: "text" as const,
346
+ text: "ERROR: Image file is empty or corrupted. Please provide a valid image.",
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ const mime = part.type === "image" ? String(part.image).split(";")[0].replace("data:", "") : part.mediaType
353
+ const filename = part.type === "file" ? part.filename : undefined
354
+ const modality = mimeToModality(mime)
355
+ if (!modality) return part
356
+ const supported = modality === "image" ? supportsImageInput(model) : model.capabilities.input[modality]
357
+ if (supported) return part
358
+
359
+ const name = filename ? `"${filename}"` : modality
360
+ return {
361
+ type: "text" as const,
362
+ text: `ERROR: Cannot read ${name} (this model does not support ${modality} input). Inform the user.`,
363
+ }
364
+ })
365
+
366
+ return { ...msg, content: filtered }
367
+ })
368
+ }
369
+
370
+ // Returns the decoded byte size of a base64 data URL, or undefined for inputs
371
+ // that aren't data URLs (remote URLs, raw binary) and therefore can't be sized.
372
+ function imageByteSize(image: string): number | undefined {
373
+ if (!image.startsWith("data:")) return undefined
374
+ const base64 = image.slice(image.indexOf(",") + 1)
375
+ if (!base64) return 0
376
+ const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0
377
+ return Math.floor((base64.length * 3) / 4) - padding
378
+ }
379
+
380
+ function limitImages(msgs: ModelMessage[]): ModelMessage[] {
381
+ const maxImages = Flag.tulingcode_MAX_PROMPT_IMAGES
382
+ const maxSize = Flag.tulingcode_MAX_PROMPT_IMAGE_SIZE
383
+ if (maxImages === undefined && maxSize === undefined) return msgs
384
+
385
+ const total = msgs.reduce(
386
+ (sum, msg) =>
387
+ msg.role === "user" && Array.isArray(msg.content)
388
+ ? sum + msg.content.filter((part) => part.type === "image").length
389
+ : sum,
390
+ 0,
391
+ )
392
+ // Drop the oldest excess images so the most recent ones reach the model.
393
+ let toDrop = maxImages === undefined ? 0 : Math.max(0, total - maxImages)
394
+
395
+ return msgs.map((msg) => {
396
+ if (msg.role !== "user" || !Array.isArray(msg.content)) return msg
397
+ const content = msg.content.map((part) => {
398
+ if (part.type !== "image") return part
399
+ if (toDrop > 0) {
400
+ toDrop--
401
+ return { type: "text" as const, text: `[Image omitted: exceeds the configured limit of ${maxImages} prompt image(s).]` }
402
+ }
403
+ if (maxSize !== undefined) {
404
+ const size = imageByteSize(String(part.image))
405
+ if (size !== undefined && size > maxSize) {
406
+ return { type: "text" as const, text: `[Image omitted: exceeds the configured ${maxSize}-byte prompt image size limit.]` }
407
+ }
408
+ }
409
+ return part
410
+ })
411
+ return { ...msg, content }
412
+ })
413
+ }
414
+
415
+ export function message(msgs: ModelMessage[], model: Provider.Model, options: Record<string, unknown>) {
416
+ msgs = unsupportedParts(msgs, model)
417
+ msgs = limitImages(msgs)
418
+ msgs = normalizeMessages(msgs, model, options)
419
+ if (supportsCacheMarkers(model)) {
420
+ msgs = applyCaching(msgs, model)
421
+ }
422
+
423
+ // Remap providerOptions keys from stored providerID to expected SDK key
424
+ const key = sdkKey(model.api.npm)
425
+ if (key && key !== model.providerID) {
426
+ const remap = (opts: Record<string, any> | undefined) => {
427
+ if (!opts) return opts
428
+ if (!(model.providerID in opts)) return opts
429
+ const result = { ...opts }
430
+ result[key] = result[model.providerID]
431
+ delete result[model.providerID]
432
+ return result
433
+ }
434
+
435
+ msgs = msgs.map((msg) => {
436
+ if (!Array.isArray(msg.content)) return { ...msg, providerOptions: remap(msg.providerOptions) }
437
+ return {
438
+ ...msg,
439
+ providerOptions: remap(msg.providerOptions),
440
+ content: msg.content.map((part) => {
441
+ if (part.type === "tool-approval-request" || part.type === "tool-approval-response") {
442
+ return { ...part }
443
+ }
444
+ return { ...part, providerOptions: remap(part.providerOptions) }
445
+ }),
446
+ } as typeof msg
447
+ })
448
+ }
449
+
450
+ return msgs
451
+ }
452
+
453
+ export function temperature(model: Provider.Model) {
454
+ const id = model.id.toLowerCase()
455
+ if (id.includes("qwen")) return 0.55
456
+ if (id.includes("claude")) return undefined
457
+ if (id.includes("gemini")) return 1.0
458
+ if (id.includes("glm-4.6")) return 1.0
459
+ if (id.includes("glm-4.7")) return 1.0
460
+ if (id.includes("minimax-m2")) return 1.0
461
+ if (id.includes("mimo-v2.5")) return 1.0
462
+ if (id.includes("kimi-k2")) {
463
+ // kimi-k2-thinking & kimi-k2.5 && kimi-k2p5 && kimi-k2-5
464
+ if (["thinking", "k2.", "k2p", "k2-5"].some((s) => id.includes(s))) {
465
+ return 1.0
466
+ }
467
+ return 0.6
468
+ }
469
+ return undefined
470
+ }
471
+
472
+ export function topP(model: Provider.Model) {
473
+ const id = model.id.toLowerCase()
474
+ if (id.includes("qwen")) return 1
475
+ if (["minimax-m2", "gemini", "kimi-k2.5", "kimi-k2p5", "kimi-k2-5"].some((s) => id.includes(s))) {
476
+ return 0.95
477
+ }
478
+ return undefined
479
+ }
480
+
481
+ export function topK(model: Provider.Model) {
482
+ const id = model.id.toLowerCase()
483
+ if (id.includes("minimax-m2")) {
484
+ if (["m2.", "m25", "m21"].some((s) => id.includes(s))) return 40
485
+ return 20
486
+ }
487
+ if (id.includes("gemini")) return 64
488
+ return undefined
489
+ }
490
+
491
+ const WIDELY_SUPPORTED_EFFORTS = ["low", "medium", "high"]
492
+ const OPENAI_EFFORTS = ["none", "minimal", ...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
493
+
494
+ function anthropicAdaptiveEfforts(apiId: string): string[] | null {
495
+ if (["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => apiId.includes(v))) {
496
+ return ["low", "medium", "high", "xhigh", "max"]
497
+ }
498
+ if (["opus-4-6", "opus-4.6", "sonnet-4-6", "sonnet-4.6"].some((v) => apiId.includes(v))) {
499
+ return ["low", "medium", "high", "max"]
500
+ }
501
+ return null
502
+ }
503
+
504
+ export function variants(model: Provider.Model): Record<string, Record<string, any>> {
505
+ if (!model.capabilities.reasoning) return {}
506
+
507
+ const id = model.id.toLowerCase()
508
+ const adaptiveEfforts = anthropicAdaptiveEfforts(model.api.id)
509
+ if (
510
+ id.includes("deepseek") ||
511
+ id.includes("minimax") ||
512
+ id.includes("glm") ||
513
+ id.includes("mistral") ||
514
+ id.includes("kimi") ||
515
+ id.includes("k2p5") ||
516
+ id.includes("qwen") ||
517
+ id.includes("big-pickle")
518
+ )
519
+ return {}
520
+
521
+ // see: https://docs.x.ai/docs/guides/reasoning#control-how-hard-the-model-thinks
522
+ if (id.includes("grok") && id.includes("grok-3-mini")) {
523
+ if (model.api.npm === "@openrouter/ai-sdk-provider") {
524
+ return {
525
+ low: { reasoning: { effort: "low" } },
526
+ high: { reasoning: { effort: "high" } },
527
+ }
528
+ }
529
+ return {
530
+ low: { reasoningEffort: "low" },
531
+ high: { reasoningEffort: "high" },
532
+ }
533
+ }
534
+ if (id.includes("grok")) return {}
535
+
536
+ switch (model.api.npm) {
537
+ case "@openrouter/ai-sdk-provider":
538
+ if (!model.id.includes("gpt") && !model.id.includes("gemini-3") && !model.id.includes("claude")) return {}
539
+ return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }]))
540
+
541
+ case "@ai-sdk/gateway":
542
+ if (model.id.includes("anthropic")) {
543
+ if (adaptiveEfforts) {
544
+ return Object.fromEntries(
545
+ adaptiveEfforts.map((effort) => [
546
+ effort,
547
+ {
548
+ thinking: {
549
+ type: "adaptive",
550
+ },
551
+ effort,
552
+ },
553
+ ]),
554
+ )
555
+ }
556
+ return {
557
+ high: {
558
+ thinking: {
559
+ type: "enabled",
560
+ budgetTokens: 16000,
561
+ },
562
+ },
563
+ max: {
564
+ thinking: {
565
+ type: "enabled",
566
+ budgetTokens: 31999,
567
+ },
568
+ },
569
+ }
570
+ }
571
+ if (model.id.includes("google")) {
572
+ if (id.includes("2.5")) {
573
+ return {
574
+ high: {
575
+ thinkingConfig: {
576
+ includeThoughts: true,
577
+ thinkingBudget: 16000,
578
+ },
579
+ },
580
+ max: {
581
+ thinkingConfig: {
582
+ includeThoughts: true,
583
+ thinkingBudget: 24576,
584
+ },
585
+ },
586
+ }
587
+ }
588
+ return Object.fromEntries(
589
+ ["low", "high"].map((effort) => [
590
+ effort,
591
+ {
592
+ includeThoughts: true,
593
+ thinkingLevel: effort,
594
+ },
595
+ ]),
596
+ )
597
+ }
598
+ return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
599
+
600
+ case "@ai-sdk/github-copilot":
601
+ if (model.id.includes("gemini")) {
602
+ // currently github copilot only returns thinking
603
+ return {}
604
+ }
605
+ if (model.id.includes("claude")) {
606
+ return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
607
+ }
608
+ const copilotEfforts = iife(() => {
609
+ if (id.includes("5.1-codex-max") || id.includes("5.2") || id.includes("5.3"))
610
+ return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
611
+ const arr = [...WIDELY_SUPPORTED_EFFORTS]
612
+ if (id.includes("gpt-5") && model.release_date >= "2025-12-04") arr.push("xhigh")
613
+ return arr
614
+ })
615
+ return Object.fromEntries(
616
+ copilotEfforts.map((effort) => [
617
+ effort,
618
+ {
619
+ reasoningEffort: effort,
620
+ reasoningSummary: "auto",
621
+ include: ["reasoning.encrypted_content"],
622
+ },
623
+ ]),
624
+ )
625
+
626
+ case "@ai-sdk/cerebras":
627
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/cerebras
628
+ case "@ai-sdk/togetherai":
629
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/togetherai
630
+ case "@ai-sdk/xai":
631
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/xai
632
+ case "@ai-sdk/deepinfra":
633
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/deepinfra
634
+ case "venice-ai-sdk-provider":
635
+ // https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort
636
+ case "@ai-sdk/openai-compatible":
637
+ return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
638
+
639
+ case "@ai-sdk/azure":
640
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/azure
641
+ if (id === "o1-mini") return {}
642
+ const azureEfforts = ["low", "medium", "high"]
643
+ if (id.includes("gpt-5-") || id === "gpt-5") {
644
+ azureEfforts.unshift("minimal")
645
+ }
646
+ return Object.fromEntries(
647
+ azureEfforts.map((effort) => [
648
+ effort,
649
+ {
650
+ reasoningEffort: effort,
651
+ reasoningSummary: "auto",
652
+ include: ["reasoning.encrypted_content"],
653
+ },
654
+ ]),
655
+ )
656
+ case "@ai-sdk/openai":
657
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/openai
658
+ if (id === "gpt-5-pro") return {}
659
+ const openaiEfforts = iife(() => {
660
+ if (id.includes("codex")) {
661
+ if (id.includes("5.2") || id.includes("5.3")) return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
662
+ return WIDELY_SUPPORTED_EFFORTS
663
+ }
664
+ const arr = [...WIDELY_SUPPORTED_EFFORTS]
665
+ if (id.includes("gpt-5-") || id === "gpt-5") {
666
+ arr.unshift("minimal")
667
+ }
668
+ if (model.release_date >= "2025-11-13") {
669
+ arr.unshift("none")
670
+ }
671
+ if (model.release_date >= "2025-12-04") {
672
+ arr.push("xhigh")
673
+ }
674
+ return arr
675
+ })
676
+ return Object.fromEntries(
677
+ openaiEfforts.map((effort) => [
678
+ effort,
679
+ {
680
+ reasoningEffort: effort,
681
+ reasoningSummary: "auto",
682
+ include: ["reasoning.encrypted_content"],
683
+ },
684
+ ]),
685
+ )
686
+
687
+ case "@ai-sdk/anthropic":
688
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/anthropic
689
+ case "@ai-sdk/google-vertex/anthropic":
690
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex#anthropic-provider
691
+
692
+ if (model.providerID === "github-copilot") {
693
+ if (model.api.id.includes("opus-4.7")) {
694
+ return Object.fromEntries(["medium"].map((effort) => [effort, { reasoningEffort: effort }]))
695
+ }
696
+ }
697
+
698
+ if (adaptiveEfforts) {
699
+ return Object.fromEntries(
700
+ adaptiveEfforts.map((effort) => [
701
+ effort,
702
+ {
703
+ thinking: {
704
+ type: "adaptive",
705
+ ...(["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => model.api.id.includes(v))
706
+ ? { display: "summarized" }
707
+ : {}),
708
+ },
709
+ effort,
710
+ },
711
+ ]),
712
+ )
713
+ }
714
+
715
+ return {
716
+ high: {
717
+ thinking: {
718
+ type: "enabled",
719
+ budgetTokens: Math.min(16_000, Math.floor(model.limit.output / 2 - 1)),
720
+ },
721
+ },
722
+ max: {
723
+ thinking: {
724
+ type: "enabled",
725
+ budgetTokens: Math.min(31_999, model.limit.output - 1),
726
+ },
727
+ },
728
+ }
729
+
730
+ case "@ai-sdk/amazon-bedrock":
731
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock
732
+ if (adaptiveEfforts) {
733
+ return Object.fromEntries(
734
+ adaptiveEfforts.map((effort) => [
735
+ effort,
736
+ {
737
+ reasoningConfig: {
738
+ type: "adaptive",
739
+ maxReasoningEffort: effort,
740
+ ...(["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => model.api.id.includes(v))
741
+ ? { display: "summarized" }
742
+ : {}),
743
+ },
744
+ },
745
+ ]),
746
+ )
747
+ }
748
+ // For Anthropic models on Bedrock, use reasoningConfig with budgetTokens
749
+ if (model.api.id.includes("anthropic")) {
750
+ return {
751
+ high: {
752
+ reasoningConfig: {
753
+ type: "enabled",
754
+ budgetTokens: 16000,
755
+ },
756
+ },
757
+ max: {
758
+ reasoningConfig: {
759
+ type: "enabled",
760
+ budgetTokens: 31999,
761
+ },
762
+ },
763
+ }
764
+ }
765
+
766
+ // For Amazon Nova models, use reasoningConfig with maxReasoningEffort
767
+ return Object.fromEntries(
768
+ WIDELY_SUPPORTED_EFFORTS.map((effort) => [
769
+ effort,
770
+ {
771
+ reasoningConfig: {
772
+ type: "enabled",
773
+ maxReasoningEffort: effort,
774
+ },
775
+ },
776
+ ]),
777
+ )
778
+
779
+ case "@ai-sdk/google-vertex":
780
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex
781
+ case "@ai-sdk/google":
782
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai
783
+ if (id.includes("2.5")) {
784
+ return {
785
+ high: {
786
+ thinkingConfig: {
787
+ includeThoughts: true,
788
+ thinkingBudget: 16000,
789
+ },
790
+ },
791
+ max: {
792
+ thinkingConfig: {
793
+ includeThoughts: true,
794
+ thinkingBudget: 24576,
795
+ },
796
+ },
797
+ }
798
+ }
799
+ let levels = ["low", "high"]
800
+ if (id.includes("3.1")) {
801
+ levels = ["low", "medium", "high"]
802
+ }
803
+
804
+ return Object.fromEntries(
805
+ levels.map((effort) => [
806
+ effort,
807
+ {
808
+ thinkingConfig: {
809
+ includeThoughts: true,
810
+ thinkingLevel: effort,
811
+ },
812
+ },
813
+ ]),
814
+ )
815
+
816
+ case "@ai-sdk/mistral":
817
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/mistral
818
+ return {}
819
+
820
+ case "@ai-sdk/cohere":
821
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/cohere
822
+ return {}
823
+
824
+ case "@ai-sdk/groq":
825
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/groq
826
+ const groqEffort = ["none", ...WIDELY_SUPPORTED_EFFORTS]
827
+ return Object.fromEntries(
828
+ groqEffort.map((effort) => [
829
+ effort,
830
+ {
831
+ reasoningEffort: effort,
832
+ },
833
+ ]),
834
+ )
835
+
836
+ case "@ai-sdk/perplexity":
837
+ // https://v5.ai-sdk.dev/providers/ai-sdk-providers/perplexity
838
+ return {}
839
+
840
+ case "@jerome-benoit/sap-ai-provider-v2":
841
+ if (model.api.id.includes("anthropic")) {
842
+ if (adaptiveEfforts) {
843
+ return Object.fromEntries(
844
+ adaptiveEfforts.map((effort) => [
845
+ effort,
846
+ {
847
+ thinking: {
848
+ type: "adaptive",
849
+ },
850
+ effort,
851
+ },
852
+ ]),
853
+ )
854
+ }
855
+ return {
856
+ high: {
857
+ thinking: {
858
+ type: "enabled",
859
+ budgetTokens: 16000,
860
+ },
861
+ },
862
+ max: {
863
+ thinking: {
864
+ type: "enabled",
865
+ budgetTokens: 31999,
866
+ },
867
+ },
868
+ }
869
+ }
870
+ if (model.api.id.includes("gemini") && id.includes("2.5")) {
871
+ return {
872
+ high: {
873
+ thinkingConfig: {
874
+ includeThoughts: true,
875
+ thinkingBudget: 16000,
876
+ },
877
+ },
878
+ max: {
879
+ thinkingConfig: {
880
+ includeThoughts: true,
881
+ thinkingBudget: 24576,
882
+ },
883
+ },
884
+ }
885
+ }
886
+ if (model.api.id.includes("gpt") || /\bo[1-9]/.test(model.api.id)) {
887
+ return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
888
+ }
889
+ return {}
890
+ }
891
+ return {}
892
+ }
893
+
894
+ export function options(input: {
895
+ model: Provider.Model
896
+ sessionID: string
897
+ providerOptions?: Record<string, any>
898
+ }): Record<string, any> {
899
+ const result: Record<string, any> = {}
900
+
901
+ // openai and providers using openai package should set store to false by default.
902
+ if (
903
+ input.model.providerID === "openai" ||
904
+ input.model.api.npm === "@ai-sdk/openai" ||
905
+ input.model.api.npm === "@ai-sdk/github-copilot"
906
+ ) {
907
+ result["store"] = false
908
+ }
909
+
910
+ if (input.model.api.npm === "@ai-sdk/azure") {
911
+ result["store"] = true
912
+ result["promptCacheKey"] = input.sessionID
913
+ }
914
+
915
+ if (input.model.api.npm === "@openrouter/ai-sdk-provider" || input.model.api.npm === "@llmgateway/ai-sdk-provider") {
916
+ result["usage"] = {
917
+ include: true,
918
+ }
919
+ if (input.model.api.id.includes("gemini-3")) {
920
+ result["reasoning"] = { effort: "high" }
921
+ }
922
+ }
923
+
924
+ if (
925
+ input.model.providerID === "baseten" ||
926
+ (input.model.providerID === "tulingcode" && ["kimi-k2-thinking", "glm-4.6"].includes(input.model.api.id))
927
+ ) {
928
+ result["chat_template_args"] = { enable_thinking: true }
929
+ }
930
+
931
+ if (
932
+ ["zai", "zhipuai"].some((id) => input.model.providerID.includes(id)) &&
933
+ input.model.api.npm === "@ai-sdk/openai-compatible"
934
+ ) {
935
+ result["thinking"] = {
936
+ type: "enabled",
937
+ clear_thinking: false,
938
+ }
939
+ }
940
+
941
+ if (input.model.providerID === "openai" || input.providerOptions?.setCacheKey) {
942
+ result["promptCacheKey"] = input.sessionID
943
+ }
944
+
945
+ if (input.model.api.npm === "@ai-sdk/google" || input.model.api.npm === "@ai-sdk/google-vertex") {
946
+ if (input.model.capabilities.reasoning) {
947
+ result["thinkingConfig"] = {
948
+ includeThoughts: true,
949
+ }
950
+ if (input.model.api.id.includes("gemini-3")) {
951
+ result["thinkingConfig"]["thinkingLevel"] = "high"
952
+ }
953
+ }
954
+ }
955
+
956
+ // Enable thinking by default for kimi-k2.5/k2p5 models using anthropic SDK
957
+ const modelId = input.model.api.id.toLowerCase()
958
+ if (
959
+ (input.model.api.npm === "@ai-sdk/anthropic" || input.model.api.npm === "@ai-sdk/google-vertex/anthropic") &&
960
+ (modelId.includes("k2p5") || modelId.includes("kimi-k2.5") || modelId.includes("kimi-k2p5"))
961
+ ) {
962
+ result["thinking"] = {
963
+ type: "enabled",
964
+ budgetTokens: Math.min(16_000, Math.floor(input.model.limit.output / 2 - 1)),
965
+ }
966
+ }
967
+
968
+ // Enable thinking for reasoning models on alibaba-cn (DashScope).
969
+ // DashScope's OpenAI-compatible API requires `enable_thinking: true` in the request body
970
+ // to return reasoning_content. Without it, models like kimi-k2.5, qwen-plus, qwen3, qwq,
971
+ // deepseek-r1, etc. never output thinking/reasoning tokens.
972
+ // Note: kimi-k2-thinking is excluded as it returns reasoning_content by default.
973
+ if (
974
+ input.model.providerID === "alibaba-cn" &&
975
+ input.model.capabilities.reasoning &&
976
+ input.model.api.npm === "@ai-sdk/openai-compatible" &&
977
+ !modelId.includes("kimi-k2-thinking")
978
+ ) {
979
+ result["enable_thinking"] = true
980
+ }
981
+
982
+ if (input.model.api.id.includes("gpt-5") && !input.model.api.id.includes("gpt-5-chat")) {
983
+ if (!input.model.api.id.includes("gpt-5-pro")) {
984
+ result["reasoningEffort"] = "medium"
985
+ // Only inject reasoningSummary for providers that support it natively.
986
+ // @ai-sdk/openai-compatible proxies (e.g. LiteLLM) do not understand this
987
+ // parameter and return "Unknown parameter: 'reasoningSummary'".
988
+ if (
989
+ input.model.api.npm === "@ai-sdk/openai" ||
990
+ input.model.api.npm === "@ai-sdk/azure" ||
991
+ input.model.api.npm === "@ai-sdk/github-copilot"
992
+ ) {
993
+ result["reasoningSummary"] = "auto"
994
+ }
995
+ }
996
+
997
+ // Only set textVerbosity for non-chat gpt-5.x models
998
+ // Chat models (e.g. gpt-5.2-chat-latest) only support "medium" verbosity
999
+ if (
1000
+ input.model.api.id.includes("gpt-5.") &&
1001
+ !input.model.api.id.includes("codex") &&
1002
+ !input.model.api.id.includes("-chat") &&
1003
+ input.model.providerID !== "azure"
1004
+ ) {
1005
+ result["textVerbosity"] = "low"
1006
+ }
1007
+
1008
+ if (input.model.providerID.startsWith("tulingcode")) {
1009
+ result["promptCacheKey"] = input.sessionID
1010
+ result["include"] = ["reasoning.encrypted_content"]
1011
+ result["reasoningSummary"] = "auto"
1012
+ }
1013
+ }
1014
+
1015
+ if (input.model.providerID === "venice") {
1016
+ result["promptCacheKey"] = input.sessionID
1017
+ }
1018
+
1019
+ if (input.model.providerID === "openrouter") {
1020
+ result["prompt_cache_key"] = input.sessionID
1021
+ }
1022
+ if (input.model.api.npm === "@ai-sdk/gateway") {
1023
+ result["gateway"] = {
1024
+ caching: "auto",
1025
+ }
1026
+ }
1027
+
1028
+ return result
1029
+ }
1030
+
1031
+ export function smallOptions(model: Provider.Model) {
1032
+ if (
1033
+ model.providerID === "openai" ||
1034
+ model.api.npm === "@ai-sdk/openai" ||
1035
+ model.api.npm === "@ai-sdk/github-copilot"
1036
+ ) {
1037
+ if (model.api.id.includes("gpt-5")) {
1038
+ if (model.api.id.includes("5.") || model.api.id.includes("5-mini")) {
1039
+ return { store: false, reasoningEffort: "low" }
1040
+ }
1041
+ return { store: false, reasoningEffort: "minimal" }
1042
+ }
1043
+ return { store: false }
1044
+ }
1045
+ if (model.providerID === "google") {
1046
+ // gemini-3 uses thinkingLevel, gemini-2.5 uses thinkingBudget
1047
+ if (model.api.id.includes("gemini-3")) {
1048
+ return { thinkingConfig: { thinkingLevel: "minimal" } }
1049
+ }
1050
+ return { thinkingConfig: { thinkingBudget: 0 } }
1051
+ }
1052
+ if (model.providerID === "openrouter" || model.providerID === "llmgateway") {
1053
+ if (model.api.id.includes("google")) {
1054
+ return { reasoning: { enabled: false } }
1055
+ }
1056
+ return { reasoningEffort: "minimal" }
1057
+ }
1058
+
1059
+ if (model.providerID === "venice") {
1060
+ return { veniceParameters: { disableThinking: true } }
1061
+ }
1062
+
1063
+ return {}
1064
+ }
1065
+
1066
+ // Maps model ID prefix to provider slug used in providerOptions.
1067
+ // Example: "amazon/nova-2-lite" → "bedrock"
1068
+ const SLUG_OVERRIDES: Record<string, string> = {
1069
+ amazon: "bedrock",
1070
+ }
1071
+
1072
+ export function providerOptions(model: Provider.Model, options: { [x: string]: any }) {
1073
+ if (model.api.npm === "@ai-sdk/gateway") {
1074
+ // Gateway providerOptions are split across two namespaces:
1075
+ // - `gateway`: gateway-native routing/caching controls (order, only, byok, etc.)
1076
+ // - `<upstream slug>`: provider-specific model options (anthropic/openai/...)
1077
+ // We keep `gateway` as-is and route every other top-level option under the
1078
+ // model-derived upstream slug.
1079
+ const i = model.api.id.indexOf("/")
1080
+ const rawSlug = i > 0 ? model.api.id.slice(0, i) : undefined
1081
+ const slug = rawSlug ? (SLUG_OVERRIDES[rawSlug] ?? rawSlug) : undefined
1082
+ const gateway = options.gateway
1083
+ const rest = Object.fromEntries(Object.entries(options).filter(([k]) => k !== "gateway"))
1084
+ const has = Object.keys(rest).length > 0
1085
+
1086
+ const result: Record<string, any> = {}
1087
+ if (gateway !== undefined) result.gateway = gateway
1088
+
1089
+ if (has) {
1090
+ if (slug) {
1091
+ // Route model-specific options under the provider slug
1092
+ result[slug] = rest
1093
+ } else if (gateway && typeof gateway === "object" && !Array.isArray(gateway)) {
1094
+ result.gateway = { ...gateway, ...rest }
1095
+ } else {
1096
+ result.gateway = rest
1097
+ }
1098
+ }
1099
+
1100
+ return result
1101
+ }
1102
+
1103
+ const key = sdkKey(model.api.npm) ?? model.providerID
1104
+ // @ai-sdk/azure delegates to OpenAIChatLanguageModel which reads from
1105
+ // providerOptions["openai"], but OpenAIResponsesLanguageModel checks
1106
+ // "azure" first. Pass both so model options work on either code path.
1107
+ if (model.api.npm === "@ai-sdk/azure") {
1108
+ return { openai: options, azure: options }
1109
+ }
1110
+ return { [key]: options }
1111
+ }
1112
+
1113
+ export function maxOutputTokens(model: Provider.Model): number {
1114
+ if (model.providerID === "tuling-ai" || model.id.toLowerCase().includes("mimo-v2.5")) {
1115
+ return MIMO_OUTPUT_TOKEN_MAX
1116
+ }
1117
+ return Math.min(model.limit.output, OUTPUT_TOKEN_MAX) || OUTPUT_TOKEN_MAX
1118
+ }
1119
+
1120
+ // Flatten a root-level `anyOf` / `oneOf` (typically from `z.discriminatedUnion`)
1121
+ // into a single `type: "object"` schema with all variant properties merged at
1122
+ // the root. The discriminator key becomes an `enum`, and per-variant required
1123
+ // fields are encoded as a textual hint on the discriminator's description.
1124
+ //
1125
+ // OpenAI's function-calling validator rejects oneOf/anyOf/allOf/enum/not at the
1126
+ // top level outright, so this is the only shape that gets through. We retain
1127
+ // `additionalProperties: false` to keep the model from inventing fields, and
1128
+ // rely on zod's runtime parse (still using the original discriminated union)
1129
+ // to enforce per-action required fields strictly.
1130
+ function flattenDiscriminatedUnion(schema: JSONSchema.BaseSchema | JSONSchema7): JSONSchema7 {
1131
+ const root = schema as Record<string, any>
1132
+ const variants = (root.anyOf ?? root.oneOf) as Array<Record<string, any>> | undefined
1133
+ if (!variants?.length) return schema as JSONSchema7
1134
+
1135
+ // Find the discriminator: a property whose `const` differs across all variants.
1136
+ const constByKey = new Map<string, Set<unknown>>()
1137
+ for (const v of variants) {
1138
+ if (!v.properties) continue
1139
+ for (const [key, prop] of Object.entries(v.properties as Record<string, any>)) {
1140
+ if (prop && typeof prop === "object" && "const" in prop) {
1141
+ if (!constByKey.has(key)) constByKey.set(key, new Set())
1142
+ constByKey.get(key)!.add(prop.const)
1143
+ }
1144
+ }
1145
+ }
1146
+ let discriminator: string | undefined
1147
+ for (const [key, values] of constByKey) {
1148
+ if (values.size === variants.length) {
1149
+ discriminator = key
1150
+ break
1151
+ }
1152
+ }
1153
+
1154
+ // Merge non-discriminator properties from every variant. Track which variants
1155
+ // each property appeared in so the description can tell the model
1156
+ // "(only when action='X'|'Y')" — flat schemas tempt some models (notably
1157
+ // gpt-5.5) to fill every property regardless of which action they chose.
1158
+ const properties: Record<string, any> = {}
1159
+ const propertyOwners: Record<string, unknown[]> = {}
1160
+ for (const v of variants) {
1161
+ if (!v.properties) continue
1162
+ const variantValue = discriminator
1163
+ ? (v.properties as Record<string, any>)[discriminator]?.const
1164
+ : undefined
1165
+ for (const [key, prop] of Object.entries(v.properties as Record<string, any>)) {
1166
+ if (key === discriminator) continue
1167
+ if (!(key in properties)) properties[key] = prop
1168
+ if (variantValue !== undefined) {
1169
+ if (!propertyOwners[key]) propertyOwners[key] = []
1170
+ propertyOwners[key].push(variantValue)
1171
+ }
1172
+ }
1173
+ }
1174
+ if (discriminator) {
1175
+ for (const [key, owners] of Object.entries(propertyOwners)) {
1176
+ if (owners.length === variants.length) continue // present in every variant — no annotation
1177
+ const tag = `(only when ${discriminator}=${owners.map((o) => JSON.stringify(o)).join("|")})`
1178
+ const original = (properties[key] as Record<string, any>).description as string | undefined
1179
+ properties[key] = {
1180
+ ...properties[key],
1181
+ description: original ? `${tag} ${original}` : tag,
1182
+ }
1183
+ }
1184
+ }
1185
+
1186
+ // Discriminator becomes an enum with per-variant required fields hinted in
1187
+ // its description. Without this hint the model only sees a flat bag of
1188
+ // optional fields and forgets what to provide for each action.
1189
+ if (discriminator) {
1190
+ const proto = (variants[0].properties as Record<string, any>)[discriminator]
1191
+ const enumValues = variants.map((v) => (v.properties as Record<string, any>)[discriminator!]?.const)
1192
+ const baseDescription = (proto?.description as string | undefined) ?? ""
1193
+ const hints = variants
1194
+ .map((v) => {
1195
+ const value = (v.properties as Record<string, any>)[discriminator!]?.const
1196
+ const required = ((v.required as string[] | undefined) ?? []).filter((r) => r !== discriminator)
1197
+ return required.length > 0 ? `${value}: requires ${required.join(", ")}` : `${value}: no extra required fields`
1198
+ })
1199
+ .join("; ")
1200
+ properties[discriminator] = {
1201
+ type: "string",
1202
+ enum: enumValues,
1203
+ description: baseDescription ? `${baseDescription}\n\nPer-${discriminator}: ${hints}.` : `Per-${discriminator}: ${hints}.`,
1204
+ }
1205
+ }
1206
+
1207
+ return {
1208
+ type: "object",
1209
+ properties,
1210
+ required: discriminator ? [discriminator] : [],
1211
+ additionalProperties: false,
1212
+ } as JSONSchema7
1213
+ }
1214
+
1215
+ export function schema(model: Provider.Model, schema: JSONSchema.BaseSchema | JSONSchema7): JSONSchema7 {
1216
+ /*
1217
+ if (["openai", "azure"].includes(providerID)) {
1218
+ if (schema.type === "object" && schema.properties) {
1219
+ for (const [key, value] of Object.entries(schema.properties)) {
1220
+ if (schema.required?.includes(key)) continue
1221
+ schema.properties[key] = {
1222
+ anyOf: [
1223
+ value as JSONSchema.JSONSchema,
1224
+ {
1225
+ type: "null",
1226
+ },
1227
+ ],
1228
+ }
1229
+ }
1230
+ }
1231
+ }
1232
+ */
1233
+
1234
+ // Many providers reject root-level `anyOf`/`oneOf` in tool schemas:
1235
+ // - OpenAI/Azure: "schema must have type 'object' and not have 'oneOf'/'anyOf'"
1236
+ // - Bedrock: "input_schema.type: Field required"
1237
+ // - Anthropic proxies to Bedrock: same Bedrock error
1238
+ // Flatten unconditionally — all providers accept a flat `type: "object"` schema,
1239
+ // and zod's runtime parse still enforces per-variant required fields strictly.
1240
+ schema = flattenDiscriminatedUnion(schema)
1241
+
1242
+ // Convert integer enums to string enums for Google/Gemini
1243
+ if (model.providerID === "google" || model.api.id.includes("gemini")) {
1244
+ const isPlainObject = (node: unknown): node is Record<string, any> =>
1245
+ typeof node === "object" && node !== null && !Array.isArray(node)
1246
+ const hasCombiner = (node: unknown) =>
1247
+ isPlainObject(node) && (Array.isArray(node.anyOf) || Array.isArray(node.oneOf) || Array.isArray(node.allOf))
1248
+ const hasSchemaIntent = (node: unknown) => {
1249
+ if (!isPlainObject(node)) return false
1250
+ if (hasCombiner(node)) return true
1251
+ return [
1252
+ "type",
1253
+ "properties",
1254
+ "items",
1255
+ "prefixItems",
1256
+ "enum",
1257
+ "const",
1258
+ "$ref",
1259
+ "additionalProperties",
1260
+ "patternProperties",
1261
+ "required",
1262
+ "not",
1263
+ "if",
1264
+ "then",
1265
+ "else",
1266
+ ].some((key) => key in node)
1267
+ }
1268
+
1269
+ const sanitizeGemini = (obj: any): any => {
1270
+ if (obj === null || typeof obj !== "object") {
1271
+ return obj
1272
+ }
1273
+
1274
+ if (Array.isArray(obj)) {
1275
+ return obj.map(sanitizeGemini)
1276
+ }
1277
+
1278
+ const result: any = {}
1279
+ for (const [key, value] of Object.entries(obj)) {
1280
+ if (key === "enum" && Array.isArray(value)) {
1281
+ // Convert all enum values to strings
1282
+ result[key] = value.map((v) => String(v))
1283
+ // If we have integer type with enum, change type to string
1284
+ if (result.type === "integer" || result.type === "number") {
1285
+ result.type = "string"
1286
+ }
1287
+ } else if (typeof value === "object" && value !== null) {
1288
+ result[key] = sanitizeGemini(value)
1289
+ } else {
1290
+ result[key] = value
1291
+ }
1292
+ }
1293
+
1294
+ // Filter required array to only include fields that exist in properties
1295
+ if (result.type === "object" && result.properties && Array.isArray(result.required)) {
1296
+ result.required = result.required.filter((field: any) => field in result.properties)
1297
+ }
1298
+
1299
+ if (result.type === "array" && !hasCombiner(result)) {
1300
+ if (result.items == null) {
1301
+ result.items = {}
1302
+ }
1303
+ // Ensure items has a type only when it's still schema-empty.
1304
+ if (isPlainObject(result.items) && !hasSchemaIntent(result.items)) {
1305
+ result.items.type = "string"
1306
+ }
1307
+ }
1308
+
1309
+ // Remove properties/required from non-object types (Gemini rejects these)
1310
+ if (result.type && result.type !== "object" && !hasCombiner(result)) {
1311
+ delete result.properties
1312
+ delete result.required
1313
+ }
1314
+
1315
+ return result
1316
+ }
1317
+
1318
+ schema = sanitizeGemini(schema)
1319
+ }
1320
+
1321
+ return schema as JSONSchema7
1322
+ }