@iislee/opencodex 2.11.0 → 2.35.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 (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -8,12 +8,25 @@
8
8
  export class ChatCompletionsRequestError extends Error {}
9
9
 
10
10
  type Rec = Record<string, unknown>;
11
+ type ChatCompletionsRoutingBody = Rec & { model: string; messages: unknown[] };
11
12
 
12
13
  function isRec(v: unknown): v is Rec {
13
14
  return !!v && typeof v === "object" && !Array.isArray(v);
14
15
  }
15
16
 
17
+ /** Validate only the fields needed before Chat routing, without projecting the body. */
18
+ export function assertChatCompletionsRoutingBody(raw: unknown): asserts raw is ChatCompletionsRoutingBody {
19
+ if (!isRec(raw)) throw new ChatCompletionsRequestError("request body must be a JSON object");
20
+ if (typeof raw.model !== "string" || raw.model.length === 0) {
21
+ throw new ChatCompletionsRequestError("model is required");
22
+ }
23
+ if (!Array.isArray(raw.messages) || raw.messages.length === 0) {
24
+ throw new ChatCompletionsRequestError("messages must be a non-empty array");
25
+ }
26
+ }
27
+
16
28
  const OUTPUT_CONFIG_EFFORTS = new Set(["minimal", "low", "medium", "high", "xhigh", "max", "ultra"]);
29
+ const OUTPUT_CONFIG_SUMMARIES = new Set(["auto", "concise", "detailed", "none"]);
17
30
 
18
31
  function contentToText(content: unknown): string {
19
32
  if (typeof content === "string") return content;
@@ -40,6 +53,14 @@ function imageUrlFromPart(part: Rec): string | null {
40
53
  return null;
41
54
  }
42
55
 
56
+ function videoUrlFromPart(part: Rec): string | null {
57
+ if (part.type !== "video_url") return null;
58
+ const videoUrl = part.video_url;
59
+ if (typeof videoUrl === "string" && videoUrl.length > 0) return videoUrl;
60
+ if (isRec(videoUrl) && typeof videoUrl.url === "string" && videoUrl.url.length > 0) return videoUrl.url;
61
+ return null;
62
+ }
63
+
43
64
  function userContentToBlocks(content: unknown): Rec[] {
44
65
  if (typeof content === "string") {
45
66
  return content.length > 0 ? [{ type: "input_text", text: content }] : [];
@@ -57,7 +78,12 @@ function userContentToBlocks(content: unknown): Rec[] {
57
78
  continue;
58
79
  }
59
80
  const imageUrl = imageUrlFromPart(raw);
60
- if (imageUrl) blocks.push({ type: "input_image", image_url: imageUrl });
81
+ if (imageUrl) {
82
+ blocks.push({ type: "input_image", image_url: imageUrl });
83
+ continue;
84
+ }
85
+ const videoUrl = videoUrlFromPart(raw);
86
+ if (videoUrl) blocks.push({ type: "input_video", video_url: videoUrl });
61
87
  }
62
88
  return blocks;
63
89
  }
@@ -86,17 +112,8 @@ function pushSystemText(parts: string[], content: unknown): void {
86
112
  if (text) parts.push(text);
87
113
  }
88
114
 
89
- function toolCallsToItems(toolCalls: unknown, input: Rec[]): void {
115
+ function toolCallsToItems(toolCalls: unknown, input: Rec[], knownNameByCallId: Map<string, string>): void {
90
116
  if (!Array.isArray(toolCalls)) return;
91
- // Recover names from earlier function_call items in the same transcript when a client
92
- // re-sends tool_calls with only id/arguments (replace-style merge lost function.name).
93
- const knownNameByCallId = new Map<string, string>();
94
- for (const item of input) {
95
- if (!isRec(item) || item.type !== "function_call") continue;
96
- if (typeof item.call_id === "string" && typeof item.name === "string" && item.name.length > 0) {
97
- knownNameByCallId.set(item.call_id, item.name);
98
- }
99
- }
100
117
  for (const raw of toolCalls) {
101
118
  if (!isRec(raw)) continue;
102
119
  const fn = isRec(raw.function) ? raw.function : null;
@@ -205,21 +222,34 @@ function resolveReasoningEffort(raw: Rec): string | undefined {
205
222
  return undefined;
206
223
  }
207
224
 
225
+ /**
226
+ * Chat Completions clients (Grok Build, Copilot, OpenAI-compatible SDKs) expect
227
+ * `delta.reasoning_content` whenever the model thinks. The internal Responses
228
+ * parser hides thinking unless `reasoning.summary` is set and is not `"none"`.
229
+ * Map the common Chat Completions knobs onto that field. When the client only
230
+ * sent an effort, default the summary to `"auto"` so traces are not swallowed.
231
+ */
232
+ function resolveReasoningSummary(raw: Rec): string | undefined {
233
+ if (isRec(raw.reasoning) && typeof raw.reasoning.summary === "string" && OUTPUT_CONFIG_SUMMARIES.has(raw.reasoning.summary)) {
234
+ return raw.reasoning.summary;
235
+ }
236
+ if (raw.include_reasoning === false) return "none";
237
+ if (raw.include_reasoning === true) return "auto";
238
+ return undefined;
239
+ }
240
+
208
241
  /**
209
242
  * Translate an OpenAI Chat Completions request body into a /v1/responses request body.
210
243
  * Throws ChatCompletionsRequestError (-> 400) on malformed input.
211
244
  */
212
245
  export function chatCompletionsToResponsesBody(raw: unknown): Rec {
213
- if (!isRec(raw)) throw new ChatCompletionsRequestError("request body must be a JSON object");
214
- if (typeof raw.model !== "string" || raw.model.length === 0) {
215
- throw new ChatCompletionsRequestError("model is required");
216
- }
217
- if (!Array.isArray(raw.messages) || raw.messages.length === 0) {
218
- throw new ChatCompletionsRequestError("messages must be a non-empty array");
219
- }
246
+ assertChatCompletionsRoutingBody(raw);
220
247
 
221
248
  const systemParts: string[] = [];
222
249
  const input: Rec[] = [];
250
+ // Recover replace-style tool calls incrementally instead of rebuilding the
251
+ // call-id index from the entire translated transcript for every message.
252
+ const knownNameByCallId = new Map<string, string>();
223
253
 
224
254
  for (const msg of raw.messages) {
225
255
  if (!isRec(msg)) continue;
@@ -237,7 +267,7 @@ export function chatCompletionsToResponsesBody(raw: unknown): Rec {
237
267
  case "assistant": {
238
268
  const blocks = assistantContentToBlocks(msg.content);
239
269
  if (blocks.length > 0) input.push({ type: "message", role: "assistant", content: blocks });
240
- if (msg.tool_calls !== undefined) toolCallsToItems(msg.tool_calls, input);
270
+ if (msg.tool_calls !== undefined) toolCallsToItems(msg.tool_calls, input, knownNameByCallId);
241
271
  break;
242
272
  }
243
273
  case "tool": {
@@ -282,11 +312,18 @@ export function chatCompletionsToResponsesBody(raw: unknown): Rec {
282
312
  if (raw.stop !== undefined) body.stop = raw.stop;
283
313
  if (typeof raw.user === "string") body.user = raw.user;
284
314
  if (typeof raw.parallel_tool_calls === "boolean") body.parallel_tool_calls = raw.parallel_tool_calls;
315
+ if (typeof raw.service_tier === "string") body.service_tier = raw.service_tier;
285
316
  if (typeof raw.prompt_cache_key === "string") body.prompt_cache_key = raw.prompt_cache_key;
286
317
  if (raw.metadata !== undefined) body.metadata = raw.metadata;
287
318
 
288
319
  const effort = resolveReasoningEffort(raw);
289
- if (effort) body.reasoning = { effort };
320
+ const summary = resolveReasoningSummary(raw);
321
+ if (effort || summary !== undefined) {
322
+ body.reasoning = {
323
+ ...(effort ? { effort } : {}),
324
+ summary: summary ?? "auto",
325
+ };
326
+ }
290
327
 
291
328
  const text = responseFormatToText(raw.response_format);
292
329
  if (text) body.text = text;
@@ -7,9 +7,16 @@
7
7
  */
8
8
  type Rec = Record<string, unknown>;
9
9
 
10
- import { decodeServerSentEvents } from "../lib/sse-decoder";
10
+ import { decodeServerSentEvents, sseFieldValue } from "../lib/sse-decoder";
11
11
  import { isTranslatorBudgetExceededError, type TranslatorBudget } from "../lib/translator-budget";
12
- import { classifyError, CYBER_POLICY_ERROR_CODE, isCyberPolicyCode, isCyberPolicyMessage } from "../lib/errors";
12
+ import {
13
+ classifyError,
14
+ cyberPolicyErrorType,
15
+ CYBER_POLICY_ERROR_CODE,
16
+ isCyberPolicyCode,
17
+ isCyberPolicyMessage,
18
+ } from "../lib/errors";
19
+ import { redactSecretString } from "../lib/redact";
13
20
 
14
21
  function isRec(v: unknown): v is Rec {
15
22
  return !!v && typeof v === "object" && !Array.isArray(v);
@@ -48,14 +55,14 @@ export function chatCompletionsUsage(usage: unknown): Rec {
48
55
  export function chatCompletionsErrorBody(
49
56
  status: number,
50
57
  message: string,
51
- type = "invalid_request_error",
58
+ type?: string,
52
59
  code?: string | null,
53
60
  ): Rec {
54
61
  if (isCyberPolicyCode(code) || isCyberPolicyMessage(message)) {
55
62
  return {
56
63
  error: {
57
64
  message,
58
- type: "invalid_request_error",
65
+ type: cyberPolicyErrorType(type),
59
66
  param: null,
60
67
  code: CYBER_POLICY_ERROR_CODE,
61
68
  },
@@ -64,7 +71,7 @@ export function chatCompletionsErrorBody(
64
71
  return {
65
72
  error: {
66
73
  message,
67
- type,
74
+ type: type ?? "invalid_request_error",
68
75
  param: null,
69
76
  code: code !== undefined
70
77
  ? code
@@ -311,18 +318,21 @@ export function responsesSseToChatCompletionsSse(
311
318
  // Deliver the error frame then close the stream abnormally (no [DONE]).
312
319
  // Do not controller.error() — that can drop already-enqueued bytes from consumers
313
320
  // like response.text().
314
- const statusHint = details?.status ?? streamErrorStatus(message);
315
- const classified = classifyError(statusHint, details?.type ?? "upstream_error", message);
321
+ const safeMessage = redactSecretString(message);
322
+ const statusHint = details?.status ?? streamErrorStatus(safeMessage);
323
+ const classified = classifyError(statusHint, details?.type ?? "upstream_error", safeMessage);
316
324
  const translatorOverflow = details?.code === "translation_buffer_limit";
317
325
  if (translatorOverflow) {
318
326
  upstreamAbort.abort(new Error("upstream translation buffer exceeded the safe limit"));
319
327
  closeToolCalls();
320
328
  try { void sseIterator?.return(undefined).catch(() => {}); } catch { /* already closed */ }
321
329
  classified.code = "translation_buffer_limit";
322
- classified.type = "invalid_request_error";
330
+ // Provider-controlled overflow is an upstream failure on every path:
331
+ // streaming frame, collector, and defensive JSON agree on 502.
332
+ classified.type = "upstream_error";
323
333
  } else if (isCyberPolicyCode(details?.code) || classified.code === CYBER_POLICY_ERROR_CODE) {
324
334
  classified.code = CYBER_POLICY_ERROR_CODE;
325
- classified.type = "invalid_request_error";
335
+ classified.type = cyberPolicyErrorType(details?.type);
326
336
  } else if (details?.code !== undefined && details.code !== null && !classified.code) {
327
337
  classified.code = details.code;
328
338
  }
@@ -468,7 +478,7 @@ export function responsesSseToChatCompletionsSse(
468
478
  fail(message, {
469
479
  code,
470
480
  ...(code === "translation_buffer_limit"
471
- ? { status: 413, type: "invalid_request_error" }
481
+ ? { status: 502, type: "upstream_error" }
472
482
  : { type, ...(code === CYBER_POLICY_ERROR_CODE ? { status: 400 } : {}) }),
473
483
  });
474
484
  break;
@@ -514,7 +524,7 @@ export function responsesSseToChatCompletionsSse(
514
524
  if (isTranslatorBudgetExceededError(err)) {
515
525
  upstreamAbort.abort(err);
516
526
  closeToolCalls();
517
- fail(err.message, { status: 413, type: "invalid_request_error", code: err.code });
527
+ fail(err.message, { status: 502, type: "upstream_error", code: err.code });
518
528
  } else {
519
529
  fail(err instanceof Error ? err.message : String(err));
520
530
  }
@@ -629,6 +639,9 @@ export async function collectChatCompletion(
629
639
  let content = "";
630
640
  let reasoning = "";
631
641
  const toolCalls = new Map<number, { id: string; name: string; arguments: string; argumentBytes: number }>();
642
+ // Per-call budget scopes (2 MiB/call enforced by the budget): the map key is the
643
+ // wire index, which is stable across deltas and present before the call id.
644
+ const callScope = (index: number) => `chat_collect_${index}`;
632
645
  let finishReason = "stop";
633
646
  let usage: unknown;
634
647
  let streamError: ChatCompletionsStreamError | null = null;
@@ -648,9 +661,11 @@ export async function collectChatCompletion(
648
661
  } catch (err) {
649
662
  if (isChatCompletionsStreamError(err)) throw err;
650
663
  if (isTranslatorBudgetExceededError(err)) {
664
+ // Provider-controlled overflow is an upstream failure, not a client
665
+ // request error: match the adapter/bridge contract (502 upstream_error).
651
666
  throw new ChatCompletionsStreamError(err.message, {
652
- status: 413,
653
- type: "invalid_request_error",
667
+ status: 502,
668
+ type: "upstream_error",
654
669
  code: err.code,
655
670
  });
656
671
  }
@@ -664,8 +679,9 @@ export async function collectChatCompletion(
664
679
  const rawFrame = buffer.slice(0, sep);
665
680
  buffer = replaceRetained(buffer, buffer.slice(sep + 2), "live_transient");
666
681
  for (const line of rawFrame.split("\n")) {
667
- if (!line.startsWith("data: ")) continue;
668
- const data = line.slice(6).trim();
682
+ const rawData = sseFieldValue(line, "data");
683
+ if (rawData === null) continue;
684
+ const data = rawData.trim();
669
685
  if (!data || data === "[DONE]") continue;
670
686
  let parsed: unknown;
671
687
  try { parsed = JSON.parse(data); } catch { continue; }
@@ -677,11 +693,15 @@ export async function collectChatCompletion(
677
693
  const type = typeof parsed.error.type === "string" ? parsed.error.type : "server_error";
678
694
  const code = typeof parsed.error.code === "string" ? parsed.error.code : null;
679
695
  const status = code === "translation_buffer_limit"
680
- ? 413
696
+ ? 502
681
697
  : code === CYBER_POLICY_ERROR_CODE || isCyberPolicyMessage(message)
682
698
  ? 400
683
699
  : streamErrorStatus(message);
684
- streamError = new ChatCompletionsStreamError(message, { status, type, code });
700
+ streamError = new ChatCompletionsStreamError(message, {
701
+ status,
702
+ type: code === "translation_buffer_limit" ? "upstream_error" : type,
703
+ code,
704
+ });
685
705
  continue;
686
706
  }
687
707
  if (parsed.usage) usage = parsed.usage;
@@ -697,7 +717,12 @@ export async function collectChatCompletion(
697
717
  for (const tc of delta.tool_calls) {
698
718
  if (!isRec(tc)) continue;
699
719
  const index = typeof tc.index === "number" ? tc.index : 0;
700
- const current = toolCalls.get(index) ?? { id: "", name: "", arguments: "", argumentBytes: 0 };
720
+ let current = toolCalls.get(index);
721
+ if (!current) {
722
+ current = { id: "", name: "", arguments: "", argumentBytes: 0 };
723
+ toolCalls.set(index, current);
724
+ translatorBudget.openCall(callScope(index));
725
+ }
701
726
  if (typeof tc.id === "string") current.id = tc.id;
702
727
  const fn = isRec(tc.function) ? tc.function : {};
703
728
  // Done-frame final arguments are authoritative last-write-wins snapshots.
@@ -707,27 +732,43 @@ export async function collectChatCompletion(
707
732
  const nextBytes = replace
708
733
  ? Buffer.byteLength(fn.arguments)
709
734
  : appendedUtf8Bytes(current.arguments, current.argumentBytes, fn.arguments);
710
- const reservation = translatorBudget.reserveTransient(nextBytes, { kind: "retained_collectors" });
735
+ const reservation = translatorBudget.reserveTransient(nextBytes, { kind: "tool_args", callId: callScope(index) });
711
736
  try {
712
737
  current.arguments = replace ? fn.arguments : current.arguments + fn.arguments;
713
738
  reservation.commitRetained();
714
- translatorBudget.releaseRetained(current.argumentBytes, { kind: "retained_collectors" });
739
+ translatorBudget.releaseRetained(current.argumentBytes, { kind: "tool_args", callId: callScope(index) });
715
740
  current.argumentBytes = nextBytes;
716
741
  } catch (error) {
717
742
  reservation.release();
718
743
  throw error;
719
744
  }
720
745
  }
721
- toolCalls.set(index, current);
722
746
  }
723
747
  }
724
748
  }
725
749
  }
726
750
  }
751
+ } catch (error) {
752
+ // Never leak an open call scope on the error path; the turn budget's
753
+ // dispose is a backstop, not the owner of this transfer.
754
+ for (const index of toolCalls.keys()) translatorBudget.closeCall(callScope(index));
755
+ // Processing-time overflow (per-call or turn cap) gets the same typed
756
+ // contract as read-time overflow: 502 upstream_error.
757
+ if (isTranslatorBudgetExceededError(error)) {
758
+ throw new ChatCompletionsStreamError(error.message, {
759
+ status: 502,
760
+ type: "upstream_error",
761
+ code: error.code,
762
+ });
763
+ }
764
+ throw error;
727
765
  } finally {
728
766
  reader.releaseLock();
729
767
  }
730
- if (streamError) throw streamError;
768
+ if (streamError) {
769
+ for (const index of toolCalls.keys()) translatorBudget.closeCall(callScope(index));
770
+ throw streamError;
771
+ }
731
772
 
732
773
  const message: Rec = {
733
774
  role: "assistant",
@@ -735,17 +776,40 @@ export async function collectChatCompletion(
735
776
  };
736
777
  if (reasoning) message.reasoning_content = reasoning;
737
778
  if (toolCalls.size > 0) {
738
- message.tool_calls = [...toolCalls.entries()]
739
- .sort((a, b) => a[0] - b[0])
740
- .map(([, tc]) => {
741
- const copy = {
742
- id: tc.id || `call_${uuid().slice(0, 16)}`,
743
- type: "function",
744
- function: { name: tc.name, arguments: tc.arguments },
745
- };
746
- translatorBudget.chargeRetained(Buffer.byteLength(JSON.stringify(copy)), { kind: "retained_collectors" });
747
- return copy;
748
- });
779
+ // Final owner transfer is itself a charging operation: if it overflows,
780
+ // release every copy already charged in this loop and close every scope
781
+ // still open — the error must not escape as a raw budget exception.
782
+ const chargedCopies: number[] = [];
783
+ try {
784
+ message.tool_calls = [...toolCalls.entries()]
785
+ .sort((a, b) => a[0] - b[0])
786
+ .map(([index, tc]) => {
787
+ const copy = {
788
+ id: tc.id || `call_${uuid().slice(0, 16)}`,
789
+ type: "function",
790
+ function: { name: tc.name, arguments: tc.arguments },
791
+ };
792
+ const copyBytes = Buffer.byteLength(JSON.stringify(copy));
793
+ translatorBudget.chargeRetained(copyBytes, { kind: "retained_collectors" });
794
+ chargedCopies.push(copyBytes);
795
+ // The serialized owner is charged; release the per-call accumulation.
796
+ translatorBudget.closeCall(callScope(index));
797
+ return copy;
798
+ });
799
+ } catch (error) {
800
+ for (const copyBytes of chargedCopies) {
801
+ translatorBudget.releaseRetained(copyBytes, { kind: "retained_collectors" });
802
+ }
803
+ for (const index of toolCalls.keys()) translatorBudget.closeCall(callScope(index));
804
+ if (isTranslatorBudgetExceededError(error)) {
805
+ throw new ChatCompletionsStreamError(error.message, {
806
+ status: 502,
807
+ type: "upstream_error",
808
+ code: error.code,
809
+ });
810
+ }
811
+ throw error;
812
+ }
749
813
  if (finishReason === "stop") finishReason = "tool_calls";
750
814
  }
751
815
 
@@ -11,16 +11,17 @@
11
11
  * Ownership contract: this module only creates/overwrites/deletes files matching
12
12
  * `ocx-*.md` inside the agents dir. User-authored agents are never touched.
13
13
  */
14
- import { lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
14
+ import { lstatSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
15
15
  import { join } from "node:path";
16
16
  import type { OcxConfig } from "../types";
17
+ import { renameAtomicFile } from "../lib/windows-atomic-replace";
17
18
  import { claudeCodeAlias, claudeCodeNativeAlias } from "./alias";
18
- import { resolveAutoContext, stripOneMillionMarker, withOneMillionMarker } from "./context-windows";
19
+ import { AUTO_CONTEXT_OFF, shouldMarkOneMillion, stripOneMillionMarker, withOneMillionMarker } from "./context-windows";
19
20
  import { claudeConfigDir } from "./gateway-cache";
20
21
  import { DEFAULT_SUBAGENT_MODELS, hasOwnProvider } from "../config";
21
22
  import { effectiveBlockedSkillNames, resolveInboundModel } from "./inbound";
22
23
  import { knownModelIdsForProvider } from "../router";
23
- import { decodeRoutedModelId } from "../providers/slug-codec";
24
+ import { decodeRoutedModelIdOrThrow } from "../providers/slug-codec";
24
25
 
25
26
  export interface ClaudeAgentDef {
26
27
  file: string;
@@ -58,13 +59,34 @@ function pickerDefaultModel(configDir: string): string | null {
58
59
  /** Roster entry -> alias + display parts. Entries are bare native slugs or "provider/id".
59
60
  * Codex-facing encoded ids (`provider/vendor-model`) decode to the native slash id first
60
61
  * so the alias joins the raw-native context-window map (context-windows.ts). */
62
+
63
+ /**
64
+ * Generated subagent defs cannot rely on the parent's auto-context compaction
65
+ * pairing, so their [1m] marker follows the AUTHORITATIVE window only: mark when
66
+ * the effective window (exact selector, then the canonical [1m] form, then bare)
67
+ * is genuinely >= 1M; strip an inherited unsafe marker back to the bare selector;
68
+ * with no window information, keep the selector as it was. Genuine routed [1m]
69
+ * ids are preserved through the canonical-exact lookup. (#854)
70
+ */
71
+ function withSubagentContextMarker(selector: string, windows: Record<string, number>): string {
72
+ const bare = stripOneMillionMarker(selector);
73
+ const wasMarked = selector !== bare;
74
+ const canonicalExact = wasMarked ? `${bare}[1m]` : selector;
75
+ const authoritativeWindow = windows[selector] ?? windows[canonicalExact] ?? windows[bare];
76
+ if (typeof authoritativeWindow === "number" && authoritativeWindow > 0) {
77
+ return shouldMarkOneMillion(authoritativeWindow, AUTO_CONTEXT_OFF)
78
+ ? (withOneMillionMarker(selector, windows) ?? selector)
79
+ : bare;
80
+ }
81
+ return wasMarked ? selector : bare;
82
+ }
61
83
  function entryParts(entry: string, config: OcxConfig): { alias: string; id: string; provider: string } {
62
84
  const slash = entry.indexOf("/");
63
85
  if (slash > 0) {
64
86
  const provider = entry.slice(0, slash);
65
87
  const prov = hasOwnProvider(config.providers, provider) ? config.providers[provider] : undefined;
66
88
  const id = prov
67
- ? decodeRoutedModelId(entry.slice(slash + 1), knownModelIdsForProvider(provider, prov))
89
+ ? decodeRoutedModelIdOrThrow(entry.slice(slash + 1), knownModelIdsForProvider(provider, prov, config))
68
90
  : entry.slice(slash + 1);
69
91
  return { alias: claudeCodeAlias(provider, id), id, provider };
70
92
  }
@@ -72,7 +94,6 @@ function entryParts(entry: string, config: OcxConfig): { alias: string; id: stri
72
94
  }
73
95
 
74
96
  export function buildClaudeAgentDefs(config: OcxConfig, windows: Record<string, number>, configDir = claudeConfigDir()): ClaudeAgentDef[] {
75
- const auto = resolveAutoContext(config.claudeCode);
76
97
  const blockedSkills = effectiveBlockedSkillNames(config.claudeCode);
77
98
  const blockedSkillsFor = (model: string): readonly string[] => {
78
99
  const unmarked = stripOneMillionMarker(model);
@@ -87,8 +108,10 @@ export function buildClaudeAgentDefs(config: OcxConfig, windows: Record<string,
87
108
  const coveredModels = new Set<string>();
88
109
 
89
110
  const push = (name: string, alias: string, description: string) => {
90
- // Effective model value: [1m] marking follows the same predicate as env slots.
91
- const model = withOneMillionMarker(alias, windows, auto) ?? alias;
111
+ // Generated defs mark [1m] on the authoritative window only never the
112
+ // main-session auto-context predicate (a 372K route marked [1m] would be
113
+ // accounted at 1M with no compaction safety net in the subagent).
114
+ const model = withSubagentContextMarker(alias, windows);
92
115
  const bare = alias.toLowerCase();
93
116
  if (coveredModels.has(bare)) return;
94
117
  coveredModels.add(bare);
@@ -120,7 +143,7 @@ export function buildClaudeAgentDefs(config: OcxConfig, windows: Record<string,
120
143
  // the next launch sync — documented limit. No resolvable default -> no self def.
121
144
  const selfModel = pickerDefaultModel(configDir) ?? (config.claudeCode?.model?.trim() || null);
122
145
  if (selfModel) {
123
- const marked = withOneMillionMarker(selfModel, windows, auto) ?? selfModel;
146
+ const marked = withSubagentContextMarker(selfModel, windows);
124
147
  defs.push({
125
148
  file: `${OWNED_PREFIX}self.md`,
126
149
  name: `${OWNED_PREFIX}self`,
@@ -195,7 +218,14 @@ function isOwnedFile(path: string): boolean {
195
218
  export function syncClaudeAgentDefs(defs: readonly ClaudeAgentDef[], configDir = claudeConfigDir()): string[] | null {
196
219
  try {
197
220
  const dir = join(configDir, "agents");
198
- mkdirSync(dir, { recursive: true });
221
+ if (defs.length === 0) {
222
+ try { lstatSync(dir); } catch (error) {
223
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
224
+ throw error;
225
+ }
226
+ } else {
227
+ mkdirSync(dir, { recursive: true });
228
+ }
199
229
  const keep = new Set(defs.map(d => d.file));
200
230
  for (const existing of readdirSync(dir)) {
201
231
  if (!existing.startsWith(OWNED_PREFIX) || !existing.endsWith(".md")) continue;
@@ -213,7 +243,7 @@ export function syncClaudeAgentDefs(defs: readonly ClaudeAgentDef[], configDir =
213
243
  } catch { /* does not exist: ours to create */ }
214
244
  const tmp = `${target}.tmp-${process.pid}`;
215
245
  writeFileSync(tmp, renderAgentDef(def), { encoding: "utf8", mode: 0o644 });
216
- renameSync(tmp, target);
246
+ renameAtomicFile(tmp, target, undefined, "claude-agents");
217
247
  written.push(def.file);
218
248
  }
219
249
  return written;
@@ -10,12 +10,24 @@
10
10
  */
11
11
  import { aliasForNative, aliasForRoute } from "./alias";
12
12
  import { desktop3pAlias } from "./desktop-3p";
13
- import { nativeOpenAiContextWindow, type CatalogModel } from "../codex/catalog";
13
+ import { nativeOpenAiContextWindow, type CatalogModel, type NativeContextLimitsInput } from "../codex/catalog";
14
14
 
15
15
  const ONE_MILLION = 1_000_000;
16
16
 
17
- /** Auto-context defaults (devlog 260712 020, user-approved). */
18
- export const AUTO_COMPACT_WINDOW_DEFAULT = 350_000;
17
+ /**
18
+ * Auto-context defaults (devlog 260712 020, user-approved).
19
+ *
20
+ * The compact window is the token count at which Claude Code starts compacting, and it is
21
+ * also the floor `shouldMarkOneMillion` uses — a model may only carry the marker if it can
22
+ * host this window. 350,000 was chosen when the widest native row advertised 372,000.
23
+ *
24
+ * It now matches the auto-compaction limit the Codex catalog ships for the same models
25
+ * (`nativeAutoCompactLimit`: 829,800 against the 922,000 native window). Leaving the two
26
+ * apart meant one model compacting at 350k under Claude Code and at 829,800 under Codex.
27
+ * The value stays clear of the measured 922,000 ceiling by ~92k, so compaction still has
28
+ * room to run before the upstream refuses.
29
+ */
30
+ export const AUTO_COMPACT_WINDOW_DEFAULT = 829_800;
19
31
  export const AUTO_CONTEXT_FLOOR = 200_000;
20
32
  /** Binary-verified accepted range for CLAUDE_CODE_AUTO_COMPACT_WINDOW (2.1.207: pSo=1e5, yDs=1e6). */
21
33
  export const AUTO_COMPACT_WINDOW_MIN = 100_000;
@@ -59,7 +71,7 @@ function inAutoCompactRange(value: number): boolean {
59
71
  * predicate so marker and threshold never separate (audit 021 #2); an invalid
60
72
  * value disables auto marking entirely (the CLI would ignore it, leaving marked
61
73
  * sub-1M models without their safety net). Out-of-range CONFIG values fall back
62
- * to the 350k default (the management API rejects them; this guards hand-edits).
74
+ * to AUTO_COMPACT_WINDOW_DEFAULT (the management API rejects them; this guards hand-edits).
63
75
  */
64
76
  export function resolveAutoContext(claudeCode: AutoContextConfigSlice | undefined, envOverride?: string): AutoContextMode {
65
77
  if (claudeCode?.autoContext === false) return AUTO_CONTEXT_OFF;
@@ -89,6 +101,10 @@ export function shouldMarkOneMillion(window: number | undefined, auto: AutoConte
89
101
  export function buildClaudeContextWindows(
90
102
  nativeSlugs: readonly string[],
91
103
  routedModels: readonly CatalogModel[],
104
+ // A configured providerContextCaps.openai has to reach the native rows here too. Without
105
+ // it the Claude surface keeps advertising the uncapped authoritative window while the
106
+ // Codex catalog advertises the capped one, and the two disagree about the same model.
107
+ nativeContextCap?: NativeContextLimitsInput,
92
108
  ): Record<string, number> {
93
109
  const out: Record<string, number> = {};
94
110
  const put = (key: string | null, value: number) => {
@@ -96,23 +112,30 @@ export function buildClaudeContextWindows(
96
112
  if (out[key] === undefined) out[key] = value; // first-wins (registry policy)
97
113
  };
98
114
  for (const slug of nativeSlugs) {
99
- const window = nativeOpenAiContextWindow(slug);
115
+ const window = nativeOpenAiContextWindow(slug, nativeContextCap);
100
116
  if (typeof window !== "number" || window <= 0) continue;
101
117
  put(slug, window);
102
118
  put(desktop3pAlias("native", slug), window);
103
119
  put(aliasForNative(slug), window);
104
120
  }
121
+ // Anthropic passthrough guard (audit 021 #3): canonical claude ids ride the
122
+ // subscription passthrough — marking a sub-1M one would strap [1m]/1M-beta onto
123
+ // a model that cannot host it. Register anthropic rows only at >=1M.
124
+ const registrable = routedModels.filter(
125
+ m =>
126
+ typeof m.contextWindow === "number" &&
127
+ m.contextWindow > 0 &&
128
+ !(m.provider === "anthropic" && m.contextWindow < ONE_MILLION),
129
+ );
105
130
  // Bare routed ids are registered only when unambiguous across providers (audit
106
- // 021 #5) — natives are registered first, so a native slug always wins the bare key.
131
+ // 021 #5) — natives are registered first, so a native slug always wins the bare
132
+ // key. Counted over the rows that can actually claim the key: a row this loop
133
+ // skips contributes no window, so letting it veto the bare key withholds an
134
+ // answer that was never in doubt.
107
135
  const bareCounts = new Map<string, number>();
108
- for (const m of routedModels) bareCounts.set(m.id, (bareCounts.get(m.id) ?? 0) + 1);
109
- for (const m of routedModels) {
110
- const window = m.contextWindow;
111
- if (typeof window !== "number" || window <= 0) continue;
112
- // Anthropic passthrough guard (audit 021 #3): canonical claude ids ride the
113
- // subscription passthrough — marking a sub-1M one would strap [1m]/1M-beta onto
114
- // a model that cannot host it. Register anthropic rows only at >=1M.
115
- if (m.provider === "anthropic" && window < ONE_MILLION) continue;
136
+ for (const m of registrable) bareCounts.set(m.id, (bareCounts.get(m.id) ?? 0) + 1);
137
+ for (const m of registrable) {
138
+ const window = m.contextWindow as number;
116
139
  put(`${m.provider}/${m.id}`, window);
117
140
  put(desktop3pAlias(m.provider, m.id), window);
118
141
  put(aliasForRoute(m.provider, m.id), window);