@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,232 @@
1
+ import type { Server } from "bun";
2
+ import {
3
+ codexWsUpstreamFetch,
4
+ currentBunRuntimeIdentity,
5
+ shouldUseCodexWsUpstream,
6
+ type BunRuntimeGateInput,
7
+ } from "./ws-upstream";
8
+ import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse, type ResponsesTerminalStatus } from "../../bridge";
9
+ import {
10
+ getConfigPath,
11
+ multiAgentGuidanceEnabled,
12
+ resolveEnvValue,
13
+ } from "../../config";
14
+ import { parseRequest } from "../../responses/parser";
15
+ import { buildCompactV1Output, COMPACT_PROMPT, decodeCompactionSummary, extractCompactUserMessages } from "../../responses/compaction";
16
+ import { FORWARD_HEADERS, sanitizeReasoningInputContent } from "../../adapters/openai-responses";
17
+ import { expandPreviousResponseInput, previousResponseProviderState, rememberResponseState } from "../../responses/state";
18
+ import { routeModel } from "../../router";
19
+ import {
20
+ advanceComboAfterFailure,
21
+ comboDefaultEffort,
22
+ comboFailureDecision,
23
+ comboIdFromRawBody,
24
+ concreteComboRequestBody,
25
+ getCombo,
26
+ isComboTargetInCooldown,
27
+ NoAvailableComboTargetsError,
28
+ noteComboSuccess,
29
+ parseRetryAfterMs,
30
+ pickComboTarget,
31
+ targetKey,
32
+ } from "../../combos";
33
+ import { isInjectionDebugEnabled } from "../../lib/debug-settings";
34
+ import { injectionDebugLog } from "../../lib/injection-debug-log";
35
+ import { modelInList, namespacedToolName } from "../../types";
36
+ import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig, OcxProviderContinuationState, OcxUsage } from "../../types";
37
+ import {
38
+ forceRefreshOAuthAccessSnapshot,
39
+ getOAuthCredentialApiBaseUrl,
40
+ getOAuthCredentialProjectId,
41
+ getValidAccessTokenSnapshot,
42
+ type OAuthAccessSnapshot,
43
+ UnsupportedOAuthProviderError,
44
+ } from "../../oauth";
45
+ import { buildWebSearchTool, planWebSearch, runWithWebSearch, shouldResolveOpenAiWebSearchSidecar } from "../../web-search";
46
+ import { describeImagesInPlace, planVisionSidecar, shouldResolveOpenAiVisionSidecar, stripImagesInPlace } from "../../vision";
47
+ import { createAdapterEventQueue, preflightAdapterEvents } from "../../adapters/run-turn-queue";
48
+ import {
49
+ applyCodexAuthContextToProvider,
50
+ CodexAccountCooldownError,
51
+ CodexAuthContextError,
52
+ CodexDirectAuthenticationError,
53
+ CodexPoolAuthenticationError,
54
+ CodexThreadAffinityExpiredError,
55
+ headersForCodexAuthContext,
56
+ isCodexAuthContextUsable,
57
+ resolveCodexAuthContext,
58
+ type CodexAuthContext,
59
+ } from "../../codex/auth-context";
60
+ import {
61
+ formatCodexProviderForLog,
62
+ recordCodexUpstreamOutcome,
63
+ type CodexUpstreamOutcome,
64
+ } from "../../codex/routing";
65
+ import { fetchWithResetRetry, fetchWithTransientRetry, applyUpstreamRecoveryInit } from "../../lib/upstream-retry";
66
+ import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "../auth-cors";
67
+ import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar, type ResolvedOpenAiForwardSidecar } from "../../providers/openai-sidecar";
68
+ import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
69
+ import { slugsEquivalent } from "../../providers/slug-codec";
70
+ import { applyOpenAiVirtualModel, resolveOpenAiCompactModel } from "../../providers/openai-virtual-models";
71
+ import { isUsageDebugEnabled } from "../../usage/debug";
72
+ import { readJsonRequestBody, DecompressedBodyTooLargeError, UnsupportedContentEncodingError } from "../request-decompress";
73
+ import { resolveAdapter, resolveWireProtocolOverride } from "../adapter-resolve";
74
+ import { hasKeyPoolFailover, rotateProviderTransportOn429 } from "../../providers/key-failover";
75
+ import { shouldAttemptImageTierRetry } from "../image-retry";
76
+ import { resolveProviderTransport } from "../../providers/xai-transport";
77
+ import type { WsData } from "../ws-bridge";
78
+ import { registerTurn, trackStreamLifetime, unregisterTurn } from "../lifecycle";
79
+ import { redactSecretString } from "../../lib/redact";
80
+ import { readBoundedResponseBody } from "../../lib/bounded-body";
81
+ import { supportedLadderFor } from "../effort-policy";
82
+ import {
83
+ beginRequestAttempt,
84
+ catalogModelSupportsServiceTier,
85
+ finishRequestAttempt,
86
+ inspectResponseLogJson,
87
+ noteAttemptSend,
88
+ readConfiguredCodexServiceTier,
89
+ requestLogSpeedLabel,
90
+ sealRequestAttemptIdentity,
91
+ usageFromResponsesPayload,
92
+ type RequestLogContext,
93
+ } from "../request-log";
94
+ import type { AttemptRecoveryKind } from "../../usage/log";
95
+ import {
96
+ consumeForInspection,
97
+ consumeForResponseLogMetadata,
98
+ markNativePassthroughSseResponse,
99
+ relaySseWithFailedTail,
100
+ relayWithAbort,
101
+ sanitizePassthroughHeaders,
102
+ } from "../relay";
103
+ import { hasResponsesItemIdRepair, relaySseWithResponsesItemIdRepair } from "../responses-item-id-repair";
104
+ import type { EffectiveSubagentRoster, SpawnAgentSurface } from "../../codex/catalog";
105
+ import { waitForProviderRequestSlot } from "../../providers/request-pacing";
106
+ import { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
107
+
108
+ export { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
109
+
110
+ export function disableResponsesRequestTimeout(req: Request, server: Pick<Server<WsData>, "timeout"> | undefined): boolean {
111
+ if (!server) return false;
112
+ try {
113
+ server.timeout(req, 0);
114
+ return true;
115
+ } catch {
116
+ return false;
117
+ }
118
+ }
119
+
120
+
121
+
122
+ export function safeHostLabel(url: string): string {
123
+ try {
124
+ return new URL(url).host;
125
+ } catch {
126
+ return "upstream";
127
+ }
128
+ }
129
+
130
+ /** Canonical origin (scheme + host) for failure-attribution keys: http and
131
+ * https for the same host must not share one ledger entry (#914 review). */
132
+ export function safeOriginLabel(url: string): string {
133
+ try {
134
+ return new URL(url).origin.toLowerCase();
135
+ } catch {
136
+ return "upstream";
137
+ }
138
+ }
139
+
140
+
141
+
142
+ export interface PaceAwareFetch {
143
+ waitForPacing?: (signal?: AbortSignal) => Promise<void>;
144
+ unpacedFetch?: typeof globalThis.fetch;
145
+ }
146
+
147
+ export type ProviderFetch = typeof globalThis.fetch & PaceAwareFetch;
148
+
149
+ export interface ProviderFetchOptions {
150
+ providerName?: string;
151
+ modelId?: string;
152
+ /** One pacing slot was acquired immediately before this fetch wrapper was created. */
153
+ pacingSlotAcquired?: boolean;
154
+ }
155
+
156
+ export function providerFetch(
157
+ provider: OcxProviderConfig,
158
+ runtime: BunRuntimeGateInput = currentBunRuntimeIdentity(),
159
+ options: ProviderFetchOptions = {},
160
+ ): ProviderFetch {
161
+ const base = (provider as OcxProviderConfig & { fetch?: typeof globalThis.fetch }).fetch ?? globalThis.fetch;
162
+ // ChatGPT Codex backend: streaming turns ride the responses_websockets
163
+ // transport (measured ~3s faster TTFT than the SSE POST queue); everything
164
+ // else keeps the provider's HTTP fetch. See ws-upstream.ts for the details.
165
+ const unpaced = async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => {
166
+ if (typeof input === "string" && init && shouldUseCodexWsUpstream(input, init, runtime)) {
167
+ return codexWsUpstreamFetch(input, init, base, runtime);
168
+ }
169
+ return base(input, withUpstreamHttpVersion(input, init, provider));
170
+ };
171
+ let pacingSlotAcquired = options.pacingSlotAcquired === true;
172
+ const waitForPacing = (signal?: AbortSignal) => {
173
+ if (pacingSlotAcquired) {
174
+ pacingSlotAcquired = false;
175
+ return Promise.resolve();
176
+ }
177
+ return options.providerName
178
+ ? waitForProviderRequestSlot(options.providerName, provider, options.modelId, signal)
179
+ : Promise.resolve();
180
+ };
181
+ const wrapped = async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => {
182
+ await waitForPacing(init?.signal ?? undefined);
183
+ return unpaced(input, init);
184
+ };
185
+ const preconnect = (...args: Parameters<typeof globalThis.fetch.preconnect>): void => {
186
+ base.preconnect?.(...args);
187
+ };
188
+ return Object.assign(wrapped, {
189
+ preconnect,
190
+ waitForPacing,
191
+ unpacedFetch: Object.assign(unpaced, { preconnect }),
192
+ });
193
+ }
194
+
195
+
196
+
197
+ export async function fetchWithHeaderTimeout(
198
+ url: string,
199
+ init: Omit<RequestInit, "signal">,
200
+ abortSignal: AbortSignal,
201
+ timeoutMs: number,
202
+ preferIdentityEncoding = false,
203
+ executor: typeof globalThis.fetch = globalThis.fetch,
204
+ manualRedirect = false,
205
+ ): Promise<Response> {
206
+ const pacing = executor as ProviderFetch;
207
+ await pacing.waitForPacing?.(abortSignal);
208
+ const fetchExecutor = pacing.unpacedFetch ?? executor;
209
+ const timeout = new AbortController();
210
+ const timer = setTimeout(() => {
211
+ if (!timeout.signal.aborted) timeout.abort(new DOMException("Timeout elapsed", "TimeoutError"));
212
+ }, timeoutMs);
213
+ const headers = new Headers(init.headers);
214
+ // Compressed SSE can be held until the decompressor has a complete block. Streaming calls
215
+ // default to identity for low-latency frame delivery, while an explicit caller choice wins.
216
+ if (preferIdentityEncoding && !headers.has("accept-encoding")) {
217
+ headers.set("accept-encoding", "identity");
218
+ }
219
+ try {
220
+ return await fetchExecutor(url, {
221
+ ...init,
222
+ headers,
223
+ // Credential-bearing sends opt into manual redirects so a 3xx is relayed
224
+ // as a Response instead of being followed into a rejection that is
225
+ // indistinguishable from a pre-connection failure (#914).
226
+ ...(manualRedirect ? { redirect: "manual" as const } : {}),
227
+ signal: AbortSignal.any([abortSignal, timeout.signal]),
228
+ });
229
+ } finally {
230
+ clearTimeout(timer);
231
+ }
232
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Pre-dispatch input admission (#1412).
3
+ *
4
+ * Refuses a turn whose estimated input cannot plausibly fit the model context window,
5
+ * BEFORE auth resolution, circuit admission, or any upstream I/O. #1412 reported ~127k of
6
+ * real context compounding to 1.3M-1.6M tokens and crashing the proxy; the provider would
7
+ * reject such a turn anyway, so paying for the round trip buys nothing.
8
+ *
9
+ * Deliberately narrow. This is not a context manager and not a compaction trigger: it
10
+ * catches the pathological case and stays out of the way otherwise. Every uncertainty
11
+ * resolves toward admitting.
12
+ */
13
+ import { nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type NativeContextLimitsInput } from "../../codex/catalog/metadata";
14
+ import { estimateTokens } from "../../lib/token-estimate";
15
+ import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
16
+ import { modelRecordValue } from "../../reasoning-effort";
17
+ import type { OcxContentPart, OcxParsedRequest, OcxProviderConfig } from "../../types";
18
+
19
+ /**
20
+ * Multiplier applied to the ceiling before refusing.
21
+ *
22
+ * 2.5, not something tighter, because `estimateTokens` can overshoot by 1.6x on its own.
23
+ * `cjkRatio` samples every `stride`-th character, so a payload of fixed-width records whose
24
+ * length aligns with the stride samples as 100% CJK while being ~1.6% CJK, firing the
25
+ * 2.5-chars/token clamp instead of the 4.0 default. Measured on Bun 1.3.14: 126,046 chars,
26
+ * true CJK ratio 0.0161, sampled ratio 1.0, estimate inflated 1.6x. Since 4.0 / 2.5 = 1.6
27
+ * is that branch maximum divergence, a threshold at or under 1.6 would convert the
28
+ * estimator error bar into false 413s.
29
+ *
30
+ * 2.5 sits above it with room for the ~10% model-family ratio spread, and still refuses the
31
+ * #1412 shape (10x) four times over.
32
+ */
33
+ export const ADMISSION_TOLERANCE = 2.5;
34
+
35
+ /**
36
+ * Token cost charged for a remote image URL. The bytes are not in this request — the
37
+ * provider fetches them — so the URL own length is not the cost. A small flat charge
38
+ * acknowledges the tiles the image will occupy without pretending to know its dimensions.
39
+ */
40
+ const REMOTE_IMAGE_TOKENS = 850;
41
+
42
+ /** Decoded image bytes per token. Coarse tile-count proxy, not a provider formula. */
43
+ const IMAGE_BYTES_PER_TOKEN = 750;
44
+
45
+ export interface InputAdmissionResult {
46
+ admitted: boolean;
47
+ estimatedTokens: number;
48
+ /** Resolved ceiling, or null when nothing could be resolved (=> always admitted). */
49
+ ceiling: number | null;
50
+ }
51
+
52
+ function positive(value: unknown): number | null {
53
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
54
+ }
55
+
56
+ /**
57
+ * Charge a `data:` URL by its DECODED size rather than its character length: base64 inflates
58
+ * by 4/3, so charging the string would overcount by a third. A remote URL is charged flat.
59
+ */
60
+ function imageTokens(imageUrl: string): number {
61
+ if (!imageUrl.startsWith("data:")) return REMOTE_IMAGE_TOKENS;
62
+ const comma = imageUrl.indexOf(",");
63
+ if (comma < 0) return REMOTE_IMAGE_TOKENS;
64
+ const payload = imageUrl.length - comma - 1;
65
+ if (payload <= 0) return 0;
66
+ const decoded = Math.floor((payload * 3) / 4);
67
+ return Math.max(1, Math.ceil(decoded / IMAGE_BYTES_PER_TOKEN));
68
+ }
69
+
70
+ function contentPartTokens(part: OcxContentPart, modelId: string): number {
71
+ return part.type === "image" ? imageTokens(part.imageUrl) : estimateTokens(part.text, modelId);
72
+ }
73
+
74
+ function contentTokens(content: string | readonly OcxContentPart[], modelId: string): number {
75
+ if (typeof content === "string") return estimateTokens(content, modelId);
76
+ let total = 0;
77
+ for (const part of content) total += contentPartTokens(part, modelId);
78
+ return total;
79
+ }
80
+
81
+ /**
82
+ * Estimate the input tokens of a parsed request.
83
+ *
84
+ * Walks the whole `OcxMessage` union rather than user text alone. Assistant turns carry
85
+ * their content as `OcxAssistantContentPart[]` — text, thinking blocks, and tool calls whose
86
+ * JSON arguments are frequently the largest single item in an agent conversation. A walk
87
+ * that counted only `{type:"text"}` would undercount exactly the turns that trigger this
88
+ * gate.
89
+ */
90
+ export function estimateInputTokens(parsed: OcxParsedRequest, modelId: string): number {
91
+ const { context } = parsed;
92
+ let total = 0;
93
+
94
+ for (const prompt of context.systemPrompt ?? []) total += estimateTokens(prompt, modelId);
95
+
96
+ for (const message of context.messages) {
97
+ if (message.role === "assistant") {
98
+ for (const part of message.content) {
99
+ if (part.type === "text") total += estimateTokens(part.text, modelId);
100
+ else if (part.type === "thinking") total += estimateTokens(part.thinking, modelId);
101
+ else total += estimateTokens(part.name, modelId) + estimateTokens(JSON.stringify(part.arguments), modelId);
102
+ }
103
+ // Opaque provider blob replayed verbatim upstream, so it costs real input tokens.
104
+ if (message.kiroRedactedReasoning) total += estimateTokens(message.kiroRedactedReasoning, modelId);
105
+ continue;
106
+ }
107
+ total += contentTokens(message.content, modelId);
108
+ }
109
+
110
+ // Tool schemas ride every turn: name, description, and the JSON parameter schema all
111
+ // reach the upstream, and a large MCP catalog can dominate a short conversation.
112
+ for (const tool of context.tools ?? []) {
113
+ total += estimateTokens(tool.name, modelId)
114
+ + estimateTokens(tool.description, modelId)
115
+ + estimateTokens(JSON.stringify(tool.parameters), modelId);
116
+ }
117
+
118
+ return total;
119
+ }
120
+
121
+ /**
122
+ * Resolve the admission ceiling. Pure: no filesystem, no catalog, no registry scan.
123
+ *
124
+ * `provider` must be the ROUTED config (`route.provider`), which `routedProviderConfig`
125
+ * has already transport-guarded and merged. Re-deriving from `config.providers[name]` would
126
+ * reject a user-defined provider that merely shares a built-in name using limits that
127
+ * belong to a different service.
128
+ */
129
+ export function resolveInputCeiling(
130
+ provider: OcxProviderConfig,
131
+ providerName: string,
132
+ modelId: string,
133
+ // Operator cap for the canonical native provider. Passed in rather than read from a
134
+ // config here so this stays pure: no filesystem, no catalog, no registry scan.
135
+ nativeContextCap?: NativeContextLimitsInput,
136
+ ): number | null {
137
+ // `modelRecordValue`, not a bare lookup: the catalog resolves these same two maps that
138
+ // way, so a `gpt-oss` entry covers `gpt-oss:120b`. Reading raw here made the gate fall
139
+ // back to the provider-wide window and refuse turns the model can plainly hold.
140
+ const configured = positive(modelRecordValue(provider.modelContextWindows, modelId))
141
+ ?? positive(provider.contextWindow);
142
+
143
+ // The canonical `openai` registry entry declares no context fields, so without this the
144
+ // gate would be inert on the default Codex route. All three clauses are load-bearing: a
145
+ // transport-mismatched custom provider named "openai" is preserved verbatim by routing
146
+ // and must not inherit built-in native limits, and a routed `provider/model` id is not a
147
+ // native slug. Static maps only — no catalog read.
148
+ const canonicalNativeBare = providerName === OPENAI_CODEX_PROVIDER_ID
149
+ && isCanonicalOpenAiForwardProvider(provider)
150
+ && !modelId.includes("/");
151
+ const nativeLimits = canonicalNativeBare && configured !== null
152
+ ? {
153
+ ...(typeof nativeContextCap === "number" ? { cap: nativeContextCap } : (nativeContextCap ?? {})),
154
+ modelWindows: { [modelId]: configured },
155
+ }
156
+ : nativeContextCap;
157
+ const native = canonicalNativeBare
158
+ ? positive(nativeOpenAiContextWindow(modelId, nativeLimits))
159
+ : null;
160
+ const nativeMaxInput = canonicalNativeBare ? positive(nativeOpenAiMaxInputTokens(modelId, nativeLimits)) : null;
161
+
162
+ const window = canonicalNativeBare ? native : configured;
163
+ // modelMaxInputTokens is an input-only cap, so it can only tighten the window.
164
+ const configuredMaxInput = positive(modelRecordValue(provider.modelMaxInputTokens, modelId));
165
+ const limits = [window, configuredMaxInput, nativeMaxInput].filter((v): v is number => v !== null);
166
+ return limits.length === 0 ? null : Math.min(...limits);
167
+ }
168
+
169
+ /**
170
+ * Fail-open when no ceiling is known; refuse only past `ceiling * ADMISSION_TOLERANCE`.
171
+ *
172
+ * The caller is responsible for skipping compaction turns — see the call site in core.ts.
173
+ */
174
+ export function checkInputAdmission(
175
+ parsed: OcxParsedRequest,
176
+ provider: OcxProviderConfig,
177
+ providerName: string,
178
+ modelId: string,
179
+ nativeContextCap?: NativeContextLimitsInput,
180
+ ): InputAdmissionResult {
181
+ const ceiling = resolveInputCeiling(provider, providerName, modelId, nativeContextCap);
182
+ if (ceiling === null) return { admitted: true, estimatedTokens: 0, ceiling: null };
183
+ const estimatedTokens = estimateInputTokens(parsed, modelId);
184
+ return { admitted: estimatedTokens <= ceiling * ADMISSION_TOLERANCE, estimatedTokens, ceiling };
185
+ }
@@ -0,0 +1,13 @@
1
+ import { formatErrorResponse } from "../../bridge";
2
+ import { RequestPacingQueueOverloadError } from "../../providers/request-pacing";
3
+
4
+ /** Convert local request-pacing admission failures into a retryable HTTP response. */
5
+ export function requestPacingOverloadResponse(error: unknown): Response | undefined {
6
+ if (!(error instanceof RequestPacingQueueOverloadError)) return undefined;
7
+ return formatErrorResponse(
8
+ 429,
9
+ "rate_limit_error",
10
+ error.message,
11
+ { retryAfter: String(error.retryAfterSeconds) },
12
+ );
13
+ }
@@ -0,0 +1,78 @@
1
+ import { formatErrorResponse } from "../../bridge";
2
+ import {
3
+ resolveClientRetryAfter,
4
+ validateClientRetryAfterHeader,
5
+ } from "../../lib/retry-after";
6
+
7
+ /**
8
+ * Passthrough adapters historically relayed upstream non-2xx bodies verbatim.
9
+ * Codex maps an *empty* body to the literal client string "Unknown error"
10
+ * (UnexpectedResponseError) — issue #452. Only empty bodies need wrapping.
11
+ *
12
+ * Non-empty bodies (including ChatGPT `{detail: ...}` account-model 400s and
13
+ * HTML/text errors) must keep their original bytes and headers so pool-retry
14
+ * activation and client diagnostics stay honest.
15
+ *
16
+ * Retry-After is validated independently of the body path:
17
+ * - valid upstream values are preserved
18
+ * - missing/malformed values are replaced when resolveClientRetryAfter yields a value
19
+ * - malformed/expired values are removed when the resolver returns undefined
20
+ * (e.g. quota-exhausted 429s must not keep junk headers or get the synthetic "2")
21
+ */
22
+ export function formatPassthroughUpstreamError(
23
+ status: number,
24
+ bodyText: string,
25
+ options?: {
26
+ statusText?: string;
27
+ headers?: Headers;
28
+ now?: number;
29
+ },
30
+ ): Response {
31
+ const trimmed = bodyText.trim();
32
+ const now = options?.now ?? Date.now();
33
+ const upstreamRetryAfter = options?.headers?.get("retry-after")?.trim() || undefined;
34
+ const originalValid = validateClientRetryAfterHeader(upstreamRetryAfter, now);
35
+ const resolved = resolveClientRetryAfter({
36
+ status,
37
+ message: trimmed || `Provider error ${status}: (empty body)`,
38
+ upstreamRetryAfter,
39
+ now,
40
+ });
41
+
42
+ if (trimmed) {
43
+ const needsSet = resolved !== undefined && upstreamRetryAfter !== resolved;
44
+ const needsDelete = resolved === undefined
45
+ && upstreamRetryAfter !== undefined
46
+ && originalValid === undefined;
47
+
48
+ if (!needsSet && !needsDelete) {
49
+ return new Response(bodyText, {
50
+ status,
51
+ ...(options?.statusText ? { statusText: options.statusText } : {}),
52
+ ...(options?.headers ? { headers: options.headers } : { headers: { "Content-Type": "application/json" } }),
53
+ });
54
+ }
55
+
56
+ const headers = options?.headers
57
+ ? new Headers(options.headers)
58
+ : new Headers({ "Content-Type": "application/json" });
59
+ if (needsSet) headers.set("Retry-After", resolved!);
60
+ else headers.delete("Retry-After");
61
+ return new Response(bodyText, {
62
+ status,
63
+ ...(options?.statusText ? { statusText: options.statusText } : {}),
64
+ headers,
65
+ });
66
+ }
67
+
68
+ const response = formatErrorResponse(
69
+ status,
70
+ "upstream_error",
71
+ `Provider error ${status}: (empty body)`,
72
+ resolved !== undefined ? { retryAfter: resolved } : undefined,
73
+ );
74
+ const headers = new Headers(response.headers);
75
+ headers.set("Content-Type", "application/json");
76
+ if (resolved !== undefined) headers.set("Retry-After", resolved);
77
+ return new Response(response.body, { status: response.status, headers });
78
+ }
@@ -0,0 +1,178 @@
1
+ import { comboFailureDecision } from "../../combos/failover";
2
+ import { readBoundedResponseBody } from "../../lib/bounded-body";
3
+ import { readJsonRequestBody } from "../request-decompress";
4
+ import { finishRequestAttempt, type RequestLogContext } from "../request-log";
5
+ import type { OcxConfig } from "../../types";
6
+ import type { RouteCandidateTrace, RouteDecisionTraceV1 } from "../../routing/trace";
7
+ import { handleResponses as handleResponsesCore } from "./core";
8
+ import { requestPacingOverloadResponse } from "./pacing-overload";
9
+
10
+ type CoreHandler = typeof handleResponsesCore;
11
+ type CoreOptions = Parameters<CoreHandler>[3];
12
+
13
+ export interface PolicyFallbackDeps {
14
+ runCore?: CoreHandler;
15
+ }
16
+
17
+ function candidateKey(candidate: Pick<RouteCandidateTrace, "provider" | "model">): string {
18
+ return `${candidate.provider}\u0000${candidate.model}`;
19
+ }
20
+
21
+ /**
22
+ * Rank the remaining candidates from the ORIGINAL policy trace. The initial
23
+ * decision stays immutable; fallback execution belongs in attempts[], not in a
24
+ * rewritten decision trace.
25
+ */
26
+ export function rankPolicyFallbackCandidates(
27
+ trace: RouteDecisionTraceV1,
28
+ tried: ReadonlySet<string>,
29
+ ): RouteCandidateTrace[] {
30
+ return trace.candidates
31
+ .map((candidate, index) => ({ candidate, index }))
32
+ .filter(({ candidate }) =>
33
+ candidate.eligible
34
+ && candidate.exclusions.length === 0
35
+ && !tried.has(candidateKey(candidate)))
36
+ .sort((left, right) => {
37
+ const scoreDelta = (right.candidate.score?.total ?? Number.NEGATIVE_INFINITY)
38
+ - (left.candidate.score?.total ?? Number.NEGATIVE_INFINITY);
39
+ return scoreDelta || left.index - right.index;
40
+ })
41
+ .map(({ candidate }) => candidate);
42
+ }
43
+
44
+ function requestWithCandidate(
45
+ req: Request,
46
+ rawBody: Record<string, unknown>,
47
+ candidate: Pick<RouteCandidateTrace, "provider" | "model">,
48
+ ): Request {
49
+ const headers = new Headers(req.headers);
50
+ headers.delete("content-encoding");
51
+ headers.delete("content-length");
52
+ headers.set("content-type", "application/json");
53
+ return new Request(req.url, {
54
+ method: req.method,
55
+ headers,
56
+ body: JSON.stringify({ ...rawBody, model: `${candidate.provider}/${candidate.model}` }),
57
+ signal: req.signal,
58
+ });
59
+ }
60
+
61
+ function errorCodeFromText(text: string): string | undefined {
62
+ if (!text) return undefined;
63
+ try {
64
+ const payload = JSON.parse(text) as { error?: { code?: unknown; type?: unknown }; code?: unknown };
65
+ const candidate = payload.error?.code ?? payload.error?.type ?? payload.code;
66
+ return typeof candidate === "string" ? candidate : undefined;
67
+ } catch {
68
+ return undefined;
69
+ }
70
+ }
71
+
72
+ async function shouldHopPolicyCandidate(response: Response, signal?: AbortSignal): Promise<boolean> {
73
+ if (response.status < 400 || signal?.aborted) return false;
74
+ try {
75
+ const inspected = await readBoundedResponseBody(response.clone(), { signal });
76
+ const text = inspected.displaySafe ? inspected.text : "";
77
+ return comboFailureDecision(response.status, text, { code: errorCodeFromText(text) }) === "hop";
78
+ } catch {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ function isPolicyDecision(trace: RouteDecisionTraceV1 | undefined): trace is RouteDecisionTraceV1 {
84
+ return trace?.routeKind === "policy" && !!trace.profile;
85
+ }
86
+
87
+ /** Finalize the failed physical attempt so the retry receives a fresh attempt row. */
88
+ function finishFailedPolicyAttempt(logCtx: RequestLogContext, status: number): void {
89
+ const attempt = logCtx.activeAttempt;
90
+ if (attempt) {
91
+ const startedAt = logCtx.activeAttemptStartedAt ?? Date.now();
92
+ finishRequestAttempt(attempt, status, Math.max(0, Date.now() - startedAt), attempt.usage ?? logCtx.usage);
93
+ }
94
+ delete logCtx.activeAttempt;
95
+ delete logCtx.activeAttemptStartedAt;
96
+ delete logCtx.usage;
97
+ delete logCtx.usageFromBridge;
98
+ delete logCtx.upstreamError;
99
+ delete logCtx.terminalHttpStatus;
100
+ delete logCtx.terminalErrorCode;
101
+ delete logCtx.terminalIncompleteReason;
102
+ }
103
+
104
+ /**
105
+ * Run a Responses request and, only for an explicitly selected policy profile,
106
+ * hop to the next eligible policy candidate after a retryable pre-success
107
+ * failure. The initial policy trace remains the canonical selection evidence;
108
+ * physical retries continue to accumulate in the existing request attempts.
109
+ */
110
+ export async function handleResponsesWithPolicyFallback(
111
+ req: Request,
112
+ config: OcxConfig,
113
+ logCtx: RequestLogContext,
114
+ options: CoreOptions = {},
115
+ deps: PolicyFallbackDeps = {},
116
+ ): Promise<Response> {
117
+ const runCore = deps.runCore ?? handleResponsesCore;
118
+ let requestBodyReadNotified = false;
119
+ const coreOptions: CoreOptions = options.onRequestBodyRead
120
+ ? {
121
+ ...options,
122
+ onRequestBodyRead: () => {
123
+ if (requestBodyReadNotified) return;
124
+ requestBodyReadNotified = true;
125
+ options.onRequestBodyRead?.();
126
+ },
127
+ }
128
+ : options;
129
+ let rawBody: Record<string, unknown> | null = null;
130
+ try {
131
+ const parsed = await readJsonRequestBody(req.clone());
132
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) rawBody = parsed as Record<string, unknown>;
133
+ } catch {
134
+ // Core owns the client-facing parse/decompression error.
135
+ }
136
+
137
+ let response: Response;
138
+ try {
139
+ response = await runCore(req, config, logCtx, coreOptions);
140
+ } catch (error) {
141
+ const overload = requestPacingOverloadResponse(error);
142
+ if (overload) return overload;
143
+ throw error;
144
+ }
145
+ const initialTrace = logCtx.routeDecision;
146
+ const initialRequestedModel = logCtx.requestedModel;
147
+ if (!rawBody || !isPolicyDecision(initialTrace)) return response;
148
+
149
+ const tried = new Set<string>([
150
+ candidateKey({ provider: initialTrace.selected.provider, model: initialTrace.selected.model }),
151
+ ]);
152
+
153
+ while (await shouldHopPolicyCandidate(response, req.signal)) {
154
+ if (req.signal.aborted) return response;
155
+ const next = rankPolicyFallbackCandidates(initialTrace, tried)[0];
156
+ if (!next) return response;
157
+ tried.add(candidateKey(next));
158
+
159
+ finishFailedPolicyAttempt(logCtx, response.status);
160
+ const retryRequest = requestWithCandidate(req, rawBody, next);
161
+ try {
162
+ try {
163
+ response = await runCore(retryRequest, config, logCtx, coreOptions);
164
+ } catch (error) {
165
+ const overload = requestPacingOverloadResponse(error);
166
+ if (overload) return overload;
167
+ throw error;
168
+ }
169
+ } finally {
170
+ logCtx.requestedModel = initialRequestedModel;
171
+ logCtx.routeDecision = initialTrace;
172
+ }
173
+ }
174
+
175
+ return response;
176
+ }
177
+
178
+ export const handleResponses = handleResponsesWithPolicyFallback;