@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,665 @@
1
+ import { createHmac, randomBytes } from "node:crypto";
2
+ import {
3
+ CodexCredentialGenerationConflictError,
4
+ CodexCredentialRefreshLockTimeoutError,
5
+ CodexCredentialRefreshBusyError,
6
+ CodexCredentialRefreshStaleError,
7
+ getValidCodexToken,
8
+ isCodexAccountGenerationLive,
9
+ } from "./account-store";
10
+ import { isAccountNeedsReauth, markAccountNeedsReauth } from "./account-runtime-state";
11
+ import { isCodexAccountPaused } from "./account-pause";
12
+ import { ConfigMutationLockError } from "../config";
13
+ import { isCodexAccountUsable } from "./account-usability";
14
+ import { reconcileMainCodexAccountRuntimeState } from "./account-lifecycle";
15
+ import { MAIN_CODEX_ACCOUNT_ID, getMainAccountToken, isMainAccountTokenLive } from "./main-account";
16
+ import { isNativeMainTrafficBlocked, nativeMainStartupGateSnapshot } from "./native-profile-startup";
17
+ import type { NativeMainStartupBlockReason } from "./native-profile-startup";
18
+ import {
19
+ codexQuotaScopeForModel,
20
+ getCodexQuotaHealthSnapshot,
21
+ releaseCodexQuotaProbeLease,
22
+ releaseCodexQuotaScopeProbeLease,
23
+ tryAcquireCodexQuotaProbeLease,
24
+ tryAcquireCodexQuotaScopeProbeLease,
25
+ pickAlternateCodexAccount,
26
+ resolveCodexAccountForThreadDetailed,
27
+ } from "./routing";
28
+ import {
29
+ entitledCodexAccountIdsForModel,
30
+ isDirectCallerEntitledToCodexModel,
31
+ resolveCodexModelEntitlements,
32
+ type CodexModelEntitlementSnapshot,
33
+ } from "./model-entitlements";
34
+ import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "./catalog/native-models";
35
+ import type { CodexCooldownSource, CodexQuotaScope } from "./routing";
36
+ import { maskAccountId } from "../lib/privacy";
37
+ import { formatErrorResponse } from "../bridge";
38
+ import { getAccountQuota } from "./quota";
39
+ import type { CodexAccountMode, OcxConfig, OcxProviderConfig } from "../types";
40
+ import { FORWARD_HEADERS } from "../adapters/openai-responses";
41
+ import { captureConfigGeneration } from "../lib/state-store-sweeper";
42
+ import { retainedUtf8Bytes } from "../lib/admission";
43
+
44
+ const CODEX_AFFINITY_COMPONENT_MAX_BYTES = 512;
45
+ const CODEX_APP_AFFINITY_KEY = randomBytes(32);
46
+
47
+ function boundedCodexAffinityComponent(value: string | null): string | undefined {
48
+ const normalized = value?.trim();
49
+ if (!normalized) return undefined;
50
+ if (retainedUtf8Bytes(normalized) > CODEX_AFFINITY_COMPONENT_MAX_BYTES) return undefined;
51
+ return normalized;
52
+ }
53
+
54
+ /**
55
+ * Preserve Codex's parent-thread affinity when present. Desktop App requests can omit that
56
+ * header while retaining a stable session/thread pair, so derive an opaque process-local key
57
+ * only from the complete bounded pair. Raw identifiers and durable hashes never enter Pool state.
58
+ */
59
+ export function codexPoolAffinityKey(headers: Headers): string | undefined {
60
+ const parentThreadId = boundedCodexAffinityComponent(headers.get("x-codex-parent-thread-id"));
61
+ if (parentThreadId) return parentThreadId;
62
+
63
+ const sessionId = boundedCodexAffinityComponent(headers.get("session-id"));
64
+ const threadId = boundedCodexAffinityComponent(headers.get("thread-id"));
65
+ if (!sessionId || !threadId) return undefined;
66
+
67
+ return `app:${createHmac("sha256", CODEX_APP_AFFINITY_KEY)
68
+ .update("opencodex-app-pool-affinity-v1\0")
69
+ .update(sessionId)
70
+ .update("\0")
71
+ .update(threadId)
72
+ .digest("base64url")}`;
73
+ }
74
+
75
+ export type CodexAuthContext =
76
+ | { kind: "main"; accountId: null }
77
+ | {
78
+ kind: "pool";
79
+ accountId: string;
80
+ writerGeneration: number;
81
+ generation: number;
82
+ accessToken: string;
83
+ chatgptAccountId: string;
84
+ /** Bypass Pool selection and suppress quota/transient failover for an exact selector. */
85
+ fixedAccount?: boolean;
86
+ /** Pool binding key; the Desktop fallback is an opaque process-local HMAC. */
87
+ affinityKey?: string;
88
+ /**
89
+ * Set when this request was admitted through an active quota cooldown as
90
+ * the account's single probe. Must be echoed into the upstream outcome so
91
+ * only this request can clear the cooldown (#433).
92
+ */
93
+ probeLeaseId?: string;
94
+ /** Native model quota group selected for this request, when known. */
95
+ quotaScope?: CodexQuotaScope;
96
+ /** Scope that owns `probeLeaseId`, when it is a scoped recovery probe. */
97
+ probeQuotaScope?: CodexQuotaScope;
98
+ }
99
+ | {
100
+ // Main Codex account participating in rotation: token injected from ~/.codex/auth.json
101
+ // (Option A). Distinct from "main" (passthrough fallback that forwards the client token).
102
+ kind: "main-pool";
103
+ accountId: string;
104
+ writerGeneration: number;
105
+ accessToken: string;
106
+ chatgptAccountId: string;
107
+ /** Bypass Pool selection and suppress quota/transient failover for an exact selector. */
108
+ fixedAccount?: boolean;
109
+ /** See `pool.affinityKey`. */
110
+ affinityKey?: string;
111
+ /** See `pool.probeLeaseId`. */
112
+ probeLeaseId?: string;
113
+ quotaScope?: CodexQuotaScope;
114
+ probeQuotaScope?: CodexQuotaScope;
115
+ };
116
+
117
+ /** Probe lease carried by this context, when it holds one. */
118
+ export function codexProbeLeaseId(ctx: CodexAuthContext | undefined): string | undefined {
119
+ return ctx?.kind === "pool" || ctx?.kind === "main-pool" ? ctx.probeLeaseId : undefined;
120
+ }
121
+
122
+ /** Scope of a lease carried by this context, when it probes a model-specific quota. */
123
+ export function codexProbeQuotaScope(ctx: CodexAuthContext | undefined): CodexQuotaScope | undefined {
124
+ return ctx?.kind === "pool" || ctx?.kind === "main-pool" ? ctx.probeQuotaScope : undefined;
125
+ }
126
+
127
+ /**
128
+ * Hand back a probe lease for a request that will not reach upstream. Safe to
129
+ * call with a context that holds no lease.
130
+ */
131
+ export function releaseCodexAuthContextProbeLease(ctx: CodexAuthContext | undefined): void {
132
+ const leaseId = codexProbeLeaseId(ctx);
133
+ if (!ctx || ctx.kind === "main" || !leaseId) return;
134
+ if (ctx.probeQuotaScope) releaseCodexQuotaScopeProbeLease(ctx.accountId!, ctx.probeQuotaScope, leaseId);
135
+ else releaseCodexQuotaProbeLease(ctx.accountId!, leaseId);
136
+ }
137
+
138
+ export type OcxRuntimeProviderConfig = OcxProviderConfig & {
139
+ _codexAccountOverride?: { accessToken: string; chatgptAccountId: string };
140
+ _codexAccountRequired?: boolean;
141
+ };
142
+
143
+ export class CodexAuthContextError extends Error {
144
+ accountId: string;
145
+
146
+ constructor(accountId: string, cause: unknown) {
147
+ super("Codex pool account auth failed", { cause });
148
+ this.name = "CodexAuthContextError";
149
+ this.accountId = accountId;
150
+ }
151
+ }
152
+
153
+ export class CodexPoolAuthenticationError extends Error {
154
+ constructor(message = "OpenAI account pool has no usable account credential") {
155
+ super(message);
156
+ this.name = "CodexPoolAuthenticationError";
157
+ }
158
+ }
159
+
160
+ export const CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE =
161
+ "OpenCodex local native-main profile maintenance is active; retry this request";
162
+
163
+ export class CodexMainProfileDrainingError extends Error {
164
+ /**
165
+ * Which startup-gate state fenced this request, when one did. Undefined means the
166
+ * fence came from somewhere other than the startup gate — the turn-drain claim race
167
+ * throws this same error while the gate reads `ready`, and inventing a reason there
168
+ * would point the next report at a gate that never closed.
169
+ *
170
+ * Captured here rather than at the throw sites because this is the last moment it is
171
+ * both in scope and still true: every catch site has already lost it, and re-reading
172
+ * the gate later can observe a recovery that completed in between (#2108).
173
+ */
174
+ readonly reason?: NativeMainStartupBlockReason;
175
+
176
+ constructor() {
177
+ super(CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE);
178
+ this.name = "CodexMainProfileDrainingError";
179
+ const gate = nativeMainStartupGateSnapshot();
180
+ if (gate.status !== "blocked") return;
181
+ this.reason = gate.reason;
182
+ reportNativeMainFenceReason(gate.reason);
183
+ }
184
+ }
185
+
186
+ /**
187
+ * #2108: a reboot could leave this fence closed until `ocx restart`, and the report was
188
+ * unactionable because the settled reason was never written anywhere. It cannot ride the
189
+ * message (claude-messages.ts matches that string exactly to keep the fence a 503 rather
190
+ * than an Anthropic 529) and it cannot ride a header (/api/logs reads only error.message
191
+ * from the body, and the Claude surface rebuilds its response headers from scratch), so
192
+ * stdout is the one surface that covers every path this fence fires on.
193
+ *
194
+ * Deduped per distinct reason: the original report shows three 503s in eleven seconds and
195
+ * a real client retries harder than that, so a per-request line would bury the signal.
196
+ * Only the reason is emitted; the snapshot's homeId is derived from a profile directory.
197
+ */
198
+ const reportedFenceReasons = new Set<NativeMainStartupBlockReason>();
199
+
200
+ function reportNativeMainFenceReason(reason: NativeMainStartupBlockReason): void {
201
+ if (reportedFenceReasons.has(reason)) return;
202
+ reportedFenceReasons.add(reason);
203
+ console.warn(
204
+ `native-main admission is fenced (reason: ${reason}); native model requests return 503 until it clears`,
205
+ );
206
+ }
207
+
208
+ /**
209
+ * Test-only reset for the dedup set above.
210
+ *
211
+ * The dedup is process-lifetime module state, so it is order-sensitive across test files
212
+ * sharing one Bun process: whichever file constructs this error first consumes the one-shot
213
+ * warn, and a later file asserting on it would see nothing and pass vacuously. Any test that
214
+ * asserts on the warn must call this first — an `afterEach` in the asserting file is not
215
+ * enough on its own, because the consuming file may not be the asserting one.
216
+ */
217
+ export function __resetNativeMainFenceReasonLog(): void {
218
+ reportedFenceReasons.clear();
219
+ }
220
+
221
+ export function codexMainProfileDrainingResponse(): Response {
222
+ const response = formatErrorResponse(503, "server_busy", CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE);
223
+ const headers = new Headers(response.headers);
224
+ headers.set("Retry-After", "1");
225
+ return new Response(response.body, { status: response.status, headers });
226
+ }
227
+
228
+ export class CodexDirectAuthenticationError extends Error {
229
+ constructor() {
230
+ super("Codex Direct requires a caller Authorization bearer token");
231
+ this.name = "CodexDirectAuthenticationError";
232
+ }
233
+ }
234
+
235
+ export function hasCallerCodexBearer(headers: Headers): boolean {
236
+ return /^Bearer\s+\S+/i.test(headers.get("authorization")?.trim() ?? "");
237
+ }
238
+
239
+ export class CodexAccountCooldownError extends Error {
240
+ accountId: string;
241
+ cooldownUntil: number;
242
+ cooldownSource?: CodexCooldownSource;
243
+ quotaScope?: CodexQuotaScope;
244
+
245
+ constructor(
246
+ accountId: string,
247
+ cooldownUntil: number,
248
+ cooldownSource?: CodexCooldownSource,
249
+ quotaScope?: CodexQuotaScope,
250
+ ) {
251
+ super("Selected Codex account is cooling down");
252
+ this.name = "CodexAccountCooldownError";
253
+ this.accountId = accountId;
254
+ this.cooldownUntil = cooldownUntil;
255
+ this.cooldownSource = cooldownSource;
256
+ this.quotaScope = quotaScope;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Human-readable account label for a client-visible error. NEVER the raw id: the proxy
262
+ * supports non-loopback binds (auth-cors.ts `isApiAuthRequired` requires a token there
263
+ * rather than refusing), so data-plane bodies can reach remote authenticated clients.
264
+ * The main login has no secret id, so it renders as the literal alias users type.
265
+ */
266
+ export function cooldownAccountLabel(accountId: string): string {
267
+ return accountId === MAIN_CODEX_ACCOUNT_ID ? "main" : maskAccountId(accountId) ?? "account-…????";
268
+ }
269
+
270
+ /**
271
+ * Actionable message for a cooled-down account: until when, why, and how to escape.
272
+ * Shared by every transport so the WebSocket surface (Codex Desktop) says the same thing
273
+ * as HTTP. The bare "cooling down" string left users with no route but commenting out the
274
+ * injected `openai_base_url` in config.toml.
275
+ */
276
+ export function cooldownErrorMessage(err: CodexAccountCooldownError, accountSelector?: string): string {
277
+ const until = new Date(err.cooldownUntil).toISOString();
278
+ const scope = err.quotaScope === "spark"
279
+ ? "Spark quota"
280
+ : err.quotaScope === "shared"
281
+ ? "shared native quota"
282
+ : null;
283
+ const selected = accountSelector
284
+ ? `Selected Codex account selector (${accountSelector})`
285
+ : `Selected Codex account (${cooldownAccountLabel(err.accountId)})`;
286
+ const recovery = accountSelector
287
+ ? " This request is pinned to that selector and will not switch accounts; choose another account-qualified model or retry later."
288
+ : " Run 'ocx account list openai' to find the id, then"
289
+ + " 'ocx account clear-cooldown openai <id>' to lift it, or switch accounts with 'ocx account use openai <id>'.";
290
+ return `${selected}${scope ? ` ${scope} is` : " is"} cooling down until ${until}`
291
+ + ` (source: ${err.cooldownSource ?? "default"}).${recovery}`;
292
+ }
293
+
294
+ /** HTTP form of {@link cooldownErrorMessage}, carrying Retry-After for well-behaved clients. */
295
+ export function cooldownErrorResponse(
296
+ err: CodexAccountCooldownError,
297
+ now = Date.now(),
298
+ accountSelector?: string,
299
+ ): Response {
300
+ const res = formatErrorResponse(429, "rate_limit_error", cooldownErrorMessage(err, accountSelector));
301
+ const headers = new Headers(res.headers);
302
+ headers.set("Retry-After", String(Math.max(1, Math.ceil((err.cooldownUntil - now) / 1000))));
303
+ return new Response(res.body, { status: res.status, headers });
304
+ }
305
+
306
+ export class CodexThreadAffinityExpiredError extends Error {
307
+ accountId: string;
308
+
309
+ constructor(accountId: string) {
310
+ super("Codex thread account affinity expired");
311
+ this.name = "CodexThreadAffinityExpiredError";
312
+ this.accountId = accountId;
313
+ }
314
+ }
315
+
316
+ export function shouldMarkAccountNeedsReauthForCodexAuthFailure(cause: unknown): boolean {
317
+ return !(cause instanceof CodexCredentialGenerationConflictError)
318
+ && !(cause instanceof CodexCredentialRefreshLockTimeoutError)
319
+ && !(cause instanceof CodexCredentialRefreshBusyError)
320
+ && !(cause instanceof CodexCredentialRefreshStaleError)
321
+ && !(cause instanceof ConfigMutationLockError);
322
+ }
323
+
324
+ export interface ResolveCodexAuthContextOptions {
325
+ excludeAccountId?: string;
326
+ /** Resolve exactly this account without consulting or mutating Pool selection. */
327
+ accountId?: string;
328
+ /** Final native model selected for this request, used to select its quota group. */
329
+ modelId?: string;
330
+ /** Short reservation converted to turn ownership before native `__main__` token materialization. */
331
+ beginCodexAccountSelection?: () => CodexAccountSelectionAdmission | undefined;
332
+ /** Test-only native credential read seams. */
333
+ isMainAccountTokenLive?: () => boolean;
334
+ getMainAccountToken?: typeof getMainAccountToken;
335
+ primeCodexPoolQuotas?: (config: OcxConfig, reason: string) => Promise<void>;
336
+ /** Test seam for account-gated native model discovery. */
337
+ resolveCodexModelEntitlements?: (
338
+ config: Pick<OcxConfig, "codexAccounts">,
339
+ ) => Promise<CodexModelEntitlementSnapshot>;
340
+ /** Direct requests admitted with a proxy bearer substitute the stored native-main credential. */
341
+ substituteMainCredentialForDirect?: boolean;
342
+ /** Test seam for a Direct request's own forwarded ChatGPT credential. */
343
+ isDirectCallerEntitledToCodexModel?: (headers: Headers, modelId: string) => Promise<boolean>;
344
+ }
345
+
346
+ export interface CodexAccountSelectionAdmission {
347
+ readonly mainProfileDraining: boolean;
348
+ claimMainProfile(): boolean;
349
+ release(): void;
350
+ }
351
+
352
+ export async function resolveCodexAuthContext(
353
+ headers: Headers,
354
+ config: OcxConfig,
355
+ mode: CodexAccountMode,
356
+ options: ResolveCodexAuthContextOptions = {},
357
+ ): Promise<CodexAuthContext> {
358
+ const writerGeneration = captureConfigGeneration();
359
+ const fixedAccountId = options.accountId;
360
+ if (fixedAccountId !== undefined && options.excludeAccountId !== undefined) {
361
+ throw new Error("Codex auth context cannot select and exclude an account simultaneously");
362
+ }
363
+ // An explicit namespace binding is stronger than the provider's default mode. It must use the
364
+ // selected stored credential even while the canonical OpenAI provider is globally Direct.
365
+ if (mode === "direct" && fixedAccountId === undefined) {
366
+ if (!hasCallerCodexBearer(headers)) throw new CodexDirectAuthenticationError();
367
+ if (options.modelId && ACCOUNT_GATED_NATIVE_OPENAI_MODELS.has(options.modelId)) {
368
+ const entitled = options.substituteMainCredentialForDirect
369
+ ? entitledCodexAccountIdsForModel(
370
+ await (options.resolveCodexModelEntitlements ?? resolveCodexModelEntitlements)(config),
371
+ options.modelId,
372
+ )?.has(MAIN_CODEX_ACCOUNT_ID) === true
373
+ : await (options.isDirectCallerEntitledToCodexModel ?? isDirectCallerEntitledToCodexModel)(
374
+ headers,
375
+ options.modelId,
376
+ );
377
+ if (!entitled) {
378
+ throw new CodexPoolAuthenticationError("The selected ChatGPT account does not support this model");
379
+ }
380
+ }
381
+ return { kind: "main", accountId: null };
382
+ }
383
+ const affinityKey = fixedAccountId === undefined ? codexPoolAffinityKey(headers) : undefined;
384
+ const entitlementSnapshot = options.modelId && ACCOUNT_GATED_NATIVE_OPENAI_MODELS.has(options.modelId)
385
+ ? await (options.resolveCodexModelEntitlements ?? resolveCodexModelEntitlements)(config)
386
+ : undefined;
387
+ const modelEligibleAccountIds = entitlementSnapshot
388
+ ? entitledCodexAccountIdsForModel(entitlementSnapshot, options.modelId)
389
+ : undefined;
390
+ // Retained startup recovery makes the physical main identity ineligible. Routing
391
+ // can still preserve service by selecting a healthy configured pool account.
392
+ const nativeMainTrafficBlocked = isNativeMainTrafficBlocked();
393
+ const selectionAdmission = options.beginCodexAccountSelection?.();
394
+ const nativeMainReadsForbidden = nativeMainTrafficBlocked || selectionAdmission?.mainProfileDraining === true;
395
+ const selectionOptions = {
396
+ // Temporary switch drain keeps the candidate until the atomic claim rejects
397
+ // it. Retained recovery makes main wholly ineligible so pool routing continues.
398
+ nativeMainSelectionOnly: !nativeMainTrafficBlocked
399
+ && selectionAdmission?.mainProfileDraining === true,
400
+ isMainAccountTokenLive: options.isMainAccountTokenLive,
401
+ modelEligibleAccountIds,
402
+ };
403
+ let accountId: string;
404
+ const quotaScope = codexQuotaScopeForModel(options.modelId);
405
+ try {
406
+ // A pre-drain selector reserves the native identity while reconciliation and
407
+ // routing inspect it. Selectors arriving after the fence skip reconciliation
408
+ // and may still route to non-main pool accounts without touching switch state.
409
+ if (!nativeMainReadsForbidden) reconcileMainCodexAccountRuntimeState();
410
+ const resolution = fixedAccountId !== undefined
411
+ ? { status: "selected" as const, accountId: fixedAccountId }
412
+ : options.excludeAccountId
413
+ ? (() => {
414
+ const selected = pickAlternateCodexAccount(
415
+ config,
416
+ options.excludeAccountId!,
417
+ Date.now(),
418
+ quotaScope,
419
+ selectionOptions,
420
+ );
421
+ return selected
422
+ ? { status: "selected" as const, accountId: selected }
423
+ : { status: "none" as const };
424
+ })()
425
+ : resolveCodexAccountForThreadDetailed(affinityKey ?? null, config, Date.now(), quotaScope, selectionOptions);
426
+ if (resolution.status === "expired") throw new CodexThreadAffinityExpiredError(resolution.accountId);
427
+ const selected = resolution.status === "selected" ? resolution.accountId : null;
428
+ if (!selected) {
429
+ if (fixedAccountId !== undefined) {
430
+ throw new CodexPoolAuthenticationError(
431
+ modelEligibleAccountIds && !modelEligibleAccountIds.has(fixedAccountId)
432
+ ? "Selected Codex account does not support this model"
433
+ : "Selected Codex account is unavailable",
434
+ );
435
+ }
436
+ // Recovery deliberately makes physical main ineligible. If no healthy
437
+ // pool route is configured and main is the intended route, report the
438
+ // temporary fence rather than misclassifying that credential as invalid.
439
+ // A configured pool retry/exclusion that finds no alternate preserves its
440
+ // ordinary pool-auth failure instead of being mislabeled as a main fence.
441
+ if (nativeMainTrafficBlocked && !options.excludeAccountId) {
442
+ throw new CodexMainProfileDrainingError();
443
+ }
444
+ throw new CodexPoolAuthenticationError(
445
+ modelEligibleAccountIds ? "No eligible Codex account supports this model" : undefined,
446
+ );
447
+ }
448
+ accountId = selected;
449
+ if (accountId === MAIN_CODEX_ACCOUNT_ID && nativeMainTrafficBlocked) {
450
+ throw new CodexMainProfileDrainingError();
451
+ }
452
+ if (
453
+ accountId === MAIN_CODEX_ACCOUNT_ID
454
+ && selectionAdmission
455
+ && !selectionAdmission.claimMainProfile()
456
+ ) {
457
+ throw new CodexMainProfileDrainingError();
458
+ }
459
+ // Some legacy Pool fallbacks preserve a configured active account even when it is not
460
+ // currently selectable, so token/cooldown code can produce the historical actionable error.
461
+ // Model entitlement is different: sending the request would spend a turn on an account whose
462
+ // authenticated roster already denied the model. Reassert this boundary after every selector.
463
+ if (modelEligibleAccountIds && !modelEligibleAccountIds.has(accountId)) {
464
+ throw new CodexPoolAuthenticationError(
465
+ fixedAccountId !== undefined
466
+ ? "Selected Codex account does not support this model"
467
+ : "No eligible Codex account supports this model",
468
+ );
469
+ }
470
+ if (fixedAccountId !== undefined) {
471
+ if (isCodexAccountPaused(config, accountId)) {
472
+ throw new CodexPoolAuthenticationError("Selected Codex account is unavailable");
473
+ }
474
+ if (isAccountNeedsReauth(accountId)) {
475
+ throw new CodexPoolAuthenticationError("Selected Codex account needs reauthentication");
476
+ }
477
+ if (!isCodexAccountUsable(config, accountId, selectionOptions)) {
478
+ throw new CodexPoolAuthenticationError("Selected Codex account is unavailable");
479
+ }
480
+ }
481
+ } finally {
482
+ selectionAdmission?.release();
483
+ }
484
+ // Lazy prime: if the selected account has no quota yet, the pool is likely
485
+ // unprimed (dashboard never opened, or startup prime was blocked). Kick a
486
+ // best-effort prime so the NEXT routing decision has real scores. This never
487
+ // blocks the current request, and the helper's single-flight guard collapses
488
+ // repeated triggers into one pass.
489
+ if (fixedAccountId === undefined && !nativeMainReadsForbidden && !getAccountQuota(accountId)) {
490
+ if (options.primeCodexPoolQuotas) {
491
+ void options.primeCodexPoolQuotas(config, "pre-route").catch(() => {});
492
+ } else {
493
+ import("./auth-api")
494
+ .then(({ primeCodexPoolQuotas }) => primeCodexPoolQuotas(config, "pre-route"))
495
+ .catch(() => {});
496
+ }
497
+ }
498
+ // Snapshot (not just the deadline) so a refused request can report WHY it is cooled:
499
+ // a literal Retry-After reads very differently to a user than a reset-derived guess.
500
+ const cooldown = getCodexQuotaHealthSnapshot(accountId, quotaScope);
501
+ const cooldownUntil = cooldown?.cooldownUntil;
502
+ // A cooled-down account never sends traffic, so upstream recovery can never be
503
+ // observed and the cooldown outlives the real limit. Admit one probe per
504
+ // interval; its outcome decides whether the cooldown ends (#433).
505
+ let probeLeaseId: string | undefined;
506
+ let probeQuotaScope: CodexQuotaScope | undefined;
507
+ if (cooldownUntil) {
508
+ // Exact bindings are not Pool recovery traffic. Fail closed instead of consuming the Pool's
509
+ // one probe lease or selecting another account.
510
+ if (fixedAccountId !== undefined) {
511
+ throw new CodexAccountCooldownError(accountId, cooldownUntil, cooldown?.cooldownSource, cooldown?.quotaScope);
512
+ }
513
+ probeQuotaScope = cooldown?.quotaScope;
514
+ probeLeaseId = probeQuotaScope
515
+ ? tryAcquireCodexQuotaScopeProbeLease(accountId, probeQuotaScope) ?? undefined
516
+ : tryAcquireCodexQuotaProbeLease(accountId) ?? undefined;
517
+ if (!probeLeaseId) {
518
+ throw new CodexAccountCooldownError(accountId, cooldownUntil, cooldown?.cooldownSource, cooldown?.quotaScope);
519
+ }
520
+ }
521
+
522
+ if (accountId === MAIN_CODEX_ACCOUNT_ID) {
523
+ // Main account in rotation: inject the read-only auth.json token and fail closed if it vanished.
524
+ const token = (options.getMainAccountToken ?? getMainAccountToken)();
525
+ if (!token) {
526
+ // Nothing will reach upstream, so give the probe back instead of burning it.
527
+ if (probeLeaseId && probeQuotaScope) releaseCodexQuotaScopeProbeLease(accountId, probeQuotaScope, probeLeaseId);
528
+ else if (probeLeaseId) releaseCodexQuotaProbeLease(accountId, probeLeaseId);
529
+ throw new CodexPoolAuthenticationError(
530
+ fixedAccountId !== undefined ? "Selected Codex account is unavailable" : undefined,
531
+ );
532
+ }
533
+ return {
534
+ kind: "main-pool",
535
+ accountId,
536
+ writerGeneration,
537
+ accessToken: token.accessToken,
538
+ chatgptAccountId: token.chatgptAccountId,
539
+ ...(fixedAccountId !== undefined ? { fixedAccount: true } : {}),
540
+ ...(affinityKey ? { affinityKey } : {}),
541
+ ...(quotaScope ? { quotaScope } : {}),
542
+ ...(probeLeaseId ? { probeLeaseId } : {}),
543
+ ...(probeQuotaScope ? { probeQuotaScope } : {}),
544
+ };
545
+ }
546
+
547
+ try {
548
+ const token = await getValidCodexToken(accountId);
549
+ return {
550
+ kind: "pool",
551
+ accountId,
552
+ writerGeneration,
553
+ generation: token.generation,
554
+ accessToken: token.accessToken,
555
+ chatgptAccountId: token.chatgptAccountId,
556
+ ...(fixedAccountId !== undefined ? { fixedAccount: true } : {}),
557
+ ...(affinityKey ? { affinityKey } : {}),
558
+ ...(quotaScope ? { quotaScope } : {}),
559
+ ...(probeLeaseId ? { probeLeaseId } : {}),
560
+ ...(probeQuotaScope ? { probeQuotaScope } : {}),
561
+ };
562
+ } catch (cause) {
563
+ if (probeLeaseId && probeQuotaScope) releaseCodexQuotaScopeProbeLease(accountId, probeQuotaScope, probeLeaseId);
564
+ else if (probeLeaseId) releaseCodexQuotaProbeLease(accountId, probeLeaseId);
565
+ if (shouldMarkAccountNeedsReauthForCodexAuthFailure(cause)) {
566
+ markAccountNeedsReauth(accountId, writerGeneration);
567
+ }
568
+ throw new CodexAuthContextError(accountId, cause);
569
+ }
570
+ }
571
+
572
+ export function assertCodexAuthContextNotCooled(ctx: CodexAuthContext | undefined): void {
573
+ if (ctx?.kind !== "pool" && ctx?.kind !== "main-pool") return;
574
+ // A context holding the probe lease was deliberately admitted through the cooldown.
575
+ if (ctx.probeLeaseId) return;
576
+ const cooldown = getCodexQuotaHealthSnapshot(ctx.accountId, ctx.quotaScope);
577
+ if (cooldown?.cooldownUntil) {
578
+ throw new CodexAccountCooldownError(ctx.accountId, cooldown.cooldownUntil, cooldown.cooldownSource, cooldown.quotaScope);
579
+ }
580
+ }
581
+
582
+ export function applyCodexAuthContextToProvider(
583
+ provider: OcxProviderConfig,
584
+ ctx: CodexAuthContext,
585
+ mode: CodexAccountMode | undefined,
586
+ ): OcxRuntimeProviderConfig {
587
+ if (mode !== "pool" || (ctx.kind !== "pool" && ctx.kind !== "main-pool") || provider.authMode !== "forward") return provider;
588
+ return {
589
+ ...provider,
590
+ _codexAccountOverride: {
591
+ accessToken: ctx.accessToken,
592
+ chatgptAccountId: ctx.chatgptAccountId,
593
+ },
594
+ _codexAccountRequired: true,
595
+ };
596
+ }
597
+
598
+ export class CodexMainSubstitutionUnavailableError extends Error {
599
+ constructor() {
600
+ super("No usable Codex main credential to substitute for an admission bearer");
601
+ this.name = "CodexMainSubstitutionUnavailableError";
602
+ }
603
+ }
604
+
605
+ /**
606
+ * Build the upstream auth headers for one Codex turn.
607
+ *
608
+ * The two credential domains meet here, and only here:
609
+ *
610
+ * - `pool` / `main-pool` always OVERWRITE with the stored account credential. Whatever the
611
+ * caller sent is irrelevant to what we send upstream.
612
+ * - `main` with an admission-bearer caller (#1686) must substitute the stored main credential.
613
+ * The caller proved admission with one of OUR secrets, which must never leave the process, so
614
+ * the only two acceptable outcomes are replaced-with-stored-main or fail-before-any-IO.
615
+ * Silently forwarding would be the leak validateForwardAdmissionCredential exists to prevent.
616
+ * - `main` with a dedicated-header caller keeps the existing intentional passthrough: the bearer
617
+ * there is the user's own ChatGPT credential, not ours.
618
+ */
619
+ export function materializeCodexUpstreamAuth(
620
+ headers: Headers,
621
+ ctx: CodexAuthContext,
622
+ options: { substituteMainCredential?: boolean } = {},
623
+ ): Headers {
624
+ const selected = new Headers();
625
+ for (const name of FORWARD_HEADERS) {
626
+ const value = headers.get(name);
627
+ if (value) selected.set(name, value);
628
+ }
629
+ if (ctx.kind === "pool" || ctx.kind === "main-pool") {
630
+ selected.set("authorization", `Bearer ${ctx.accessToken}`);
631
+ selected.set("chatgpt-account-id", ctx.chatgptAccountId);
632
+ return selected;
633
+ }
634
+ if (ctx.kind === "main" && options.substituteMainCredential === true) {
635
+ const stored = getMainAccountToken();
636
+ // Fail BEFORE any upstream I/O. Falling through here would send the admission secret.
637
+ if (!stored?.accessToken || !isMainAccountTokenLive()) {
638
+ throw new CodexMainSubstitutionUnavailableError();
639
+ }
640
+ selected.set("authorization", `Bearer ${stored.accessToken}`);
641
+ if (stored.chatgptAccountId) selected.set("chatgpt-account-id", stored.chatgptAccountId);
642
+ return selected;
643
+ }
644
+ return selected;
645
+ }
646
+
647
+ /** @deprecated Prefer materializeCodexUpstreamAuth; kept for call sites without admission context. */
648
+ export function headersForCodexAuthContext(headers: Headers, ctx: CodexAuthContext): Headers {
649
+ return materializeCodexUpstreamAuth(headers, ctx);
650
+ }
651
+
652
+ export function isCodexAuthContextUsable(ctx: CodexAuthContext, config: OcxConfig): boolean {
653
+ if (ctx.kind === "main") return true;
654
+ if (ctx.kind === "main-pool") return isCodexAccountUsable(config, ctx.accountId);
655
+ return isCodexAccountUsable(config, ctx.accountId) && isCodexAccountGenerationLive(ctx.accountId, ctx.generation);
656
+ }
657
+
658
+ export function stripCodexRuntimeProviderFields(provider: OcxProviderConfig): OcxProviderConfig {
659
+ const {
660
+ _codexAccountOverride: _override,
661
+ _codexAccountRequired: _required,
662
+ ...safeProvider
663
+ } = provider as OcxRuntimeProviderConfig;
664
+ return safeProvider;
665
+ }