@yansigit/opencodex 2.31.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 (826) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +587 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
  11. package/gui/dist/assets/index-CGoDO3uO.css +1 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/icons.svg +24 -0
  14. package/gui/dist/index.html +25 -0
  15. package/gui/dist/logo.png +0 -0
  16. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/cline-color.svg +16 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  25. package/gui/dist/provider-icons/discord.svg +1 -0
  26. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  27. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  28. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  29. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  30. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  31. package/gui/dist/provider-icons/grok.svg +1 -0
  32. package/gui/dist/provider-icons/groq-color.svg +1 -0
  33. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  34. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  35. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  36. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  37. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  38. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  39. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  40. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  41. package/gui/dist/provider-icons/openai.svg +1 -0
  42. package/gui/dist/provider-icons/opencode.svg +2 -0
  43. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  44. package/gui/dist/provider-icons/pi.svg +21 -0
  45. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  46. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  47. package/gui/dist/provider-icons/telegram.svg +1 -0
  48. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  49. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  50. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  51. package/package.json +108 -0
  52. package/src/AGENTS.md +28 -0
  53. package/src/adapters/anthropic-image-guard.ts +251 -0
  54. package/src/adapters/anthropic-image-normalize.ts +518 -0
  55. package/src/adapters/anthropic-output-schema.ts +137 -0
  56. package/src/adapters/anthropic.ts +1327 -0
  57. package/src/adapters/azure.ts +36 -0
  58. package/src/adapters/base.ts +121 -0
  59. package/src/adapters/client-fingerprint.ts +65 -0
  60. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  61. package/src/adapters/command-code.ts +601 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  65. package/src/adapters/cursor/cursor-errors.ts +288 -0
  66. package/src/adapters/cursor/discovery.ts +333 -0
  67. package/src/adapters/cursor/effort-map.ts +151 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +250 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/h2-pool.ts +123 -0
  72. package/src/adapters/cursor/http1-bidi.ts +361 -0
  73. package/src/adapters/cursor/images.ts +704 -0
  74. package/src/adapters/cursor/kv-store.ts +52 -0
  75. package/src/adapters/cursor/live-models.ts +269 -0
  76. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  77. package/src/adapters/cursor/live-transport.ts +1653 -0
  78. package/src/adapters/cursor/mcp-config.ts +42 -0
  79. package/src/adapters/cursor/mcp-manager.ts +333 -0
  80. package/src/adapters/cursor/message-mapper.ts +49 -0
  81. package/src/adapters/cursor/native-exec-common.ts +76 -0
  82. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  83. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  84. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  85. package/src/adapters/cursor/native-exec-network.ts +43 -0
  86. package/src/adapters/cursor/native-exec-shell.ts +547 -0
  87. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  88. package/src/adapters/cursor/native-exec.ts +663 -0
  89. package/src/adapters/cursor/protobuf-events.ts +1381 -0
  90. package/src/adapters/cursor/protobuf-request.ts +1032 -0
  91. package/src/adapters/cursor/request-builder.ts +461 -0
  92. package/src/adapters/cursor/thread-continuity.ts +67 -0
  93. package/src/adapters/cursor/tool-definitions.ts +735 -0
  94. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  95. package/src/adapters/cursor/transport-retry.ts +132 -0
  96. package/src/adapters/cursor/transport.ts +79 -0
  97. package/src/adapters/cursor/types.ts +79 -0
  98. package/src/adapters/cursor.ts +322 -0
  99. package/src/adapters/google-antigravity-hosts.ts +48 -0
  100. package/src/adapters/google-antigravity-replay.ts +827 -0
  101. package/src/adapters/google-antigravity-tools.ts +105 -0
  102. package/src/adapters/google-antigravity-wire.ts +141 -0
  103. package/src/adapters/google-errors.ts +92 -0
  104. package/src/adapters/google-http.ts +460 -0
  105. package/src/adapters/google-tool-schema.ts +238 -0
  106. package/src/adapters/google-truncation.ts +24 -0
  107. package/src/adapters/google-wire-compiler.ts +232 -0
  108. package/src/adapters/google.ts +1377 -0
  109. package/src/adapters/identity.ts +77 -0
  110. package/src/adapters/image.ts +23 -0
  111. package/src/adapters/kiro-constants.ts +16 -0
  112. package/src/adapters/kiro-errors.ts +208 -0
  113. package/src/adapters/kiro-events.ts +197 -0
  114. package/src/adapters/kiro-images.ts +129 -0
  115. package/src/adapters/kiro-retry.ts +312 -0
  116. package/src/adapters/kiro-thinking.ts +112 -0
  117. package/src/adapters/kiro-tool-fallback.ts +36 -0
  118. package/src/adapters/kiro-tools.ts +224 -0
  119. package/src/adapters/kiro-truncation.ts +33 -0
  120. package/src/adapters/kiro-wire.ts +129 -0
  121. package/src/adapters/kiro.ts +1936 -0
  122. package/src/adapters/mimo-free.ts +280 -0
  123. package/src/adapters/openai-chat-url.ts +11 -0
  124. package/src/adapters/openai-chat.ts +1980 -0
  125. package/src/adapters/openai-responses-url.ts +16 -0
  126. package/src/adapters/openai-responses.ts +1911 -0
  127. package/src/adapters/registry.ts +175 -0
  128. package/src/adapters/responses-tool-schema.ts +67 -0
  129. package/src/adapters/run-turn-queue.ts +114 -0
  130. package/src/adapters/tool-call-id.ts +119 -0
  131. package/src/adapters/tool-catalog-nudge.ts +154 -0
  132. package/src/adapters/upstream-http-error.ts +48 -0
  133. package/src/adapters/xai-web-search.ts +185 -0
  134. package/src/bridge.ts +1986 -0
  135. package/src/chat/inbound.ts +319 -0
  136. package/src/chat/outbound.ts +821 -0
  137. package/src/claude/agents-inject.ts +266 -0
  138. package/src/claude/alias.ts +149 -0
  139. package/src/claude/auth-detect.ts +229 -0
  140. package/src/claude/auth-mode-migration.ts +32 -0
  141. package/src/claude/auth-mode.ts +62 -0
  142. package/src/claude/context-windows.ts +205 -0
  143. package/src/claude/desktop-3p-guard.ts +35 -0
  144. package/src/claude/desktop-3p-paths.ts +84 -0
  145. package/src/claude/desktop-3p.ts +615 -0
  146. package/src/claude/desktop-health.ts +26 -0
  147. package/src/claude/desktop-profile.ts +263 -0
  148. package/src/claude/gateway-cache.ts +107 -0
  149. package/src/claude/inbound-debug.ts +163 -0
  150. package/src/claude/inbound.ts +578 -0
  151. package/src/claude/model-info.ts +174 -0
  152. package/src/claude/outbound.ts +926 -0
  153. package/src/cli/access.ts +108 -0
  154. package/src/cli/account-api.ts +302 -0
  155. package/src/cli/account-auth.ts +250 -0
  156. package/src/cli/account-catalog-refresh.ts +14 -0
  157. package/src/cli/account-extended.ts +737 -0
  158. package/src/cli/account-main.ts +317 -0
  159. package/src/cli/account.ts +299 -0
  160. package/src/cli/agent-driven.ts +70 -0
  161. package/src/cli/agent.ts +290 -0
  162. package/src/cli/catalog-prewarm.ts +27 -0
  163. package/src/cli/claude-agent-startup-sync.ts +73 -0
  164. package/src/cli/claude-desktop.ts +213 -0
  165. package/src/cli/claude.ts +355 -0
  166. package/src/cli/codex-log-guard-doctor.ts +103 -0
  167. package/src/cli/codex-shim-autorestore.ts +47 -0
  168. package/src/cli/codex-shim-readiness.ts +76 -0
  169. package/src/cli/combo.ts +127 -0
  170. package/src/cli/config-command.ts +209 -0
  171. package/src/cli/debug.ts +228 -0
  172. package/src/cli/dispatch.ts +585 -0
  173. package/src/cli/doctor.ts +1202 -0
  174. package/src/cli/ensure-desired-integrations.ts +152 -0
  175. package/src/cli/export-command.ts +213 -0
  176. package/src/cli/help.ts +101 -0
  177. package/src/cli/index.ts +973 -0
  178. package/src/cli/init.ts +211 -0
  179. package/src/cli/integrations.ts +260 -0
  180. package/src/cli/interactive-confirm.ts +133 -0
  181. package/src/cli/lab.ts +607 -0
  182. package/src/cli/launcher-context.ts +77 -0
  183. package/src/cli/minimax.ts +497 -0
  184. package/src/cli/models-runtime.ts +245 -0
  185. package/src/cli/models.ts +422 -0
  186. package/src/cli/observe.ts +206 -0
  187. package/src/cli/opencode.ts +588 -0
  188. package/src/cli/provider-replit.ts +232 -0
  189. package/src/cli/provider-runtime.ts +179 -0
  190. package/src/cli/provider.ts +492 -0
  191. package/src/cli/ready.ts +301 -0
  192. package/src/cli/registry.ts +422 -0
  193. package/src/cli/replit-gateway-key-input.ts +138 -0
  194. package/src/cli/root.ts +86 -0
  195. package/src/cli/route-policy.ts +92 -0
  196. package/src/cli/runtime-api.ts +328 -0
  197. package/src/cli/star-prompt.ts +211 -0
  198. package/src/cli/status-oauth.ts +78 -0
  199. package/src/cli/status.ts +328 -0
  200. package/src/cli/system-command.ts +112 -0
  201. package/src/cli/system-restart-client.ts +146 -0
  202. package/src/cli/tray-proxy.ts +199 -0
  203. package/src/cli/v2.ts +268 -0
  204. package/src/cli.ts +10 -0
  205. package/src/clients/config-export.ts +1704 -0
  206. package/src/codex/account-id.ts +34 -0
  207. package/src/codex/account-label.ts +47 -0
  208. package/src/codex/account-lifecycle.ts +172 -0
  209. package/src/codex/account-namespace-match.ts +63 -0
  210. package/src/codex/account-namespaces.ts +195 -0
  211. package/src/codex/account-pause.ts +20 -0
  212. package/src/codex/account-priority.ts +83 -0
  213. package/src/codex/account-runtime-state.ts +31 -0
  214. package/src/codex/account-store.ts +544 -0
  215. package/src/codex/account-usability.ts +43 -0
  216. package/src/codex/admission.ts +256 -0
  217. package/src/codex/affinity-debug.ts +162 -0
  218. package/src/codex/agent-roles-sync.ts +225 -0
  219. package/src/codex/agent-roles.ts +238 -0
  220. package/src/codex/app-server-processes.ts +1143 -0
  221. package/src/codex/app-server-restart-service.ts +232 -0
  222. package/src/codex/auth-api.ts +2147 -0
  223. package/src/codex/auth-collision.ts +109 -0
  224. package/src/codex/auth-context.ts +665 -0
  225. package/src/codex/autostart-health.ts +156 -0
  226. package/src/codex/catalog/account-models.ts +67 -0
  227. package/src/codex/catalog/aggregation.ts +436 -0
  228. package/src/codex/catalog/bundled.ts +549 -0
  229. package/src/codex/catalog/effort.ts +446 -0
  230. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  231. package/src/codex/catalog/kinds.ts +2 -0
  232. package/src/codex/catalog/metadata.ts +664 -0
  233. package/src/codex/catalog/native-models.ts +72 -0
  234. package/src/codex/catalog/parsing.ts +650 -0
  235. package/src/codex/catalog/provider-fetch.ts +2064 -0
  236. package/src/codex/catalog/sync.ts +1883 -0
  237. package/src/codex/catalog-admission.ts +199 -0
  238. package/src/codex/catalog-refresh-status.ts +105 -0
  239. package/src/codex/catalog-write-serialization.ts +242 -0
  240. package/src/codex/catalog.ts +14 -0
  241. package/src/codex/codex-write-lock.ts +384 -0
  242. package/src/codex/convergence-types.ts +614 -0
  243. package/src/codex/convergence.ts +651 -0
  244. package/src/codex/coordinator-doctor.ts +332 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/exec-invocation.ts +22 -0
  249. package/src/codex/features.ts +1566 -0
  250. package/src/codex/generation.ts +202 -0
  251. package/src/codex/history-job.ts +407 -0
  252. package/src/codex/history-lock.ts +242 -0
  253. package/src/codex/history-migration-guardian.ts +108 -0
  254. package/src/codex/history-provider.ts +979 -0
  255. package/src/codex/history-transition.ts +105 -0
  256. package/src/codex/history-worker.ts +220 -0
  257. package/src/codex/home.ts +206 -0
  258. package/src/codex/inject-coordination.ts +290 -0
  259. package/src/codex/inject.ts +1733 -0
  260. package/src/codex/injected-marker.ts +106 -0
  261. package/src/codex/integration-record.ts +266 -0
  262. package/src/codex/internal/catalog-writer.ts +203 -0
  263. package/src/codex/internal/history-writer.ts +80 -0
  264. package/src/codex/journal.ts +225 -0
  265. package/src/codex/log-guard/inspect.ts +506 -0
  266. package/src/codex/log-guard/lock.ts +150 -0
  267. package/src/codex/log-guard/maintenance.ts +403 -0
  268. package/src/codex/log-guard/path-safety.ts +88 -0
  269. package/src/codex/log-guard/policy.ts +44 -0
  270. package/src/codex/log-guard/processes.ts +205 -0
  271. package/src/codex/log-guard/protection.ts +489 -0
  272. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  273. package/src/codex/main-account-cache.ts +56 -0
  274. package/src/codex/main-account.ts +68 -0
  275. package/src/codex/management-convergence.ts +167 -0
  276. package/src/codex/model-cache.ts +273 -0
  277. package/src/codex/model-entitlements.ts +353 -0
  278. package/src/codex/native-main-admission.ts +47 -0
  279. package/src/codex/native-main-auth-temp.ts +187 -0
  280. package/src/codex/native-main-claim.ts +178 -0
  281. package/src/codex/native-main-lock-file.ts +162 -0
  282. package/src/codex/native-main-owner.ts +329 -0
  283. package/src/codex/native-profile-api.ts +247 -0
  284. package/src/codex/native-profile-manager.ts +1531 -0
  285. package/src/codex/native-profile-processes.ts +121 -0
  286. package/src/codex/native-profile-recovery.ts +99 -0
  287. package/src/codex/native-profile-stage-store.ts +387 -0
  288. package/src/codex/native-profile-startup.ts +492 -0
  289. package/src/codex/native-profile-store.ts +855 -0
  290. package/src/codex/native-profile-types.ts +120 -0
  291. package/src/codex/native-residue.ts +682 -0
  292. package/src/codex/paths.ts +144 -0
  293. package/src/codex/plan-from-token.ts +140 -0
  294. package/src/codex/plan.ts +40 -0
  295. package/src/codex/plugins-doctor.ts +242 -0
  296. package/src/codex/pool-rotation.ts +295 -0
  297. package/src/codex/project-config-warnings.ts +425 -0
  298. package/src/codex/prompt-journal.ts +352 -0
  299. package/src/codex/prompt-layers.ts +967 -0
  300. package/src/codex/prompt-lock.ts +143 -0
  301. package/src/codex/quota-rejection.ts +298 -0
  302. package/src/codex/quota.ts +573 -0
  303. package/src/codex/refresh.ts +62 -0
  304. package/src/codex/reset-credit-recovery.ts +1044 -0
  305. package/src/codex/routing.ts +1888 -0
  306. package/src/codex/runtime.ts +659 -0
  307. package/src/codex/shim.ts +2170 -0
  308. package/src/codex/subagent-defaults.ts +550 -0
  309. package/src/codex/subagent-model-fallback.ts +784 -0
  310. package/src/codex/sync.ts +319 -0
  311. package/src/codex/transition-state.ts +612 -0
  312. package/src/codex/upstream-host-health.ts +368 -0
  313. package/src/codex/user-identity.ts +557 -0
  314. package/src/codex/warmup.ts +298 -0
  315. package/src/codex/websocket-registry.ts +100 -0
  316. package/src/codex/write-coordination.ts +114 -0
  317. package/src/combos/failover.ts +160 -0
  318. package/src/combos/index.ts +45 -0
  319. package/src/combos/request.ts +94 -0
  320. package/src/combos/resolve.ts +232 -0
  321. package/src/combos/types.ts +398 -0
  322. package/src/config/provider-name.ts +24 -0
  323. package/src/config.ts +4041 -0
  324. package/src/fork/register.ts +3 -0
  325. package/src/generated/compatibility-version.json +3116 -0
  326. package/src/generated/model-metadata.ts +106 -0
  327. package/src/github/star-state.ts +203 -0
  328. package/src/grok/inject.ts +530 -0
  329. package/src/grok/inspect.ts +45 -0
  330. package/src/grok/status.ts +121 -0
  331. package/src/grok/sync.ts +66 -0
  332. package/src/images/artifacts.ts +516 -0
  333. package/src/images/fulfill-video.ts +163 -0
  334. package/src/images/fulfill.ts +149 -0
  335. package/src/images/index.ts +4 -0
  336. package/src/images/loop.ts +955 -0
  337. package/src/images/plan.ts +143 -0
  338. package/src/images/synthetic-tool.ts +133 -0
  339. package/src/images/types.ts +41 -0
  340. package/src/images/xai-client.ts +141 -0
  341. package/src/images/xai-video-client.ts +163 -0
  342. package/src/index.ts +22 -0
  343. package/src/integrations/config-io.ts +269 -0
  344. package/src/integrations/journal.ts +315 -0
  345. package/src/integrations/merge.ts +135 -0
  346. package/src/integrations/mutation-flight.ts +71 -0
  347. package/src/integrations/native/ownership-preflight.ts +202 -0
  348. package/src/integrations/omp-yaml-source.ts +358 -0
  349. package/src/integrations/owned-refresh.ts +74 -0
  350. package/src/integrations/ownership.ts +111 -0
  351. package/src/integrations/registry.ts +159 -0
  352. package/src/integrations/serialize.ts +314 -0
  353. package/src/integrations/state.ts +361 -0
  354. package/src/integrations/store.ts +103 -0
  355. package/src/integrations/writer-lock.ts +98 -0
  356. package/src/integrations/writer.ts +691 -0
  357. package/src/lab/artifacts/sanitize.ts +586 -0
  358. package/src/lab/artifacts/secure-fs.ts +475 -0
  359. package/src/lab/artifacts/store.ts +310 -0
  360. package/src/lab/automation/budgets.ts +78 -0
  361. package/src/lab/automation/config-persistence.ts +256 -0
  362. package/src/lab/automation/constants.ts +39 -0
  363. package/src/lab/automation/cooldown.ts +103 -0
  364. package/src/lab/automation/dispatch.ts +211 -0
  365. package/src/lab/automation/index.ts +13 -0
  366. package/src/lab/automation/orchestrator.ts +499 -0
  367. package/src/lab/automation/persistence.ts +512 -0
  368. package/src/lab/automation/planner.ts +371 -0
  369. package/src/lab/automation/policy.ts +136 -0
  370. package/src/lab/automation/queue.ts +191 -0
  371. package/src/lab/automation/recovery.ts +24 -0
  372. package/src/lab/automation/route-context.ts +21 -0
  373. package/src/lab/automation/run-key.ts +44 -0
  374. package/src/lab/automation/runs-query.ts +34 -0
  375. package/src/lab/automation/types.ts +160 -0
  376. package/src/lab/conformance/assertion.ts +325 -0
  377. package/src/lab/conformance/digest.ts +22 -0
  378. package/src/lab/conformance/executor.ts +741 -0
  379. package/src/lab/conformance/fixture-provider.ts +27 -0
  380. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  381. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  382. package/src/lab/conformance/harness-budget.ts +47 -0
  383. package/src/lab/conformance/index.ts +5 -0
  384. package/src/lab/conformance/jcs.ts +64 -0
  385. package/src/lab/conformance/json-pointer.ts +39 -0
  386. package/src/lab/conformance/manifest.ts +180 -0
  387. package/src/lab/conformance/mcp-stub.ts +179 -0
  388. package/src/lab/conformance/negative-controls.ts +164 -0
  389. package/src/lab/conformance/observation.ts +355 -0
  390. package/src/lab/conformance/runner.ts +68 -0
  391. package/src/lab/conformance/sse-normalize.ts +59 -0
  392. package/src/lab/conformance/suite-manifest.ts +78 -0
  393. package/src/lab/conformance/types.ts +214 -0
  394. package/src/lab/constants.ts +126 -0
  395. package/src/lab/digest.ts +64 -0
  396. package/src/lab/events/errors.ts +9 -0
  397. package/src/lab/events/limits.ts +117 -0
  398. package/src/lab/events/types.ts +229 -0
  399. package/src/lab/events/validate.ts +781 -0
  400. package/src/lab/fabric/constants.ts +40 -0
  401. package/src/lab/fabric/executor.ts +492 -0
  402. package/src/lab/fabric/index.ts +80 -0
  403. package/src/lab/fabric/manifest.ts +222 -0
  404. package/src/lab/fabric/observe.ts +489 -0
  405. package/src/lab/fabric/patch.ts +79 -0
  406. package/src/lab/fabric/producer-child.ts +139 -0
  407. package/src/lab/fabric/producer-isolate.ts +276 -0
  408. package/src/lab/fabric/producer-protocol.ts +61 -0
  409. package/src/lab/fabric/scratch.ts +439 -0
  410. package/src/lab/fabric/subject.ts +106 -0
  411. package/src/lab/fabric/types.ts +134 -0
  412. package/src/lab/fabric/verifier.ts +98 -0
  413. package/src/lab/index.ts +54 -0
  414. package/src/lab/ledger/artifact-refs.ts +127 -0
  415. package/src/lab/ledger/invalidation.ts +136 -0
  416. package/src/lab/ledger/purge.ts +310 -0
  417. package/src/lab/ledger/store.ts +532 -0
  418. package/src/lab/live/credential-lease.ts +53 -0
  419. package/src/lab/live/destination.ts +155 -0
  420. package/src/lab/live/executor.ts +336 -0
  421. package/src/lab/live/inert-tools.ts +56 -0
  422. package/src/lab/live/manifest.ts +85 -0
  423. package/src/lab/live/mcp-loopback.ts +57 -0
  424. package/src/lab/live/runner.ts +19 -0
  425. package/src/lab/live/sandbox.ts +61 -0
  426. package/src/lab/live/suite-manifest.ts +41 -0
  427. package/src/lab/live/transport.ts +118 -0
  428. package/src/lab/live/types.ts +197 -0
  429. package/src/lab/observe/from-conformance.ts +301 -0
  430. package/src/lab/observe/from-live.ts +117 -0
  431. package/src/lab/paths.ts +153 -0
  432. package/src/lab/projection/rebuild.ts +495 -0
  433. package/src/lab/projection/schema.ts +135 -0
  434. package/src/lab/projection/verdicts.ts +474 -0
  435. package/src/lab/projection/verification.ts +412 -0
  436. package/src/lab/public/bundle.ts +217 -0
  437. package/src/lab/public/community-authority.ts +175 -0
  438. package/src/lab/public/community-files.ts +29 -0
  439. package/src/lab/public/community.ts +479 -0
  440. package/src/lab/public/file-safety.ts +155 -0
  441. package/src/lab/public/ids.ts +26 -0
  442. package/src/lab/public/index.ts +16 -0
  443. package/src/lab/public/mutation-lock.ts +424 -0
  444. package/src/lab/public/operator.ts +353 -0
  445. package/src/lab/public/origin-purge.ts +79 -0
  446. package/src/lab/public/origin.ts +203 -0
  447. package/src/lab/public/privacy.ts +143 -0
  448. package/src/lab/public/private-file.ts +261 -0
  449. package/src/lab/public/project.ts +124 -0
  450. package/src/lab/public/purge-test-fault.ts +21 -0
  451. package/src/lab/public/purge.ts +223 -0
  452. package/src/lab/public/registry.ts +44 -0
  453. package/src/lab/public/revocation.ts +252 -0
  454. package/src/lab/public/signature.ts +243 -0
  455. package/src/lab/public/storage.ts +105 -0
  456. package/src/lab/public/strict-json.ts +206 -0
  457. package/src/lab/public/time.ts +26 -0
  458. package/src/lab/public/types.ts +172 -0
  459. package/src/lab/public/validate.ts +391 -0
  460. package/src/lab/query/catalog.ts +101 -0
  461. package/src/lab/query/connection.ts +107 -0
  462. package/src/lab/query/constants.ts +4 -0
  463. package/src/lab/query/cursor.ts +132 -0
  464. package/src/lab/query/dto-map.ts +277 -0
  465. package/src/lab/query/errors.ts +22 -0
  466. package/src/lab/query/freshness.ts +53 -0
  467. package/src/lab/query/index.ts +45 -0
  468. package/src/lab/query/latest-observation.ts +59 -0
  469. package/src/lab/query/passive-production.ts +159 -0
  470. package/src/lab/query/queries.ts +444 -0
  471. package/src/lab/query/types.ts +266 -0
  472. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  473. package/src/lab/subject/installation-salt.ts +112 -0
  474. package/src/lab/subject/protocol-subject.ts +80 -0
  475. package/src/lab/subject/route-subject.ts +74 -0
  476. package/src/lib/abort.ts +146 -0
  477. package/src/lib/admin-secrets.ts +25 -0
  478. package/src/lib/admission.ts +83 -0
  479. package/src/lib/app-owned-memory-stores.ts +195 -0
  480. package/src/lib/app-owned-memory.ts +265 -0
  481. package/src/lib/bounded-body.ts +346 -0
  482. package/src/lib/bun-binary-validator.d.mts +3 -0
  483. package/src/lib/bun-binary-validator.mjs +18 -0
  484. package/src/lib/bun-runtime.ts +184 -0
  485. package/src/lib/bun-stream-caps.ts +130 -0
  486. package/src/lib/codex-restart-contract.ts +120 -0
  487. package/src/lib/config-ownership.ts +364 -0
  488. package/src/lib/crash-guard.ts +344 -0
  489. package/src/lib/debug-log-buffer.ts +83 -0
  490. package/src/lib/debug-settings.ts +108 -0
  491. package/src/lib/debug.ts +31 -0
  492. package/src/lib/destination-policy.ts +380 -0
  493. package/src/lib/errors.ts +406 -0
  494. package/src/lib/eventstream-decoder.ts +253 -0
  495. package/src/lib/fabric-task-execution-authority.ts +7 -0
  496. package/src/lib/fabric-task-host.ts +29 -0
  497. package/src/lib/gcp-adc.ts +341 -0
  498. package/src/lib/injection-debug-log.ts +58 -0
  499. package/src/lib/lab-activation.ts +223 -0
  500. package/src/lib/lab-live-execution-authority.ts +13 -0
  501. package/src/lib/lab-live-host.ts +30 -0
  502. package/src/lib/lab-live-pinned-sender.ts +56 -0
  503. package/src/lib/lab-live-route-production.ts +130 -0
  504. package/src/lib/lab-passive-linker-registration.ts +26 -0
  505. package/src/lib/local-management-attestation.ts +51 -0
  506. package/src/lib/local-management-capability.ts +100 -0
  507. package/src/lib/local-provider-reload-contract.ts +100 -0
  508. package/src/lib/open-url.ts +25 -0
  509. package/src/lib/optional-shutdown-hooks.ts +57 -0
  510. package/src/lib/pinned-http.ts +270 -0
  511. package/src/lib/privacy.ts +20 -0
  512. package/src/lib/process-control.ts +168 -0
  513. package/src/lib/provider-outbound.ts +210 -0
  514. package/src/lib/provider-url.ts +14 -0
  515. package/src/lib/proxy-env.ts +18 -0
  516. package/src/lib/redact.ts +521 -0
  517. package/src/lib/retry-after.ts +55 -0
  518. package/src/lib/self-launch-argv.ts +15 -0
  519. package/src/lib/server-resource-ownership.ts +71 -0
  520. package/src/lib/service-secrets.ts +25 -0
  521. package/src/lib/shadow-call.ts +61 -0
  522. package/src/lib/sidecar-tracker.ts +52 -0
  523. package/src/lib/sse-decoder.ts +364 -0
  524. package/src/lib/state-store-registrations.ts +119 -0
  525. package/src/lib/state-store-sweeper.ts +184 -0
  526. package/src/lib/system-restart-contract.ts +73 -0
  527. package/src/lib/test-home-guard.ts +90 -0
  528. package/src/lib/token-estimate.ts +86 -0
  529. package/src/lib/tool-argument-integers.ts +202 -0
  530. package/src/lib/translator-budget.ts +400 -0
  531. package/src/lib/upstream-http-version.ts +57 -0
  532. package/src/lib/upstream-reachability.ts +95 -0
  533. package/src/lib/upstream-retry.ts +392 -0
  534. package/src/lib/win-exec.ts +115 -0
  535. package/src/lib/win-paths.ts +68 -0
  536. package/src/lib/windows-atomic-replace.ts +156 -0
  537. package/src/lib/windows-elevation.ts +773 -0
  538. package/src/lib/windows-secret-acl.ts +854 -0
  539. package/src/lib/windows-service-wrappers.ts +72 -0
  540. package/src/lib/windows-text.ts +106 -0
  541. package/src/lib/windows-user-principal.ts +341 -0
  542. package/src/lib/winsw.ts +403 -0
  543. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  544. package/src/oauth/account-import/index.ts +15 -0
  545. package/src/oauth/account-import/parser.ts +83 -0
  546. package/src/oauth/account-import/registry.ts +18 -0
  547. package/src/oauth/account-import/service.ts +75 -0
  548. package/src/oauth/account-import/types.ts +91 -0
  549. package/src/oauth/anthropic-routing.ts +594 -0
  550. package/src/oauth/anthropic.ts +188 -0
  551. package/src/oauth/antigravity-routing.ts +151 -0
  552. package/src/oauth/callback-server.ts +300 -0
  553. package/src/oauth/chatgpt.ts +161 -0
  554. package/src/oauth/command-code.ts +239 -0
  555. package/src/oauth/cursor.ts +252 -0
  556. package/src/oauth/github-copilot.ts +428 -0
  557. package/src/oauth/google-antigravity.ts +262 -0
  558. package/src/oauth/health.ts +407 -0
  559. package/src/oauth/index.ts +1504 -0
  560. package/src/oauth/key-providers.ts +124 -0
  561. package/src/oauth/kimi.ts +227 -0
  562. package/src/oauth/kiro-credentials.ts +726 -0
  563. package/src/oauth/kiro.ts +621 -0
  564. package/src/oauth/local-token-detect.ts +130 -0
  565. package/src/oauth/log.ts +50 -0
  566. package/src/oauth/login-cli.ts +223 -0
  567. package/src/oauth/nous.ts +798 -0
  568. package/src/oauth/pkce.ts +15 -0
  569. package/src/oauth/store.ts +728 -0
  570. package/src/oauth/token-guardian.ts +309 -0
  571. package/src/oauth/types.ts +62 -0
  572. package/src/oauth/xai.ts +241 -0
  573. package/src/providers/alibaba-region-backup.ts +75 -0
  574. package/src/providers/alibaba-region-migration.ts +156 -0
  575. package/src/providers/alibaba-region-startup.ts +36 -0
  576. package/src/providers/antigravity-models.ts +695 -0
  577. package/src/providers/antigravity-quota.ts +216 -0
  578. package/src/providers/api-keys.ts +140 -0
  579. package/src/providers/base-url-choices.ts +74 -0
  580. package/src/providers/codex-capacity.ts +292 -0
  581. package/src/providers/command-code-efforts.ts +144 -0
  582. package/src/providers/context-cap.ts +82 -0
  583. package/src/providers/cursor-pool.ts +72 -0
  584. package/src/providers/derive.ts +586 -0
  585. package/src/providers/fastwire.ts +501 -0
  586. package/src/providers/free-directory.ts +187 -0
  587. package/src/providers/github-copilot-transport.ts +56 -0
  588. package/src/providers/google-vertex-location.ts +14 -0
  589. package/src/providers/key-failover.ts +271 -0
  590. package/src/providers/kiro-models.ts +67 -0
  591. package/src/providers/label.ts +19 -0
  592. package/src/providers/model-discovery-limits.ts +16 -0
  593. package/src/providers/model-discovery.ts +449 -0
  594. package/src/providers/model-rename-migration.ts +255 -0
  595. package/src/providers/model-rename-startup.ts +28 -0
  596. package/src/providers/openai-sidecar.ts +243 -0
  597. package/src/providers/openai-tier-startup.ts +56 -0
  598. package/src/providers/openai-tiers.ts +423 -0
  599. package/src/providers/openai-virtual-models.ts +83 -0
  600. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  601. package/src/providers/openrouter-routing.ts +102 -0
  602. package/src/providers/provider-id-rewrite.ts +185 -0
  603. package/src/providers/quota.ts +2345 -0
  604. package/src/providers/registry.ts +2918 -0
  605. package/src/providers/replit/constants.ts +27 -0
  606. package/src/providers/replit/derive.ts +85 -0
  607. package/src/providers/replit/headers.ts +28 -0
  608. package/src/providers/replit/origin.ts +55 -0
  609. package/src/providers/replit/pair-install-response.ts +72 -0
  610. package/src/providers/replit/probe.ts +199 -0
  611. package/src/providers/replit/setup.ts +350 -0
  612. package/src/providers/request-pacing.ts +310 -0
  613. package/src/providers/service-tier.ts +277 -0
  614. package/src/providers/slug-codec.ts +103 -0
  615. package/src/providers/static-model-discovery.ts +86 -0
  616. package/src/providers/xai-responses-opt-in.ts +15 -0
  617. package/src/providers/xai-transport.ts +148 -0
  618. package/src/reasoning-effort.ts +183 -0
  619. package/src/responses/compaction.ts +142 -0
  620. package/src/responses/custom-tool-compat.ts +266 -0
  621. package/src/responses/hosted-tool-policy.ts +9 -0
  622. package/src/responses/namespace-tool-compat.ts +355 -0
  623. package/src/responses/parser.ts +838 -0
  624. package/src/responses/provider-continuation.ts +98 -0
  625. package/src/responses/provider-opaque-metadata.ts +73 -0
  626. package/src/responses/reasoning-envelope.ts +60 -0
  627. package/src/responses/reasoning-replay-cache.ts +426 -0
  628. package/src/responses/schema.ts +165 -0
  629. package/src/responses/spill-store.ts +459 -0
  630. package/src/responses/state.ts +1433 -0
  631. package/src/responses/thought-signature-replay.ts +347 -0
  632. package/src/responses/tool-groups.ts +19 -0
  633. package/src/responses/tool-search-compat.ts +301 -0
  634. package/src/responses/truncated-stop-reason.ts +60 -0
  635. package/src/router.ts +761 -0
  636. package/src/routing/analytics.ts +378 -0
  637. package/src/routing/capability.ts +244 -0
  638. package/src/routing/compatibility/assemble.ts +73 -0
  639. package/src/routing/compatibility/behavior.ts +278 -0
  640. package/src/routing/compatibility/catalog.ts +99 -0
  641. package/src/routing/compatibility/endpoint.ts +52 -0
  642. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  643. package/src/routing/compatibility/policy.ts +181 -0
  644. package/src/routing/compatibility/provider-slot.ts +56 -0
  645. package/src/routing/compatibility/reader.ts +110 -0
  646. package/src/routing/compatibility/subject.ts +191 -0
  647. package/src/routing/compatibility/types.ts +64 -0
  648. package/src/routing/compatibility/version.ts +104 -0
  649. package/src/routing/cost.ts +77 -0
  650. package/src/routing/evaluator.ts +495 -0
  651. package/src/routing/health.ts +412 -0
  652. package/src/routing/history/cursor.ts +43 -0
  653. package/src/routing/history/indexer.ts +605 -0
  654. package/src/routing/history/schema.ts +72 -0
  655. package/src/routing/profile-namespace.ts +15 -0
  656. package/src/routing/profile.ts +547 -0
  657. package/src/routing/quota.ts +145 -0
  658. package/src/routing/request-evidence.ts +45 -0
  659. package/src/routing/trace.ts +776 -0
  660. package/src/server/adapter-resolve.ts +53 -0
  661. package/src/server/auth-cors.ts +751 -0
  662. package/src/server/background-lifecycle.ts +182 -0
  663. package/src/server/chat-completions.ts +442 -0
  664. package/src/server/chat-native-sse.ts +331 -0
  665. package/src/server/chat-native.ts +426 -0
  666. package/src/server/claude-messages.ts +1030 -0
  667. package/src/server/direct-local-http.ts +347 -0
  668. package/src/server/effort-policy.ts +190 -0
  669. package/src/server/github-copilot-responses-repair.ts +338 -0
  670. package/src/server/gui-static.ts +152 -0
  671. package/src/server/image-retry.ts +42 -0
  672. package/src/server/images.ts +568 -0
  673. package/src/server/index.ts +1813 -0
  674. package/src/server/lifecycle.ts +498 -0
  675. package/src/server/live.ts +717 -0
  676. package/src/server/local-management-read-client.ts +90 -0
  677. package/src/server/local-provider-reload-client.ts +137 -0
  678. package/src/server/management/agent-settings-routes.ts +1433 -0
  679. package/src/server/management/api-access.ts +141 -0
  680. package/src/server/management/api-key-usage.ts +193 -0
  681. package/src/server/management/body.ts +41 -0
  682. package/src/server/management/combo-routes.ts +263 -0
  683. package/src/server/management/config-routes.ts +835 -0
  684. package/src/server/management/context.ts +113 -0
  685. package/src/server/management/integration-routes.ts +498 -0
  686. package/src/server/management/lab-automation-routes.ts +206 -0
  687. package/src/server/management/lab-routes.ts +563 -0
  688. package/src/server/management/logs-usage-routes.ts +586 -0
  689. package/src/server/management/model-routes.ts +560 -0
  690. package/src/server/management/model-rows.ts +163 -0
  691. package/src/server/management/native-integration-routes.ts +769 -0
  692. package/src/server/management/oauth-account-routes.ts +637 -0
  693. package/src/server/management/provider-capability-config.ts +48 -0
  694. package/src/server/management/provider-routes.ts +1033 -0
  695. package/src/server/management/replit-provider-routes.ts +86 -0
  696. package/src/server/management/request-history-routes.ts +191 -0
  697. package/src/server/management/routing-analytics-routes.ts +74 -0
  698. package/src/server/management/routing-profile-routes.ts +385 -0
  699. package/src/server/management/shared.ts +286 -0
  700. package/src/server/management/sidebar-routes.ts +106 -0
  701. package/src/server/management/storage-log-guard-routes.ts +186 -0
  702. package/src/server/management/sync-response.ts +69 -0
  703. package/src/server/management/system-restart.ts +435 -0
  704. package/src/server/management/system-routes.ts +194 -0
  705. package/src/server/management/usage-summary-cache.ts +94 -0
  706. package/src/server/management/vision-sidecar-options.ts +167 -0
  707. package/src/server/management/web-search-sidecar-options.ts +120 -0
  708. package/src/server/management-api.ts +314 -0
  709. package/src/server/management-auth.ts +482 -0
  710. package/src/server/memory-watchdog.ts +156 -0
  711. package/src/server/passive-route-linker.ts +66 -0
  712. package/src/server/port-reclaim.ts +307 -0
  713. package/src/server/ports.ts +156 -0
  714. package/src/server/proxy-liveness.ts +328 -0
  715. package/src/server/readiness.ts +99 -0
  716. package/src/server/relay-eager.ts +353 -0
  717. package/src/server/relay.ts +1209 -0
  718. package/src/server/request-decompress.ts +239 -0
  719. package/src/server/request-log-conversation.ts +168 -0
  720. package/src/server/request-log.ts +1259 -0
  721. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  722. package/src/server/responses/agent-task-recovery.ts +465 -0
  723. package/src/server/responses/collaboration.ts +551 -0
  724. package/src/server/responses/compact.ts +771 -0
  725. package/src/server/responses/core.ts +5389 -0
  726. package/src/server/responses/empty-completion-guard.ts +276 -0
  727. package/src/server/responses/encrypted-payload.ts +331 -0
  728. package/src/server/responses/fetch-helpers.ts +232 -0
  729. package/src/server/responses/input-admission.ts +185 -0
  730. package/src/server/responses/pacing-overload.ts +13 -0
  731. package/src/server/responses/passthrough-error.ts +78 -0
  732. package/src/server/responses/policy-fallback.ts +178 -0
  733. package/src/server/responses/responses-field-backfill.ts +251 -0
  734. package/src/server/responses/terminal-guard.ts +251 -0
  735. package/src/server/responses/upstream-error.ts +53 -0
  736. package/src/server/responses/ws-upstream.ts +308 -0
  737. package/src/server/responses-custom-tool-repair.ts +282 -0
  738. package/src/server/responses-image-gen-repair.ts +132 -0
  739. package/src/server/responses-item-id-repair.ts +272 -0
  740. package/src/server/responses-json-events.ts +90 -0
  741. package/src/server/responses-model-rewrite.ts +29 -0
  742. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  743. package/src/server/responses-snapshot-repair.ts +621 -0
  744. package/src/server/responses-terminal-repair.ts +342 -0
  745. package/src/server/responses-tool-search-repair.ts +267 -0
  746. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  747. package/src/server/responses.ts +25 -0
  748. package/src/server/search.ts +201 -0
  749. package/src/server/sse-frame-buffer.ts +292 -0
  750. package/src/server/sse-payload-rewrite.ts +263 -0
  751. package/src/server/startup-action-control.ts +315 -0
  752. package/src/server/startup-health-cache.ts +131 -0
  753. package/src/server/system-env.ts +484 -0
  754. package/src/server/windows-tcp-drop.ts +184 -0
  755. package/src/server/windows-tray-control.ts +41 -0
  756. package/src/server/ws-bridge.ts +472 -0
  757. package/src/service-manager-probe.ts +892 -0
  758. package/src/service.ts +3575 -0
  759. package/src/sidecar/auth.ts +92 -0
  760. package/src/sidecar/candidates.ts +83 -0
  761. package/src/stall-timeout.ts +20 -0
  762. package/src/storage/cleanup-job.ts +57 -0
  763. package/src/storage/cleanup.ts +3085 -0
  764. package/src/storage/policy-job.ts +457 -0
  765. package/src/storage/policy-scheduler.ts +40 -0
  766. package/src/storage/policy-worker.ts +59 -0
  767. package/src/storage/policy.ts +527 -0
  768. package/src/storage/restore-job.ts +299 -0
  769. package/src/storage/restore-worker.ts +58 -0
  770. package/src/storage/scanner.ts +238 -0
  771. package/src/storage/storage-mutation-coordinator.ts +139 -0
  772. package/src/storage/worker-lifecycle.ts +215 -0
  773. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  774. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  775. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  776. package/src/tray/assets/opencodex-tray.png +0 -0
  777. package/src/tray/windows-tray.ps1 +364 -0
  778. package/src/tray/windows.ts +757 -0
  779. package/src/types/accounts.ts +37 -0
  780. package/src/types/config.ts +876 -0
  781. package/src/types/provider.ts +545 -0
  782. package/src/types/request.ts +384 -0
  783. package/src/types/tools.ts +131 -0
  784. package/src/types/wire.ts +80 -0
  785. package/src/types.ts +106 -0
  786. package/src/update/badge.ts +72 -0
  787. package/src/update/index.ts +415 -0
  788. package/src/update/job.ts +1887 -0
  789. package/src/update/notify.ts +263 -0
  790. package/src/update/npm-cache-preflight.d.mts +47 -0
  791. package/src/update/npm-cache-preflight.mjs +201 -0
  792. package/src/update/npm-invocation.d.mts +23 -0
  793. package/src/update/npm-invocation.mjs +94 -0
  794. package/src/update/transactional-install.d.mts +22 -0
  795. package/src/update/transactional-install.mjs +259 -0
  796. package/src/update/tray-update-plan.d.mts +18 -0
  797. package/src/update/tray-update-plan.mjs +38 -0
  798. package/src/usage/cost.ts +625 -0
  799. package/src/usage/debug.ts +97 -0
  800. package/src/usage/expected-prices.ts +416 -0
  801. package/src/usage/log.ts +1223 -0
  802. package/src/usage/summary.ts +753 -0
  803. package/src/usage/totals.ts +14 -0
  804. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  805. package/src/usage/user-cost-overlays.ts +314 -0
  806. package/src/vision/anthropic-describe.ts +189 -0
  807. package/src/vision/backends.ts +97 -0
  808. package/src/vision/describe.ts +131 -0
  809. package/src/vision/eligibility.ts +250 -0
  810. package/src/vision/index.ts +681 -0
  811. package/src/vision/reasoning.ts +55 -0
  812. package/src/vision/routed-describe.ts +175 -0
  813. package/src/vision/timeout-bounds.ts +9 -0
  814. package/src/web-search/anthropic-executor.ts +195 -0
  815. package/src/web-search/backends.ts +108 -0
  816. package/src/web-search/exa-executor.ts +88 -0
  817. package/src/web-search/executor.ts +113 -0
  818. package/src/web-search/format-result.ts +89 -0
  819. package/src/web-search/gemini-executor.ts +141 -0
  820. package/src/web-search/index.ts +331 -0
  821. package/src/web-search/loop.ts +896 -0
  822. package/src/web-search/parse.ts +315 -0
  823. package/src/web-search/progress-stream.ts +342 -0
  824. package/src/web-search/sources.ts +60 -0
  825. package/src/web-search/synthetic-tool.ts +47 -0
  826. package/src/web-search/xai-executor.ts +219 -0
