@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
@@ -2,6 +2,7 @@ import type { Server } from "bun";
2
2
  import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse, type ResponsesTerminalStatus } from "../../bridge";
3
3
  import {
4
4
  getConfigPath,
5
+ loadConfig,
5
6
  multiAgentGuidanceEnabled,
6
7
  resolveEnvValue,
7
8
  } from "../../config";
@@ -10,6 +11,7 @@ import { buildCompactV1Output, COMPACT_PROMPT, decodeCompactionSummary, extractC
10
11
  import { FORWARD_HEADERS, sanitizeReasoningInputContent } from "../../adapters/openai-responses";
11
12
  import { expandPreviousResponseInput, previousResponseProviderState, rememberResponseState } from "../../responses/state";
12
13
  import { routeModel } from "../../router";
14
+ import type { RawEntry } from "../../codex/catalog/parsing";
13
15
  import {
14
16
  advanceComboAfterFailure,
15
17
  comboDefaultEffort,
@@ -26,7 +28,7 @@ import {
26
28
  } from "../../combos";
27
29
  import { isInjectionDebugEnabled } from "../../lib/debug-settings";
28
30
  import { injectionDebugLog } from "../../lib/injection-debug-log";
29
- import { modelInList, namespacedToolName } from "../../types";
31
+ import { modelInList, namespacedToolName, toolChoiceToolPredicate } from "../../types";
30
32
  import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig, OcxProviderContinuationState, OcxUsage } from "../../types";
31
33
  import {
32
34
  forceRefreshOAuthAccessSnapshot,
@@ -96,23 +98,37 @@ import {
96
98
  sanitizePassthroughHeaders,
97
99
  } from "../relay";
98
100
  import { hasResponsesItemIdRepair, relaySseWithResponsesItemIdRepair } from "../responses-item-id-repair";
99
- import type { EffectiveSubagentRoster, SpawnAgentSurface } from "../../codex/catalog";
101
+ import type { EffectiveSubagentModel, EffectiveSubagentRoster, SpawnAgentSurface } from "../../codex/catalog";
100
102
  import type { TranslatorBudget } from "../../lib/translator-budget";
101
103
 
102
104
 
103
105
  export function buildToolBridgeMaps(parsed: OcxParsedRequest, budget?: TranslatorBudget): {
104
- toolNsMap: Map<string, { namespace: string; name: string }>;
106
+ toolNsMap: Map<string, { namespace: string; name: string; freeform?: true }>;
107
+ declaredToolNames: Set<string>;
108
+ /** Declared parameter schema per request-visible tool name (#1611 integer repair). */
109
+ toolParameterSchemas: Map<string, Record<string, unknown>>;
105
110
  freeformToolNames: Set<string>;
106
111
  toolSearchToolNames: Set<string>;
107
112
  } {
108
- const toolNsMap = new Map<string, { namespace: string; name: string }>();
113
+ const toolNsMap = new Map<string, { namespace: string; name: string; freeform?: true }>();
114
+ const declaredToolNames = new Set<string>();
115
+ const toolParameterSchemas = new Map<string, Record<string, unknown>>();
109
116
  const freeformToolNames = new Set<string>();
110
117
  const toolSearchToolNames = new Set<string>();
111
- for (const t of parsed.context.tools ?? []) {
118
+ const requestedTools = parsed.context.tools ?? [];
119
+ const toolAllowed = toolChoiceToolPredicate(parsed.options.toolChoice, requestedTools);
120
+ const authorizedTools = requestedTools.filter(toolAllowed);
121
+ for (const t of authorizedTools) {
122
+ // Upstream output is untrusted: only restore calls for tools the caller authorized.
123
+ const wireName = namespacedToolName(t.namespace, t.name);
124
+ budget?.chargeRetained(new TextEncoder().encode(wireName).byteLength, { kind: "retained_collectors" });
125
+ declaredToolNames.add(wireName);
126
+ // Retained by reference (the schema is already resident in parsed.context.tools),
127
+ // so this adds a map entry rather than a copy of every tool's parameters.
128
+ if (t.parameters && typeof t.parameters === "object") toolParameterSchemas.set(wireName, t.parameters);
112
129
  if (t.namespace) {
113
- const wireName = namespacedToolName(t.namespace, t.name);
114
130
  budget?.chargeRetained(new TextEncoder().encode(JSON.stringify([wireName, t.namespace, t.name])).byteLength, { kind: "retained_collectors" });
115
- toolNsMap.set(wireName, { namespace: t.namespace, name: t.name });
131
+ toolNsMap.set(wireName, { namespace: t.namespace, name: t.name, ...(t.freeform ? { freeform: true } : {}) });
116
132
  }
117
133
  if (t.freeform) {
118
134
  budget?.chargeRetained(new TextEncoder().encode(t.name).byteLength, { kind: "retained_collectors" });
@@ -123,7 +139,30 @@ export function buildToolBridgeMaps(parsed: OcxParsedRequest, budget?: Translato
123
139
  toolSearchToolNames.add(t.name);
124
140
  }
125
141
  }
126
- return { toolNsMap, freeformToolNames, toolSearchToolNames };
142
+ // Some routed providers echo a bare tool_choice selector instead of the flattened catalog
143
+ // name. Accept only selectors the client actually sent and only when the full request catalog
144
+ // contains one tool with that logical name.
145
+ const choice = parsed.options.toolChoice;
146
+ const bareChoiceNames = new Set(
147
+ choice && typeof choice === "object"
148
+ ? ("allowedTools" in choice ? choice.allowedTools : [choice.name])
149
+ : [],
150
+ );
151
+ const bareNameCounts = new Map<string, number>();
152
+ for (const t of requestedTools) {
153
+ bareNameCounts.set(t.name, (bareNameCounts.get(t.name) ?? 0) + 1);
154
+ }
155
+ for (const t of authorizedTools) {
156
+ if (!t.namespace || !bareChoiceNames.has(t.name) || bareNameCounts.get(t.name) !== 1 || declaredToolNames.has(t.name)) continue;
157
+ budget?.chargeRetained(new TextEncoder().encode(t.name).byteLength, { kind: "retained_collectors" });
158
+ declaredToolNames.add(t.name);
159
+ budget?.chargeRetained(new TextEncoder().encode(JSON.stringify([t.name, t.namespace, t.name])).byteLength, { kind: "retained_collectors" });
160
+ toolNsMap.set(t.name, { namespace: t.namespace, name: t.name, ...(t.freeform ? { freeform: true } : {}) });
161
+ if (t.parameters && typeof t.parameters === "object") {
162
+ toolParameterSchemas.set(t.name, t.parameters);
163
+ }
164
+ }
165
+ return { toolNsMap, declaredToolNames, toolParameterSchemas, freeformToolNames, toolSearchToolNames };
127
166
  }
128
167
 
129
168
 
@@ -169,6 +208,7 @@ export function collabSurface(parsed: OcxParsedRequest): "v1" | "v2" | null {
169
208
 
170
209
  export interface MultiAgentGuidanceOptions {
171
210
  multiAgentGuidanceEnabled?: boolean;
211
+ codexAccountNamespace?: string;
172
212
  injectionModel?: string;
173
213
  injectionEffort?: string;
174
214
  subagentModels?: string[];
@@ -183,7 +223,8 @@ export interface MultiAgentGuidanceDeps {
183
223
  configuredModels: readonly string[],
184
224
  surface: SpawnAgentSurface,
185
225
  ) => EffectiveSubagentRoster | Promise<EffectiveSubagentRoster>;
186
- collectCatalogState?: () => { state: "fresh" | "stale" | "not_running" | "unknown" };
226
+ collectCatalogState?: () => { state: "fresh" | "stale" | "not_running" | "unknown" }
227
+ | Promise<{ state: "fresh" | "stale" | "not_running" | "unknown" }>;
187
228
  }
188
229
 
189
230
  async function defaultCollectCatalogState(): Promise<{ state: "fresh" | "stale" | "not_running" | "unknown" }> {
@@ -193,8 +234,8 @@ async function defaultCollectCatalogState(): Promise<{ state: "fresh" | "stale"
193
234
  if (override === "fresh" || override === "stale" || override === "not_running" || override === "unknown") {
194
235
  return { state: override };
195
236
  }
196
- const { collectCodexAppServerCatalogState } = await import("../../codex/app-server-processes");
197
- return collectCodexAppServerCatalogState();
237
+ const { collectCodexAppServerCatalogStateForRequest } = await import("../../codex/app-server-processes");
238
+ return collectCodexAppServerCatalogStateForRequest();
198
239
  }
199
240
 
200
241
 
@@ -204,7 +245,49 @@ export async function resolveEffectiveSubagentRoster(
204
245
  surface: SpawnAgentSurface,
205
246
  ): Promise<EffectiveSubagentRoster> {
206
247
  const { effectiveSubagentRoster } = await import("../../codex/catalog");
207
- return effectiveSubagentRoster(configuredModels, surface);
248
+ return effectiveSubagentRoster(configuredModels, surface, await freshSubagentCatalogEntries());
249
+ }
250
+
251
+ /**
252
+ * The persisted Codex catalog, with native context metadata re-derived from the CURRENT config.
253
+ *
254
+ * The subagent roster reads the catalog FILE, which is only as fresh as the last sync. A row
255
+ * written before the operator widened the native window keeps its old `context_window`, so a
256
+ * child was planning and compacting against a narrower budget than its parent — measured at
257
+ * 272,000 x 95% = 258,400 while the request path resolved 922,000 (#2574).
258
+ *
259
+ * Re-applying the override is cheap and idempotent: it is the same function the writer uses,
260
+ * so a fresh catalog is unchanged and a stale one is repaired in memory rather than silently
261
+ * believed. It does not rewrite the file — the row on disk stays whatever the last sync wrote,
262
+ * and `ocx sync` remains what refreshes it.
263
+ */
264
+ async function freshSubagentCatalogEntries(): Promise<RawEntry[]> {
265
+ const { readCatalog, readCodexCatalogPath, nativeContextLimits } = await import("../../codex/catalog");
266
+ const { applyNativeOpenAiContextOverride } = await import("../../codex/catalog/parsing");
267
+ const entries = readCatalog(readCodexCatalogPath())?.models ?? [];
268
+ if (entries.length === 0) return [];
269
+ let limits: ReturnType<typeof nativeContextLimits>;
270
+ try {
271
+ limits = nativeContextLimits(loadConfig());
272
+ } catch {
273
+ // An unreadable config must not cost the caller its roster; serve the file as written.
274
+ return entries;
275
+ }
276
+ return entries.map(entry => {
277
+ const clone = { ...entry };
278
+ applyNativeOpenAiContextOverride(clone, limits);
279
+ return clone;
280
+ });
281
+ }
282
+
283
+ /** Reuse one parsed catalog snapshot across every roster projection for this request. */
284
+ async function createRequestScopedSubagentRosterResolver(): Promise<NonNullable<
285
+ MultiAgentGuidanceDeps["resolveEffectiveSubagentRoster"]
286
+ >> {
287
+ const { effectiveSubagentRoster } = await import("../../codex/catalog");
288
+ const catalogEntries = await freshSubagentCatalogEntries();
289
+ return (configuredModels, surface) =>
290
+ effectiveSubagentRoster(configuredModels, surface, catalogEntries);
208
291
  }
209
292
 
210
293
 
@@ -218,10 +301,14 @@ export async function multiAgentGuidanceText(
218
301
  const {
219
302
  injectionModel,
220
303
  injectionEffort,
304
+ codexAccountNamespace,
221
305
  subagentModels,
222
306
  subagentModelFallback,
223
307
  injectionPrompt,
224
308
  } = options;
309
+ const activeAccountNamespace = codexAccountNamespace?.length
310
+ ? codexAccountNamespace
311
+ : undefined;
225
312
  const surface = collabSurface(parsed);
226
313
  if (surface === null) return null;
227
314
 
@@ -231,9 +318,24 @@ export async function multiAgentGuidanceText(
231
318
  // Codex cannot actually spawn makes spawn_agent reject the override, so
232
319
  // suppress positive model claims while the state is stale or unknown.
233
320
  const catalogState = await (deps.collectCatalogState ?? defaultCollectCatalogState)();
321
+ // #1354 / #1395: `collectCodexAppServerCatalogState()` folds every app-server
322
+ // owned by the current user into ONE global observation, and the inbound
323
+ // request carries no sender PID or catalog fingerprint. So a stale process A
324
+ // makes the global state `stale` even when this request came from a fresh
325
+ // process B, and `unknown` can be reached by a process-enumeration failure
326
+ // that says nothing about any particular server.
327
+ //
328
+ // Emitting "do not set model or reasoning_effort overrides" off that global
329
+ // observation prohibits options the active `spawn_agent` tool legitimately
330
+ // advertises, for a request we cannot attribute to the stale process. The
331
+ // safe behaviour is to withhold OpenCodex's own disk-derived claims —
332
+ // preferred model, roster, fallback, custom guidance — and stay silent about
333
+ // overrides, leaving the active tool schema authoritative.
334
+ //
335
+ // `fresh` and `not_running` are unchanged: there we can positively describe
336
+ // the catalog, so the guidance below still applies.
234
337
  if (catalogState.state === "stale" || catalogState.state === "unknown") {
235
- return "<multi_agent_mode>The model catalog changed after Codex started; do not set "
236
- + "model or reasoning_effort overrides until Codex restarts.</multi_agent_mode>";
338
+ return null;
237
339
  }
238
340
  // codex-rs supplies the Proactive text on v2; the proxy only adds model-designation
239
341
  // guidance, and only when there is something concrete to designate: a configured
@@ -242,15 +344,51 @@ export async function multiAgentGuidanceText(
242
344
  ...(subagentModels ?? []),
243
345
  ...(injectionModel ? [injectionModel] : []),
244
346
  ];
245
- const resolveRoster = deps.resolveEffectiveSubagentRoster ?? resolveEffectiveSubagentRoster;
347
+ const resolveRoster = deps.resolveEffectiveSubagentRoster
348
+ ?? await createRequestScopedSubagentRosterResolver();
246
349
  const effective = await resolveRoster(configuredForGuidance, "v2");
247
- const rosterModels = effective.advertised.filter(candidate =>
248
- (subagentModels ?? []).some(model => slugsEquivalent(model, candidate.model))
249
- );
350
+ // Resolve the roster and preferred roles independently so a bare native can project onto its
351
+ // generated account rows without making an unrelated provider/gpt-* row look equivalent.
352
+ // The intersection keeps both projections inside Codex's one global five-model window.
353
+ const candidateModels = new Set(effective.candidates.map(candidate => candidate.model));
354
+ const withinCandidateWindow = (candidate: EffectiveSubagentModel): boolean =>
355
+ candidateModels.has(candidate.model);
356
+ const configuredSubagents = subagentModels ?? [];
357
+ const subagentEffective = configuredSubagents.length > 0
358
+ ? injectionModel
359
+ ? await resolveRoster(configuredSubagents, "v2")
360
+ : effective
361
+ : undefined;
362
+ const preferredEffective = injectionModel
363
+ ? configuredSubagents.length > 0
364
+ ? await resolveRoster([injectionModel], "v2")
365
+ : effective
366
+ : undefined;
367
+ const explicitlyConfigured = (candidate: EffectiveSubagentModel): boolean =>
368
+ configuredSubagents.some(model =>
369
+ model.includes("/") && slugsEquivalent(model, candidate.model)
370
+ );
371
+ const allowedForCurrentRoute = (candidate: EffectiveSubagentModel): boolean =>
372
+ explicitlyConfigured(candidate)
373
+ || !candidate.model.includes("/")
374
+ || (activeAccountNamespace !== undefined
375
+ && candidate.model.startsWith(`${activeAccountNamespace}/`));
376
+ const rosterModels = (subagentEffective?.advertised ?? [])
377
+ .filter(withinCandidateWindow)
378
+ .filter(allowedForCurrentRoute);
250
379
  const roster = subagentRosterText(rosterModels);
251
- const preferred = injectionModel
252
- ? effective.candidates.find(candidate => slugsEquivalent(injectionModel, candidate.model))
380
+ const preferredCandidates = (preferredEffective?.advertised ?? []).filter(withinCandidateWindow);
381
+ const soleBarePreferred = preferredCandidates.length === 1
382
+ && !preferredCandidates[0]!.model.includes("/")
383
+ ? preferredCandidates[0]
253
384
  : undefined;
385
+ const preferred = injectionModel?.includes("/")
386
+ ? preferredCandidates[0]
387
+ : activeAccountNamespace
388
+ ? preferredCandidates.find(candidate =>
389
+ candidate.model.startsWith(`${activeAccountNamespace}/`)
390
+ ) ?? soleBarePreferred
391
+ : soleBarePreferred;
254
392
 
255
393
  if (isInjectionDebugEnabled() && effective.excluded.length > 0) {
256
394
  injectionDebugLog(`[opencodex] multi-agent guidance excluded: ${effective.excluded
@@ -260,7 +398,11 @@ export async function multiAgentGuidanceText(
260
398
  const fallbackGuidance = subagentFallbackGuidanceText({ subagentModelFallback } as OcxConfig);
261
399
  if (!injectionModel && roster === "" && fallbackGuidance === "") return null;
262
400
  if (injectionPrompt) {
263
- return `<multi_agent_mode>${applyInjectionPlaceholders(injectionPrompt, injectionModel, injectionEffort, roster, fallbackGuidance)}</multi_agent_mode>`;
401
+ // Bare ids must resolve to a unique/current-route candidate. Preserve the legacy raw
402
+ // fallback only for explicit routed/account-qualified ids.
403
+ const promptModel = preferred?.model
404
+ ?? (injectionModel?.includes("/") ? injectionModel : undefined);
405
+ return `<multi_agent_mode>${applyInjectionPlaceholders(injectionPrompt, promptModel, injectionEffort, roster, fallbackGuidance)}</multi_agent_mode>`;
264
406
  }
265
407
  if (!preferred && roster === "" && fallbackGuidance === "") return null;
266
408
  let text = "When the active spawn_agent tool supports optional \"model\" or \"reasoning_effort\" overrides, "
@@ -323,32 +465,93 @@ function isRecord(value: unknown): value is Record<string, unknown> {
323
465
  return !!value && typeof value === "object" && !Array.isArray(value);
324
466
  }
325
467
 
326
- function isGeneratedDeveloperItem(item: unknown, text: string): boolean {
327
- if (!isRecord(item) || item.type !== "message" || item.role !== "developer") return false;
328
- if (!Array.isArray(item.content) || item.content.length !== 1) return false;
468
+ function generatedDeveloperText(item: unknown): string | undefined {
469
+ if (!isRecord(item) || item.type !== "message" || item.role !== "developer") return undefined;
470
+ if (!Array.isArray(item.content) || item.content.length !== 1) return undefined;
329
471
  const [part] = item.content;
330
- return isRecord(part) && part.type === "input_text" && part.text === text;
472
+ return isRecord(part) && part.type === "input_text" && typeof part.text === "string"
473
+ ? part.text
474
+ : undefined;
475
+ }
476
+
477
+ function isGeneratedDeveloperItem(item: unknown, text: string): boolean {
478
+ return generatedDeveloperText(item) === text;
479
+ }
480
+
481
+ function isDeveloperPrefixItem(item: unknown): boolean {
482
+ if (!isRecord(item)) return false;
483
+ if (item.type === "additional_tools") return item.role === "developer";
484
+ const type = item.type ?? (typeof item.role === "string" ? "message" : undefined);
485
+ return type === "message" && (item.role === "system" || item.role === "developer");
486
+ }
487
+
488
+ function leadingDeveloperPrefixLength(items: readonly unknown[]): number {
489
+ let index = 0;
490
+ while (index < items.length && isDeveloperPrefixItem(items[index])) index += 1;
491
+ return index;
492
+ }
493
+
494
+ function isConversationalItem(item: unknown): boolean {
495
+ if (!isRecord(item)) return false;
496
+ if (item.type === "agent_message") return true;
497
+ const type = item.type ?? (typeof item.role === "string" ? "message" : undefined);
498
+ return type === "message" && (item.role === "user" || item.role === "assistant");
499
+ }
500
+
501
+ function statefulRawInsertionIndex(items: readonly unknown[], replayPrefixLen: number): number {
502
+ for (let index = replayPrefixLen; index < items.length; index += 1) {
503
+ if (isConversationalItem(items[index])) return index;
504
+ }
505
+ const last = items[items.length - 1];
506
+ return isRecord(last) && last.type === "compaction_trigger"
507
+ ? items.length - 1
508
+ : items.length;
331
509
  }
332
510
 
333
511
  export function injectDeveloperMessage(parsed: OcxParsedRequest, text: string): void {
334
512
  const raw = parsed._rawBody as { input?: unknown } | undefined;
513
+ const rawInput = raw && Array.isArray(raw.input) ? raw.input : undefined;
514
+ const replayPrefixLen = rawInput
515
+ ? Math.min(parsed._replayPrefixLen ?? 0, rawInput.length)
516
+ : 0;
335
517
  const devItem = { type: "message", role: "developer", content: [{ type: "input_text", text }] };
336
- if (raw && Array.isArray(raw.input)) {
337
- const replayPrefixLen = Math.min(parsed._replayPrefixLen ?? 0, raw.input.length);
338
- if (raw.input.slice(0, replayPrefixLen).some(item => isGeneratedDeveloperItem(item, text))) {
518
+ if (rawInput) {
519
+ const replayPrefix = rawInput.slice(0, replayPrefixLen);
520
+ const taggedGuidance = text.startsWith("<multi_agent_mode>") && text.endsWith("</multi_agent_mode>");
521
+ const lastTaggedGuidance = taggedGuidance
522
+ ? replayPrefix.map(generatedDeveloperText)
523
+ .filter(item => item?.startsWith("<multi_agent_mode>") && item.endsWith("</multi_agent_mode>"))
524
+ .at(-1)
525
+ : undefined;
526
+ if (taggedGuidance ? lastTaggedGuidance === text : replayPrefix.some(item => isGeneratedDeveloperItem(item, text))) {
339
527
  return;
340
528
  }
341
529
  }
342
530
 
343
- parsed.context.messages.push({ role: "developer", content: text, timestamp: Date.now() });
344
- if (raw && Array.isArray(raw.input)) {
345
- // compaction_trigger must remain the final input item (codex-rs + ChatGPT backend both
346
- // validate this). Insert the developer message BEFORE the trigger when present.
347
- const last = raw.input[raw.input.length - 1];
348
- if (last && typeof last === "object" && (last as { type?: string }).type === "compaction_trigger") {
349
- raw.input.splice(raw.input.length - 1, 0, devItem);
531
+ const statefulContinuation = parsed.previousResponseId !== undefined;
532
+ const message = { role: "developer" as const, content: text, timestamp: Date.now() };
533
+ const statefulRawIndex = statefulContinuation && rawInput
534
+ ? statefulRawInsertionIndex(rawInput, replayPrefixLen)
535
+ : undefined;
536
+
537
+ // A previous_response_id delta can begin with tool/protocol items. Keep those first, then place
538
+ // changed guidance before the current conversation. Stateless requests keep guidance in the prefix.
539
+ if (statefulContinuation) {
540
+ const index = Math.min(
541
+ parsed._continuationConversationMessageIndex ?? parsed.context.messages.length,
542
+ parsed.context.messages.length,
543
+ );
544
+ parsed.context.messages.splice(index, 0, message);
545
+ } else {
546
+ const prefixLen = parsed.context.messages.findIndex(item => item.role !== "developer");
547
+ parsed.context.messages.splice(prefixLen < 0 ? parsed.context.messages.length : prefixLen, 0, message);
548
+ }
549
+
550
+ if (rawInput) {
551
+ if (statefulContinuation) {
552
+ rawInput.splice(statefulRawIndex!, 0, devItem);
350
553
  } else {
351
- raw.input.push(devItem);
554
+ rawInput.splice(leadingDeveloperPrefixLength(rawInput), 0, devItem);
352
555
  }
353
556
  }
354
557
  }
@@ -0,0 +1,178 @@
1
+ import type { ResponsesTerminalStatus } from "../../bridge";
2
+ import type { RequestLogContext } from "../request-log";
3
+ import { createSseInspector } from "../relay";
4
+ import { MAX_CLIENT_SSE_FRAME_BYTES } from "../sse-frame-buffer";
5
+
6
+ const COMBO_STREAM_PREFLIGHT_MAX_BYTES = MAX_CLIENT_SSE_FRAME_BYTES;
7
+ // Keep retained object count proportional to the same byte budget used by the
8
+ // shared SSE framer. Tiny or empty upstream reads must not bypass the byte cap.
9
+ const COMBO_STREAM_PREFLIGHT_MAX_CHUNKS = Math.max(
10
+ 1,
11
+ Math.ceil(COMBO_STREAM_PREFLIGHT_MAX_BYTES / 1024),
12
+ );
13
+
14
+ const PRE_OUTPUT_CONTROL_EVENTS = new Set([
15
+ "response.created",
16
+ "response.in_progress",
17
+ "response.queued",
18
+ "response.heartbeat",
19
+ ]);
20
+
21
+ const TERMINAL_EVENTS = new Set([
22
+ "response.completed",
23
+ "response.failed",
24
+ "response.incomplete",
25
+ ]);
26
+
27
+ /**
28
+ * Decide when replaying the request on another combo target would risk duplicating
29
+ * client-visible output or a tool-side effect. Unknown event types commit the child
30
+ * conservatively; only the small Responses lifecycle preamble remains replayable.
31
+ */
32
+ export function comboStreamPayloadCommitsOutput(payload: unknown): boolean {
33
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return true;
34
+ const type = (payload as { type?: unknown }).type;
35
+ if (typeof type !== "string") return true;
36
+ return !PRE_OUTPUT_CONTROL_EVENTS.has(type) && !TERMINAL_EVENTS.has(type);
37
+ }
38
+
39
+ function replayBufferedResponse(
40
+ response: Response,
41
+ reader: ReadableStreamDefaultReader<Uint8Array>,
42
+ buffered: Uint8Array[],
43
+ ): Response {
44
+ let index = 0;
45
+ const body = new ReadableStream<Uint8Array>({
46
+ async pull(controller) {
47
+ if (index < buffered.length) {
48
+ controller.enqueue(buffered[index++]!);
49
+ return;
50
+ }
51
+ try {
52
+ const next = await reader.read();
53
+ if (next.done) controller.close();
54
+ else controller.enqueue(next.value);
55
+ } catch (error) {
56
+ try { controller.error(error); } catch { /* consumer already closed */ }
57
+ }
58
+ },
59
+ cancel(reason) {
60
+ reader.cancel(reason).catch(() => undefined);
61
+ },
62
+ });
63
+ return new Response(body, {
64
+ status: response.status,
65
+ statusText: response.statusText,
66
+ headers: response.headers,
67
+ });
68
+ }
69
+
70
+ function failedTerminalResponse(
71
+ response: Response,
72
+ terminalPayload: Record<string, unknown>,
73
+ logCtx: RequestLogContext,
74
+ ): Response {
75
+ const nested = terminalPayload.response;
76
+ const terminalResponse = nested && typeof nested === "object" && !Array.isArray(nested)
77
+ ? nested as Record<string, unknown>
78
+ : {};
79
+ const nestedError = terminalResponse.error;
80
+ const error = nestedError && typeof nestedError === "object" && !Array.isArray(nestedError)
81
+ ? nestedError as Record<string, unknown>
82
+ : {
83
+ type: "upstream_error",
84
+ code: "upstream_server_error",
85
+ message: logCtx.upstreamError ?? "Provider stream failed before producing output",
86
+ };
87
+ const headers = new Headers(response.headers);
88
+ headers.set("content-type", "application/json");
89
+ headers.delete("content-length");
90
+ headers.delete("content-encoding");
91
+ const usage = terminalResponse.usage;
92
+ return new Response(JSON.stringify({
93
+ error,
94
+ // The combo classifier needs only the error and optional usage. Do not carry
95
+ // response ids, provider metadata, or future terminal fields into the client
96
+ // error envelope merely because they shared the terminal snapshot.
97
+ response: {
98
+ error,
99
+ ...(usage && typeof usage === "object" && !Array.isArray(usage) ? { usage } : {}),
100
+ },
101
+ }), {
102
+ status: logCtx.terminalHttpStatus ?? 502,
103
+ headers,
104
+ });
105
+ }
106
+
107
+ export type ComboStreamPreflightResult =
108
+ | { kind: "accepted"; response: Response }
109
+ | { kind: "failed"; response: Response };
110
+
111
+ /**
112
+ * Buffer a combo child's downstream SSE only until the request becomes unsafe to
113
+ * replay or reaches a terminal. This owns exactly one body reader. The aggregate
114
+ * buffer is capped by bytes and retained chunks; hitting either cap commits the
115
+ * current target instead of growing memory or guessing that replay is safe.
116
+ */
117
+ export async function preflightComboStreamResponse(
118
+ response: Response,
119
+ logCtx: RequestLogContext,
120
+ ): Promise<ComboStreamPreflightResult> {
121
+ const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
122
+ if (!response.ok || !response.body || !contentType.includes("text/event-stream")) {
123
+ return { kind: "accepted", response };
124
+ }
125
+
126
+ const reader = response.body.getReader();
127
+ const buffered: Uint8Array[] = [];
128
+ let bufferedBytes = 0;
129
+ let outputCommitted = false;
130
+ let terminalStatus: ResponsesTerminalStatus | undefined;
131
+ let failedPayload: Record<string, unknown> | undefined;
132
+ const inspector = createSseInspector({
133
+ logCtx,
134
+ onParsedPayload: payload => {
135
+ if (comboStreamPayloadCommitsOutput(payload)) outputCommitted = true;
136
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return;
137
+ if ((payload as { type?: unknown }).type === "response.failed") {
138
+ failedPayload = payload as Record<string, unknown>;
139
+ }
140
+ },
141
+ onTerminal: status => { terminalStatus = status; },
142
+ });
143
+
144
+ try {
145
+ for (;;) {
146
+ const next = await reader.read();
147
+ if (next.done) {
148
+ inspector.finish();
149
+ } else {
150
+ if (bufferedBytes + next.value.byteLength > COMBO_STREAM_PREFLIGHT_MAX_BYTES) {
151
+ // Keep the cap about memory the preflight allocates. The upstream chunk already exists;
152
+ // copying it before committing would transiently exceed the boundary for no
153
+ // replay benefit. Preserve it unsliced behind the already-bounded prefix.
154
+ return {
155
+ kind: "accepted",
156
+ response: replayBufferedResponse(response, reader, [...buffered, next.value]),
157
+ };
158
+ }
159
+ const retained = next.value.slice();
160
+ buffered.push(retained);
161
+ bufferedBytes += retained.byteLength;
162
+ inspector.feed(retained);
163
+ }
164
+
165
+ if (terminalStatus === "failed" && !outputCommitted && failedPayload) {
166
+ await reader.cancel("retrying zero-output combo stream failure").catch(() => undefined);
167
+ return { kind: "failed", response: failedTerminalResponse(response, failedPayload, logCtx) };
168
+ }
169
+ if (next.done || terminalStatus !== undefined || outputCommitted
170
+ || bufferedBytes >= COMBO_STREAM_PREFLIGHT_MAX_BYTES
171
+ || buffered.length >= COMBO_STREAM_PREFLIGHT_MAX_CHUNKS) {
172
+ return { kind: "accepted", response: replayBufferedResponse(response, reader, buffered) };
173
+ }
174
+ }
175
+ } finally {
176
+ inspector.dispose();
177
+ }
178
+ }