@@ -0,0 +1,141 @@
1
+ import type { OcxConfig } from "../../types";
2
+ import { probeHostname } from "../proxy-liveness";
3
+
4
+ export interface ApiAccessEndpoints {
5
+ baseUrl: string;
6
+ responsesEndpoint: string;
7
+ chatCompletionsEndpoint: string;
8
+ messagesEndpoint: string;
9
+ modelsEndpoint: string;
10
+ claudeCodeEnabled: boolean;
11
+ /** Back-compat alias for older GUI clients. */
12
+ endpoint: string;
13
+ }
14
+
15
+ export type BuildApiAccessEndpointsOptions = {
16
+ /** Full request URL (preferred when the bind host is a wildcard). */
17
+ requestUrl?: string | URL | null;
18
+ /** Raw `Host` header from the inbound request. */
19
+ requestHost?: string | null;
20
+ /** Raw `Origin` header from the inbound request. */
21
+ requestOrigin?: string | null;
22
+ };
23
+
24
+ function isWildcardBindHost(hostname: string | undefined): boolean {
25
+ const trimmed = (hostname ?? "").trim();
26
+ return !trimmed || trimmed === "0.0.0.0" || trimmed === "::" || trimmed === "[::]";
27
+ }
28
+
29
+ /** Bracket bare IPv6 literals for URL authority composition. */
30
+ export function formatAuthorityHost(hostname: string): string {
31
+ const trimmed = hostname.trim();
32
+ if (!trimmed) return "127.0.0.1";
33
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) return trimmed;
34
+ return trimmed.includes(":") ? `[${trimmed}]` : trimmed;
35
+ }
36
+
37
+ function hostnameFromAuthority(authority: string): string | null {
38
+ const raw = authority.trim();
39
+ if (!raw) return null;
40
+ if (raw.startsWith("[")) {
41
+ const end = raw.indexOf("]");
42
+ if (end > 0) return raw.slice(1, end) || null;
43
+ return null;
44
+ }
45
+ // Host headers for IPv6 are bracketed; treat multi-colon values as unusable.
46
+ if (raw.includes(":") && raw.split(":").length > 2) return null;
47
+ const colon = raw.lastIndexOf(":");
48
+ if (colon > 0 && /^\d+$/.test(raw.slice(colon + 1))) {
49
+ return raw.slice(0, colon) || null;
50
+ }
51
+ return raw;
52
+ }
53
+
54
+ function originBaseUrl(raw: string): string | null {
55
+ try {
56
+ const url = new URL(raw);
57
+ if (!url.hostname || isWildcardBindHost(url.hostname)) return null;
58
+ return `${url.protocol}//${url.host}/v1`;
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Prefer the client's request host/origin when the proxy is bound to a wildcard.
66
+ * Falls back to loopback only when no usable request context is available.
67
+ */
68
+ export function resolveApiAccessBaseUrl(
69
+ config: Pick<OcxConfig, "hostname" | "port">,
70
+ opts: BuildApiAccessEndpointsOptions = {},
71
+ ): string {
72
+ const port = config.port ?? 10100;
73
+
74
+ if (!isWildcardBindHost(config.hostname)) {
75
+ return `http://${probeHostname(config.hostname)}:${port}/v1`;
76
+ }
77
+
78
+ const fromOrigin = opts.requestOrigin ? originBaseUrl(opts.requestOrigin) : null;
79
+ if (fromOrigin) return fromOrigin;
80
+
81
+ if (opts.requestUrl) {
82
+ try {
83
+ const url = typeof opts.requestUrl === "string" ? new URL(opts.requestUrl) : opts.requestUrl;
84
+ if (url.hostname && !isWildcardBindHost(url.hostname)) {
85
+ return `${url.protocol}//${url.host}/v1`;
86
+ }
87
+ } catch {
88
+ /* ignore malformed request URL */
89
+ }
90
+ }
91
+
92
+ const hostHeader = opts.requestHost?.trim();
93
+ if (hostHeader) {
94
+ const hostname = hostnameFromAuthority(hostHeader);
95
+ if (hostname && !isWildcardBindHost(hostname)) {
96
+ // Preserve an explicit port from the Host header; otherwise use the bind port.
97
+ const hasPort = hostHeader.startsWith("[")
98
+ ? /\]:\d+$/.test(hostHeader)
99
+ : /:\d+$/.test(hostHeader) && hostHeader.split(":").length === 2;
100
+ const authority = hasPort
101
+ ? (hostHeader.startsWith("[") ? hostHeader : hostHeader)
102
+ : `${formatAuthorityHost(hostname)}:${port}`;
103
+ return `http://${authority}/v1`;
104
+ }
105
+ }
106
+
107
+ return `http://127.0.0.1:${port}/v1`;
108
+ }
109
+
110
+ /** @deprecated Prefer resolveApiAccessBaseUrl; retained for focused host-format tests. */
111
+ export function resolveApiAccessDisplayHost(
112
+ configHostname: string | undefined,
113
+ opts: BuildApiAccessEndpointsOptions = {},
114
+ ): string {
115
+ if (!isWildcardBindHost(configHostname)) {
116
+ return probeHostname(configHostname);
117
+ }
118
+ try {
119
+ return new URL(resolveApiAccessBaseUrl({ hostname: configHostname, port: 10100 }, opts)).hostname
120
+ || "127.0.0.1";
121
+ } catch {
122
+ return "127.0.0.1";
123
+ }
124
+ }
125
+
126
+ export function buildApiAccessEndpoints(
127
+ config: OcxConfig,
128
+ opts: BuildApiAccessEndpointsOptions = {},
129
+ ): ApiAccessEndpoints {
130
+ const baseUrl = resolveApiAccessBaseUrl(config, opts);
131
+ const responsesEndpoint = `${baseUrl}/responses`;
132
+ return {
133
+ baseUrl,
134
+ responsesEndpoint,
135
+ chatCompletionsEndpoint: `${baseUrl}/chat/completions`,
136
+ messagesEndpoint: `${baseUrl}/messages`,
137
+ modelsEndpoint: `${baseUrl}/models`,
138
+ claudeCodeEnabled: config.claudeCode?.enabled !== false,
139
+ endpoint: responsesEndpoint,
140
+ };
141
+ }
@@ -0,0 +1,193 @@
1
+ import {
2
+ currentUsageLogRevision,
3
+ readUsageSnapshotForManagement,
4
+ usageLogIdentityKey,
5
+ type PersistedUsageEntry,
6
+ } from "../../usage/log";
7
+
8
+ /**
9
+ * Per-key usage as the API tab renders it.
10
+ *
11
+ * A discriminated union rather than numbers with a flag beside them: when two
12
+ * config entries share an id there IS no per-key total, and an optional marker
13
+ * next to `requests7d: 7` invites a consumer to render the 7 anyway.
14
+ */
15
+ export type ApiKeyUsage =
16
+ | { ambiguous: true }
17
+ | { ambiguous?: false; requests7d: number; totalRequests: number; lastUsedAt?: string };
18
+
19
+ export interface ApiKeyUsageSnapshot {
20
+ rollup: Map<string, ApiKeyUsage>;
21
+ historyTruncated?: true;
22
+ /**
23
+ * Earliest row carrying a recognized `admissionKind`. A property of the DATA
24
+ * SET, not of a key, so it is singular and lives beside the map: it is what
25
+ * lets the GUI tell "this key was used zero times" from "nothing is
26
+ * attributable yet". Keyed on the kind rather than on `apiKeyId`, because an
27
+ * environment or loopback row is attributed traffic with no configured key.
28
+ */
29
+ attributionSince?: string;
30
+ }
31
+
32
+ const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
33
+
34
+ /**
35
+ * A timestamp we can actually do date arithmetic with.
36
+ *
37
+ * `usage.jsonl` is hand-editable and JSON permits numbers outside the Date
38
+ * range: `1e309` survives normalization and then throws `RangeError` from
39
+ * `toISOString()`. Since the caller catches to protect key management, one bad
40
+ * row would have zeroed the rollup for EVERY key — active keys reported as
41
+ * unused is exactly the wrong answer to hand someone deciding what to delete.
42
+ */
43
+ function usableTimestamp(value: unknown): number | null {
44
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
45
+ return Number.isNaN(new Date(value).getTime()) ? null : value;
46
+ }
47
+
48
+ /**
49
+ * Pure: one pass over an already-read snapshot, so it is unit-testable without
50
+ * touching the filesystem.
51
+ *
52
+ * Rows are bucketed only when `admissionKind === "configured"`. Keying on
53
+ * `apiKeyId` alone would let a hand-edited entry whose id is `loopback` absorb
54
+ * traffic it never admitted.
55
+ */
56
+ export function rollupApiKeyUsage(
57
+ entries: PersistedUsageEntry[],
58
+ configuredIds: string[],
59
+ now: number = Date.now(),
60
+ ): ApiKeyUsageSnapshot {
61
+ const duplicated = new Set<string>();
62
+ const seen = new Set<string>();
63
+ for (const id of configuredIds) {
64
+ if (seen.has(id)) duplicated.add(id);
65
+ seen.add(id);
66
+ }
67
+
68
+ const totals = new Map<string, { requests7d: number; totalRequests: number; lastUsedAt?: string }>();
69
+ let attributionSince: number | undefined;
70
+ const cutoff = now - SEVEN_DAYS_MS;
71
+
72
+ for (const entry of entries) {
73
+ if (!entry.admissionKind) continue;
74
+ const timestamp = usableTimestamp(entry.timestamp);
75
+ if (timestamp !== null && (attributionSince === undefined || timestamp < attributionSince)) {
76
+ attributionSince = timestamp;
77
+ }
78
+ if (entry.admissionKind !== "configured" || !entry.apiKeyId) continue;
79
+
80
+ const bucket = totals.get(entry.apiKeyId) ?? { requests7d: 0, totalRequests: 0 };
81
+ // The request happened even if its clock reading is unusable, so it still
82
+ // counts toward the total; only the time-based fields are skipped.
83
+ bucket.totalRequests += 1;
84
+ if (timestamp !== null) {
85
+ if (timestamp >= cutoff) bucket.requests7d += 1;
86
+ const iso = new Date(timestamp).toISOString();
87
+ if (!bucket.lastUsedAt || iso > bucket.lastUsedAt) bucket.lastUsedAt = iso;
88
+ }
89
+ totals.set(entry.apiKeyId, bucket);
90
+ }
91
+
92
+ const rollup = new Map<string, ApiKeyUsage>();
93
+ for (const id of configuredIds) {
94
+ if (duplicated.has(id)) {
95
+ rollup.set(id, { ambiguous: true });
96
+ continue;
97
+ }
98
+ rollup.set(id, totals.get(id) ?? { requests7d: 0, totalRequests: 0 });
99
+ }
100
+ return {
101
+ rollup,
102
+ ...(attributionSince !== undefined ? { attributionSince: new Date(attributionSince).toISOString() } : {}),
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Rollup cache keyed by the exact usage-log revision, mirroring the /api/usage
108
+ * summary cache. Without it, every key-list read reparses an append-only log
109
+ * that only ever grows — and the GUI fetches this route on mount and after every
110
+ * create/rename/delete. The compact rollup is a handful of counters per key, so
111
+ * caching it costs nothing; a new row changes the revision and invalidates it.
112
+ */
113
+ let rollupCache: { revisionKey: string; expiresAt: number; lastSeenSize?: number; snapshot: ApiKeyUsageSnapshot } | null = null;
114
+
115
+ /**
116
+ * The rollup is a function of the log AND of the clock: a request ages out of
117
+ * the seven-day window with no write to bump the file revision, so a purely
118
+ * revision-keyed entry would report a stale `requests7d` indefinitely.
119
+ *
120
+ * A minute is the whole rule. Deriving the exact next-transition instant would
121
+ * mean tracking the OLDEST counted request per key, which the compact rollup
122
+ * deliberately does not keep — and a count that can be at most 60s stale is
123
+ * already far tighter than the window it describes.
124
+ */
125
+ const ROLLUP_CACHE_TTL_MS = 60_000;
126
+
127
+ /** Test seam: the cache is module state and would otherwise leak between cases. */
128
+ export function clearApiKeyUsageCacheForTests(): void {
129
+ rollupCache = null;
130
+ }
131
+
132
+ /**
133
+ * Reads the durable usage snapshot the way /api/usage does, then rolls it up.
134
+ *
135
+ * Never throws: an unreadable snapshot yields empty rollups and no
136
+ * `attributionSince`. Key management working matters more than usage numbers
137
+ * being present, and the GUI already treats an absent field as "no data".
138
+ */
139
+ export function cacheApiKeyUsageFromSnapshot(
140
+ entries: PersistedUsageEntry[],
141
+ configuredIds: string[],
142
+ identityKey: string,
143
+ lastSeenSize: number,
144
+ truncated: boolean,
145
+ maxReadBytes: number | undefined,
146
+ now: number = Date.now(),
147
+ ): ApiKeyUsageSnapshot {
148
+ const idsKey = JSON.stringify([configuredIds, maxReadBytes]);
149
+ const rolled = {
150
+ ...rollupApiKeyUsage(entries, configuredIds, now),
151
+ ...(truncated ? { historyTruncated: true as const } : {}),
152
+ };
153
+ rollupCache = {
154
+ revisionKey: `${identityKey}|${idsKey}`,
155
+ expiresAt: now + ROLLUP_CACHE_TTL_MS,
156
+ lastSeenSize,
157
+ snapshot: rolled,
158
+ };
159
+ return rolled;
160
+ }
161
+
162
+ export async function readApiKeyUsageRollup(configuredIds: string[], maxReadBytes?: number): Promise<ApiKeyUsageSnapshot> {
163
+ // JSON rather than a joined string: ids are only validated as non-empty
164
+ // strings, so `["a\0b","c"]` and `["a","b\0c"]` join to the same value and one
165
+ // config could be served the other's cached rollup.
166
+ const idsKey = JSON.stringify([configuredIds, maxReadBytes]);
167
+ const now = Date.now();
168
+ try {
169
+ const observed = currentUsageLogRevision();
170
+ const observedKey = `${usageLogIdentityKey(observed)}|${idsKey}`;
171
+ const observedSize = observed?.size ?? 0;
172
+ if (rollupCache?.revisionKey === observedKey && now < rollupCache.expiresAt && observedSize >= (rollupCache.lastSeenSize ?? 0)) {
173
+ return rollupCache.snapshot;
174
+ }
175
+
176
+ const snapshot = await readUsageSnapshotForManagement(maxReadBytes);
177
+ const rolled = {
178
+ ...rollupApiKeyUsage(snapshot.entries, configuredIds, now),
179
+ ...(snapshot.truncatedPrefixBytes > 0 || snapshot.entriesTruncated ? { historyTruncated: true as const } : {}),
180
+ };
181
+ rollupCache = {
182
+ revisionKey: `${usageLogIdentityKey(snapshot.revision)}|${idsKey}`,
183
+ expiresAt: now + ROLLUP_CACHE_TTL_MS,
184
+ lastSeenSize: snapshot.revision?.size ?? 0,
185
+ snapshot: rolled,
186
+ };
187
+ return rolled;
188
+ } catch {
189
+ const rollup = new Map<string, ApiKeyUsage>();
190
+ for (const id of configuredIds) rollup.set(id, { requests7d: 0, totalRequests: 0 });
191
+ return { rollup };
192
+ }
193
+ }
@@ -0,0 +1,41 @@
1
+ import type { OcxConfig } from "../../types";
2
+ import { jsonResponse } from "../auth-cors";
3
+ import {
4
+ DecompressedBodyTooLargeError,
5
+ readBoundedJsonRequestBody,
6
+ } from "../request-decompress";
7
+
8
+ export const MANAGEMENT_JSON_BODY_MAX_BYTES = 4 * 1024 * 1024;
9
+
10
+ export function readManagementJsonBody<T = unknown>(req: Request): Promise<T> {
11
+ return readBoundedJsonRequestBody(req, MANAGEMENT_JSON_BODY_MAX_BYTES) as Promise<T>;
12
+ }
13
+
14
+ export function readOptionalManagementJsonBody<T = unknown>(req: Request): Promise<T> {
15
+ return readBoundedJsonRequestBody(req, MANAGEMENT_JSON_BODY_MAX_BYTES, undefined, {
16
+ emptyBodyFallback: {},
17
+ }) as Promise<T>;
18
+ }
19
+
20
+ export function managementBodyTooLargeResponse(
21
+ error: unknown,
22
+ req: Request,
23
+ config: OcxConfig,
24
+ ): Response | null {
25
+ return error instanceof DecompressedBodyTooLargeError
26
+ ? jsonResponse({ error: "request body too large" }, 413, req, config)
27
+ : null;
28
+ }
29
+
30
+ export function rethrowManagementBodyTooLarge(error: unknown): void {
31
+ if (error instanceof DecompressedBodyTooLargeError) throw error;
32
+ }
33
+
34
+ export async function readManagementJsonBodyOr<T>(req: Request, fallback: T): Promise<unknown | T> {
35
+ try {
36
+ return await readManagementJsonBody(req);
37
+ } catch (error) {
38
+ rethrowManagementBodyTooLarge(error);
39
+ return fallback;
40
+ }
41
+ }
@@ -0,0 +1,263 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import type { CatalogModel } from "../../codex/catalog";
4
+ import { catalogModelSlug, invalidateCodexModelsCache, nativeModelRows, uniqueCatalogModelsForPublicList } from "../../codex/catalog";
5
+ import {
6
+ DEFAULT_SUBAGENT_MODELS,
7
+ codexAutoStartEnabled,
8
+ hasOwnProvider,
9
+ isValidProviderName,
10
+ multiAgentGuidanceEnabled,
11
+ providerBaseUrlConfigError,
12
+ providerHeadersConfigError,
13
+ saveConfigPreservingClaudeCode,
14
+ } from "../../config";
15
+ import {
16
+ clearLoginState,
17
+ getLoginStatus,
18
+ isPublicOAuthProvider,
19
+ listOAuthProviders,
20
+ startLoginFlow,
21
+ submitManualLoginCode,
22
+ upsertOAuthProvider,
23
+ } from "../../oauth";
24
+ import { removeCredential } from "../../oauth/store";
25
+ import { providerDestinationResolvedError } from "../../lib/destination-policy";
26
+ import { enrichProviderFromCatalog, listKeyLoginProviders } from "../../oauth/key-providers";
27
+ import { deriveProviderPresets } from "../../providers/derive";
28
+ import { providerCodexAccountMode } from "../../providers/registry";
29
+ import { routedSlug, slugEquals } from "../../providers/slug-codec";
30
+ import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../providers/quota";
31
+ import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
32
+ import {
33
+ CODEX_ACCOUNT_NAMESPACE_COMBO_ALIAS_COLLISION_ERROR,
34
+ codexAccountNamespaceForModel,
35
+ } from "../../codex/account-namespace-match";
36
+ import { clearThreadAccountMap } from "../../codex/routing";
37
+ import { primeCodexPoolQuotas } from "../../codex/auth-api";
38
+ import { DEFAULT_PROVIDER_CONTEXT_CAP, globalContextCapValue, providerContextCap, providerContextCaps, setAllProviderContextCaps, setGlobalContextCapValue, setProviderContextCap } from "../../providers/context-cap";
39
+ import { resolveCodexHomeDir } from "../../codex/home";
40
+ import { readUsageEntries } from "../../usage/log";
41
+ import { getUsageDebugLogEntries } from "../../usage/debug";
42
+ import { parseRange, parseUsageSurface, summarizeUsage } from "../../usage/summary";
43
+ import { stripCodexRuntimeProviderFields } from "../../codex/auth-context";
44
+ import { getProviderRegistryEntry } from "../../providers/registry";
45
+ import { getDebugLogEntries } from "../../lib/debug-log-buffer";
46
+ import { getInjectionDebugLogEntries } from "../../lib/injection-debug-log";
47
+ import {
48
+ clearDebugSettings,
49
+ clearDebugSetting,
50
+ getDebugSettings,
51
+ setDebugSettings,
52
+ type DebugFlag,
53
+ } from "../../lib/debug-settings";
54
+ import type { OcxClaudeCodeConfig, OcxConfig, OcxCustomModel, OcxProviderConfig } from "../../types";
55
+ import { drainAndShutdown } from "../lifecycle";
56
+ import { reconcileLiveStateStores } from "../../lib/state-store-registrations";
57
+ import { filterRequestLogs, getRequestLogEntries, type RequestLogEntry } from "../request-log";
58
+ import { estimateComboCost, estimateRequestCost, normalizeCostTokens, tokensPerSecond } from "../../usage/cost";
59
+ import type { PersistedUsageAttempt } from "../../usage/log";
60
+ import { isAllowedRequestOrigin, jsonResponse, providerManagementConfigError, publicProviderBaseUrl, safeConfigDTO } from "../auth-cors";
61
+ import { applySystemEnvToggle } from "../system-env";
62
+
63
+ import { isPlainRecord, parseDebugLogQuery, tokPerSecondResult, unavailableCostReason, costResult, requestLogDto, stripRegistryOnlyStaticHeaders, fetchAllModels } from "./shared";
64
+ import type { MetricUnavailableReason, TokPerSecondResult, CostEstimateReason, CostResult, MetricSource } from "./shared";
65
+ import type { ManagementContext } from "./context";
66
+ import { readManagementJsonBody, rethrowManagementBodyTooLarge } from "./body";
67
+
68
+
69
+ /** Management wire shape: omit default imageInput "auto" (persist/response sparse). */
70
+ function sparseComboConfig<T extends { imageInput?: "auto" | "disabled" }>(combo: T): Omit<T, "imageInput"> & { imageInput?: "disabled" } {
71
+ const { imageInput, ...rest } = combo;
72
+ return {
73
+ ...rest,
74
+ ...(imageInput === "disabled" ? { imageInput: "disabled" as const } : {}),
75
+ };
76
+ }
77
+
78
+ export async function handleComboRoutes(ctx: ManagementContext): Promise<Response | null> {
79
+ const { req, url, config, deps, convergeCodexCatalog, syncClaudeAgentDefsBestEffort } = ctx;
80
+
81
+ if (url.pathname === "/api/combos" && req.method === "GET") {
82
+ const { comboPublicModelId, getCombo, listComboIds } = await import("../../combos");
83
+ return jsonResponse({ combos: listComboIds(config).map(id => {
84
+ const combo = getCombo(config, id)!;
85
+ return {
86
+ id,
87
+ model: comboPublicModelId(id, combo),
88
+ ...sparseComboConfig(combo),
89
+ };
90
+ }) });
91
+ }
92
+
93
+ if (url.pathname === "/api/combos" && req.method === "PUT") {
94
+ let rawBody: unknown;
95
+ try { rawBody = await readManagementJsonBody(req); } catch (error) { rethrowManagementBodyTooLarge(error); return jsonResponse({ error: "invalid JSON body" }, 400); }
96
+ if (!isPlainRecord(rawBody)) {
97
+ return jsonResponse({ error: "request body must be an object" }, 400);
98
+ }
99
+ const body = rawBody;
100
+ if (typeof body.id !== "string" || !body.id.trim()) {
101
+ return jsonResponse({ error: "id is required and must be a string" }, 400);
102
+ }
103
+ const id = body.id.trim();
104
+ let renameFrom: string | undefined;
105
+ if (body.renameFrom !== undefined) {
106
+ if (typeof body.renameFrom !== "string" || !body.renameFrom.trim()) {
107
+ return jsonResponse({ error: "renameFrom must be a non-empty string" }, 400);
108
+ }
109
+ renameFrom = body.renameFrom.trim();
110
+ if (renameFrom === id) {
111
+ return jsonResponse({ error: "renameFrom must differ from id" }, 400);
112
+ }
113
+ if (!Object.hasOwn(config.combos ?? {}, renameFrom)) {
114
+ return jsonResponse({ error: `combo "${renameFrom}" does not exist` }, 400);
115
+ }
116
+ if (Object.hasOwn(config.combos ?? {}, id)) {
117
+ return jsonResponse({ error: `combo "${id}" already exists` }, 400);
118
+ }
119
+ }
120
+ const {
121
+ clearComboSelectionState,
122
+ clearComboTargetCooldowns,
123
+ comboConfigError,
124
+ comboDisabledModelId,
125
+ comboDisabledModelSelectors,
126
+ comboModelId,
127
+ comboPublicModelId,
128
+ normalizeComboConfig,
129
+ } = await import("../../combos");
130
+ const error = comboConfigError(id, body.combo, config.providers, {
131
+ requireEnabledTarget: true,
132
+ combos: config.combos,
133
+ excludeComboId: renameFrom ?? id,
134
+ });
135
+ if (error) return jsonResponse({ error }, 400);
136
+ const normalized = normalizeComboConfig(body.combo as import("../../types").OcxComboConfig);
137
+ // Persist only non-default identity/capability fields so config stays sparse.
138
+ const {
139
+ alias: normalizedAlias,
140
+ nativeAlias: normalizedNativeAlias,
141
+ displayName: normalizedDisplayName,
142
+ imageInput: normalizedImageInput,
143
+ ...normalizedBase
144
+ } = normalized;
145
+ const stored: import("../../types").OcxComboConfig = {
146
+ ...normalizedBase,
147
+ ...(normalizedAlias ? { alias: normalizedAlias } : {}),
148
+ ...(normalizedNativeAlias ? { nativeAlias: true } : {}),
149
+ ...(normalizedDisplayName ? { displayName: normalizedDisplayName } : {}),
150
+ ...(normalizedImageInput === "disabled" ? { imageInput: "disabled" as const } : {}),
151
+ };
152
+ const sourceId = renameFrom ?? id;
153
+ const previous = config.combos?.[sourceId];
154
+ const oldPublicModel = previous ? comboPublicModelId(sourceId, previous) : null;
155
+ const newPublicModel = comboPublicModelId(id, normalized);
156
+ const disabledIdentityChanged = previous !== undefined && (
157
+ renameFrom !== undefined
158
+ || oldPublicModel !== newPublicModel
159
+ || (previous.nativeAlias === true) !== normalized.nativeAlias
160
+ );
161
+ const oldDisabledSelectors = disabledIdentityChanged
162
+ ? new Set(comboDisabledModelSelectors(sourceId, previous))
163
+ : new Set<string>();
164
+ const newDisabledModel = comboDisabledModelId(id, normalized);
165
+ if (codexAccountNamespaceForModel(config.codexAccountNamespaces, newPublicModel)) {
166
+ return jsonResponse({ error: CODEX_ACCOUNT_NAMESPACE_COMBO_ALIAS_COLLISION_ERROR }, 409);
167
+ }
168
+ const nextCombos = { ...(config.combos ?? {}) };
169
+ if (renameFrom) delete nextCombos[renameFrom];
170
+ nextCombos[id] = stored;
171
+ config.combos = nextCombos;
172
+ let shouldSyncClaudeAgentDefs = false;
173
+ const migratedModels = new Map<string, string>();
174
+ if (oldPublicModel && oldPublicModel !== newPublicModel && previous?.nativeAlias !== true) {
175
+ migratedModels.set(oldPublicModel, newPublicModel);
176
+ }
177
+ if (renameFrom) {
178
+ // A bare native id is ambiguous after the alias changes. Preserve it as a native route,
179
+ // while the unambiguous canonical combo reference follows the renamed combo.
180
+ migratedModels.set(
181
+ comboModelId(renameFrom),
182
+ previous?.nativeAlias === true ? comboModelId(id) : newPublicModel,
183
+ );
184
+ }
185
+ if (migratedModels.size > 0) {
186
+ const migrateReference = (model: string): string => migratedModels.get(model) ?? model;
187
+ const migrateAgentReference = (model: string): string => {
188
+ const migrated = migrateReference(model);
189
+ if (migrated !== model) shouldSyncClaudeAgentDefs = true;
190
+ return migrated;
191
+ };
192
+ if (config.subagentModels) {
193
+ config.subagentModels = [...new Set(config.subagentModels.map(migrateAgentReference))];
194
+ }
195
+ if (config.subagentRoles) {
196
+ for (const role of config.subagentRoles) {
197
+ role.model = migrateAgentReference(role.model);
198
+ }
199
+ }
200
+ if (config.injectionModel && migratedModels.has(config.injectionModel)) {
201
+ config.injectionModel = migrateReference(config.injectionModel);
202
+ }
203
+ if (config.shadowCallIntercept?.model && migratedModels.has(config.shadowCallIntercept.model)) {
204
+ config.shadowCallIntercept = {
205
+ ...config.shadowCallIntercept,
206
+ model: migrateReference(config.shadowCallIntercept.model),
207
+ };
208
+ }
209
+ if (config.claudeCode) {
210
+ const claudeCode = { ...config.claudeCode };
211
+ for (const field of ["model", "smallFastModel"] as const) {
212
+ if (claudeCode[field]) claudeCode[field] = migrateAgentReference(claudeCode[field]);
213
+ }
214
+ if (claudeCode.tierModels) {
215
+ claudeCode.tierModels = Object.fromEntries(
216
+ Object.entries(claudeCode.tierModels).map(([tier, model]) => [tier, migrateAgentReference(model)]),
217
+ );
218
+ }
219
+ if (claudeCode.modelMap) {
220
+ claudeCode.modelMap = Object.fromEntries(
221
+ Object.entries(claudeCode.modelMap).map(([source, model]) => [source, migrateAgentReference(model)]),
222
+ );
223
+ }
224
+ config.claudeCode = claudeCode;
225
+ }
226
+ }
227
+ if (oldDisabledSelectors.size > 0 && config.disabledModels) {
228
+ config.disabledModels = [...new Set(config.disabledModels.map(model => (
229
+ oldDisabledSelectors.has(model) ? newDisabledModel : model
230
+ )))];
231
+ }
232
+ saveConfigPreservingClaudeCode(config);
233
+ reconcileLiveStateStores();
234
+ clearComboSelectionState(id);
235
+ clearComboTargetCooldowns(id);
236
+ if (renameFrom) {
237
+ clearComboSelectionState(renameFrom);
238
+ clearComboTargetCooldowns(renameFrom);
239
+ }
240
+ const catalogRefresh = await convergeCodexCatalog();
241
+ if (shouldSyncClaudeAgentDefs) await syncClaudeAgentDefsBestEffort();
242
+ // Wire shape matches persistence: omit default imageInput "auto".
243
+ return jsonResponse({ success: true, id, model: newPublicModel, combo: sparseComboConfig(stored), catalogRefresh });
244
+ }
245
+
246
+ if (url.pathname === "/api/combos" && req.method === "DELETE") {
247
+ const id = url.searchParams.get("id")?.trim();
248
+ if (!id) return jsonResponse({ error: "id query param is required" }, 400);
249
+ if (!Object.hasOwn(config.combos ?? {}, id)) {
250
+ return jsonResponse({ error: "unknown combo" }, 404);
251
+ }
252
+ const { clearComboSelectionState, clearComboTargetCooldowns } = await import("../../combos");
253
+ delete config.combos![id];
254
+ if (Object.keys(config.combos!).length === 0) delete config.combos;
255
+ saveConfigPreservingClaudeCode(config);
256
+ reconcileLiveStateStores();
257
+ clearComboSelectionState(id);
258
+ clearComboTargetCooldowns(id);
259
+ const catalogRefresh = await convergeCodexCatalog();
260
+ return jsonResponse({ success: true, id, catalogRefresh });
261
+ }
262
+ return null;
263
+ }