@iislee/opencodex 2.11.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -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 +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -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 +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -6,17 +6,21 @@ import {
6
6
  addFinalRequestLog,
7
7
  httpStatusForRequestLogTerminal,
8
8
  inspectResponseLogJson,
9
- inspectResponseLogSsePayload,
10
9
  inspectResponseLogSsePayloadParsed,
11
10
  recordFirstOutput,
12
11
  type RequestLogContext,
13
12
  type RequestLogEntry,
14
13
  } from "./request-log";
14
+ import {
15
+ BoundedSseFrameBuffer,
16
+ joinSseFrameBytes,
17
+ MAX_CLIENT_SSE_FRAME_BYTES,
18
+ } from "./sse-frame-buffer";
15
19
 
16
20
  const nativePassthroughSseResponses = new WeakSet<Response>();
17
21
  const eagerRelaySseResponses = new WeakSet<Response>();
18
22
 
19
- export const MAX_INSPECTION_SSE_FRAME_BYTES = 4 * 1024 * 1024;
23
+ export const MAX_INSPECTION_SSE_FRAME_BYTES = MAX_CLIENT_SSE_FRAME_BYTES;
20
24
  export const MAX_COMPLETED_OUTPUT_ITEMS = 256;
21
25
  export const MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES = 8 * 1024 * 1024;
22
26
  export const MAX_TAIL_ERROR_MESSAGE_CHARS = 512;
@@ -95,6 +99,74 @@ export function buildFailedTailPayload(err: unknown): string {
95
99
  });
96
100
  }
97
101
 
102
+ export type SseTerminalOutputBoundary = {
103
+ feed(chunk: Uint8Array): Uint8Array;
104
+ finish(): Uint8Array;
105
+ terminalSeen(): boolean;
106
+ doneSeen(): boolean;
107
+ dispose(): void;
108
+ };
109
+
110
+ /**
111
+ * Frame-aware client output boundary shared by both native Responses relays.
112
+ * It buffers only the current incomplete SSE block under the same hard byte
113
+ * cap as inspection, forwards complete blocks through the first Responses
114
+ * terminal, and drops every later block/byte.
115
+ */
116
+ export function createSseTerminalOutputBoundary(): SseTerminalOutputBoundary {
117
+ const decoder = new TextDecoder();
118
+ const framer = new BoundedSseFrameBuffer(MAX_INSPECTION_SSE_FRAME_BYTES);
119
+ let terminal = false;
120
+ let done = false;
121
+ let disposed = false;
122
+
123
+ const processFrames = (
124
+ frames: ReturnType<BoundedSseFrameBuffer["feed"]>,
125
+ ): Uint8Array => {
126
+ if (disposed || terminal || frames.length === 0) return new Uint8Array(0);
127
+ const output: Uint8Array[] = [];
128
+ let responsesTerminal = false;
129
+ for (const frame of frames) {
130
+ const payload = sseDataPayload(decoder.decode(frame.block));
131
+ const isDone = payload === "[DONE]";
132
+ // Preserve every frame through the first Responses terminal. A [DONE]
133
+ // frame is also preserved when it immediately follows that terminal in
134
+ // the same upstream chunk; every later non-DONE frame is dropped.
135
+ if (!responsesTerminal || isDone) output.push(frame.block, frame.delimiter);
136
+ if (isDone) {
137
+ done = true;
138
+ continue;
139
+ }
140
+ if (!responsesTerminal && payload && terminalStatusFromSsePayload(payload)) {
141
+ responsesTerminal = true;
142
+ }
143
+ }
144
+ if (responsesTerminal) {
145
+ terminal = true;
146
+ framer.dispose();
147
+ }
148
+ return joinSseFrameBytes(output);
149
+ };
150
+
151
+ return {
152
+ feed(chunk) {
153
+ if (disposed || terminal) return new Uint8Array(0);
154
+ return processFrames(framer.feed(chunk));
155
+ },
156
+ finish() {
157
+ if (disposed || terminal) return new Uint8Array(0);
158
+ return framer.finish();
159
+ },
160
+ terminalSeen: () => terminal,
161
+ doneSeen: () => done,
162
+ dispose() {
163
+ if (disposed) return;
164
+ disposed = true;
165
+ framer.dispose();
166
+ },
167
+ };
168
+ }
169
+
98
170
  /**
99
171
  * Relay a passthrough SSE body like relayWithAbort, but convert a MID-STREAM failure (upstream
100
172
  * reset after headers) into a clean terminal: any partial block is closed off, then a synthetic
@@ -110,18 +182,64 @@ export function relaySseWithFailedTail(
110
182
  ): ReadableStream<Uint8Array> {
111
183
  const reader = body.getReader();
112
184
  const encoder = new TextEncoder();
185
+ const terminalBoundary = createSseTerminalOutputBoundary();
186
+ let closed = false;
187
+ const relayChunk = (
188
+ controller: ReadableStreamDefaultController<Uint8Array>,
189
+ value: Uint8Array,
190
+ ): "terminal" | "output" | "buffered" => {
191
+ const outbound = terminalBoundary.feed(value);
192
+ if (outbound.byteLength > 0) controller.enqueue(outbound);
193
+ if (!terminalBoundary.terminalSeen()) return outbound.byteLength > 0 ? "output" : "buffered";
194
+
195
+ // A Responses terminal frame is the protocol boundary. Some compatible
196
+ // gateways leave the HTTP connection open after response.completed, which
197
+ // otherwise leaves Codex waiting forever even though the model turn is done.
198
+ // Preserve through the terminal block only, add the conventional sentinel
199
+ // when there was no real [DONE] data event, then stop reading upstream.
200
+ if (!terminalBoundary.doneSeen()) {
201
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
202
+ }
203
+ closed = true;
204
+ controller.close();
205
+ const reason = "Responses terminal event received";
206
+ // Notify the tee inspection branch as well. It has already received the
207
+ // same terminal-bearing upstream chunk, so its bounded drain records the
208
+ // real terminal and then releases the turn/upstream keep-alive connection.
209
+ onClientGone?.(reason);
210
+ reader.cancel(reason).catch(() => {});
211
+ terminalBoundary.dispose();
212
+ return "terminal";
213
+ };
113
214
  return new ReadableStream<Uint8Array>({
114
215
  async pull(controller) {
115
216
  try {
116
- const { done, value } = await reader.read();
117
- if (done) {
118
- controller.close();
119
- return;
217
+ for (;;) {
218
+ const { done, value } = await reader.read();
219
+ if (done) {
220
+ const tail = terminalBoundary.finish();
221
+ if (tail.byteLength > 0) controller.enqueue(tail);
222
+ terminalBoundary.dispose();
223
+ controller.close();
224
+ return;
225
+ }
226
+ const result = relayChunk(controller, value);
227
+ if (result !== "buffered") return;
120
228
  }
121
- controller.enqueue(value);
122
229
  } catch (err) {
230
+ let partial: Uint8Array = new Uint8Array(0);
231
+ try {
232
+ partial = terminalBoundary.finish();
233
+ } catch {
234
+ // A near-cap ambiguous delimiter tail may itself overflow at EOF.
235
+ // Preserve the original read/framing failure and continue emitting
236
+ // the bounded failed tail instead of letting cleanup throw again.
237
+ }
238
+ terminalBoundary.dispose();
239
+ if (closed) return;
123
240
  const payload = buildFailedTailPayload(err);
124
241
  try {
242
+ if (partial.byteLength > 0) controller.enqueue(partial);
125
243
  // Leading blank line terminates a partial SSE block so the failed frame parses cleanly.
126
244
  controller.enqueue(encoder.encode(`\n\nevent: response.failed\ndata: ${payload}\n\ndata: [DONE]\n\n`));
127
245
  controller.close();
@@ -130,6 +248,7 @@ export function relaySseWithFailedTail(
130
248
  }
131
249
  },
132
250
  cancel(reason) {
251
+ terminalBoundary.dispose();
133
252
  if (onClientGone) onClientGone(reason);
134
253
  else upstream.abort(reason);
135
254
  reader.cancel(reason).catch(() => {});
@@ -137,11 +256,12 @@ export function relaySseWithFailedTail(
137
256
  });
138
257
  }
139
258
 
140
- export function nextSseBlock(buffer: string): { block: string; rest: string } | null {
259
+ export function nextSseBlock(buffer: string): { block: string; delimiter: string; rest: string } | null {
141
260
  const match = buffer.match(/\r?\n\r?\n/);
142
261
  if (!match || match.index === undefined) return null;
143
262
  return {
144
263
  block: buffer.slice(0, match.index),
264
+ delimiter: match[0],
145
265
  rest: buffer.slice(match.index + match[0].length),
146
266
  };
147
267
  }
@@ -245,53 +365,52 @@ export function trackSseForRequestLog(
245
365
  onFirstOutput?: () => void,
246
366
  ): ReadableStream<Uint8Array> {
247
367
  const reader = body.getReader();
248
- const decoder = new TextDecoder();
249
- let buffer = "";
250
368
  let terminalReported = false;
251
- const reportFirstOutput = createFirstOutputReporter(onFirstOutput);
369
+ let cancelled = false;
252
370
 
253
371
  const reportTerminal = (status: ResponsesTerminalStatus) => {
254
372
  if (terminalReported) return;
255
373
  terminalReported = true;
256
374
  onTerminal(status);
257
375
  };
258
-
259
- const inspectPayload = (payload: string | null) => {
260
- if (!payload) return;
261
- if (logCtx) inspectResponseLogSsePayload(logCtx, payload);
262
- reportFirstOutput.payload(payload);
263
- const status = terminalStatusFromSsePayload(payload);
264
- if (status) reportTerminal(status);
265
- };
266
-
267
- const inspectChunk = (value: Uint8Array) => {
268
- buffer += decoder.decode(value, { stream: true });
269
- let next: { block: string; rest: string } | null;
270
- while ((next = nextSseBlock(buffer))) {
271
- buffer = next.rest;
272
- inspectPayload(sseDataPayload(next.block));
273
- }
274
- };
376
+ // Reuse the byte-bounded inspector so translated responses cannot retain an
377
+ // unterminated upstream frame or parse the same event once per observer.
378
+ const inspector = createSseInspector({
379
+ onTerminal: reportTerminal,
380
+ logCtx,
381
+ onFirstOutput,
382
+ });
275
383
 
276
384
  return new ReadableStream<Uint8Array>({
277
385
  async pull(controller) {
278
386
  try {
279
387
  const { done, value } = await reader.read();
280
388
  if (done) {
281
- buffer += decoder.decode();
282
- if (buffer.trim()) inspectPayload(sseDataPayload(buffer));
283
- if (!terminalReported) reportTerminal("incomplete");
389
+ if (!cancelled) {
390
+ inspector.finish();
391
+ if (!terminalReported) reportTerminal("incomplete");
392
+ }
393
+ inspector.dispose();
284
394
  controller.close();
285
395
  return;
286
396
  }
287
- inspectChunk(value);
397
+ inspector.feed(value);
288
398
  controller.enqueue(value);
289
399
  } catch (err) {
290
- if (!terminalReported) reportTerminal("incomplete");
400
+ // The upstream read rejected: the 200 body died mid-flight. Client
401
+ // cancellation is the caller's separate 499 path, so a cancel-drained
402
+ // pending read (cancelled=true) must not carry the truncation marker.
403
+ if (!cancelled && !terminalReported && logCtx?.activeAttempt) {
404
+ logCtx.activeAttempt.streamAborted = true;
405
+ }
406
+ if (!cancelled && !terminalReported) reportTerminal("incomplete");
407
+ inspector.dispose();
291
408
  try { controller.error(err); } catch { /* already torn down */ }
292
409
  }
293
410
  },
294
411
  cancel(reason) {
412
+ cancelled = true;
413
+ inspector.dispose();
295
414
  onCancel();
296
415
  reader.cancel(reason).catch(() => {});
297
416
  },
@@ -402,38 +521,23 @@ export function relaySseWithHeartbeat(
402
521
  ): ReadableStream<Uint8Array> | null {
403
522
  if (!body) return null;
404
523
  const reader = body.getReader();
405
- const decoder = new TextDecoder();
406
524
  const heartbeat = new TextEncoder().encode(": opencodex keepalive\n\n");
407
525
  let timer: ReturnType<typeof setInterval> | undefined;
408
526
  let closed = false;
409
527
  let clientCancelled = false;
410
528
  let terminalReported = false;
411
- let buffer = "";
412
529
 
413
530
  const reportTerminal = (status: ResponsesTerminalStatus) => {
414
531
  if (terminalReported || clientCancelled || closed) return;
415
532
  terminalReported = true;
416
533
  onTerminal?.(status);
417
534
  };
418
-
419
- const inspectPayload = (payload: string | null) => {
420
- if (!payload) return;
421
- const status = terminalStatusFromSsePayload(payload);
422
- if (status) reportTerminal(status);
423
- };
424
-
425
- const inspectChunk = (value: Uint8Array) => {
426
- buffer += decoder.decode(value, { stream: true });
427
- let next: { block: string; rest: string } | null;
428
- while ((next = nextSseBlock(buffer))) {
429
- buffer = next.rest;
430
- inspectPayload(sseDataPayload(next.block));
431
- }
432
- };
535
+ const inspector = createSseInspector({ onTerminal: reportTerminal });
433
536
 
434
537
  const cleanup = () => {
435
538
  if (closed) return;
436
539
  closed = true;
540
+ inspector.dispose();
437
541
  if (timer) clearInterval(timer);
438
542
  timer = undefined;
439
543
  options?.onDone?.();
@@ -455,14 +559,13 @@ export function relaySseWithHeartbeat(
455
559
  try {
456
560
  const { done, value } = await reader.read();
457
561
  if (done) {
458
- buffer += decoder.decode();
459
- if (buffer.trim()) inspectPayload(sseDataPayload(buffer));
562
+ inspector.finish();
460
563
  if (!terminalReported && !clientCancelled) reportTerminal("incomplete");
461
564
  cleanup();
462
565
  controller.close();
463
566
  return;
464
567
  }
465
- inspectChunk(value);
568
+ inspector.feed(value);
466
569
  controller.enqueue(value);
467
570
  } catch (err) {
468
571
  if (!clientCancelled) reportTerminal("incomplete");
@@ -500,7 +603,20 @@ export type SseInspectorHandlers = {
500
603
  onTerminal?: (status: ResponsesTerminalStatus, httpStatusOverride?: number) => void;
501
604
  logCtx?: RequestLogContext;
502
605
  onCompletedResponse?: (response: { id?: unknown; output?: unknown; status?: unknown }) => void;
606
+ /**
607
+ * Every parsed SSE payload, delivered BEFORE any onCompletedResponse derived from that same
608
+ * payload. A caller that must decide on the whole turn -- not just its terminal snapshot --
609
+ * needs to see the incremental events, because a stream can announce an item and then close
610
+ * with an empty `output`.
611
+ */
612
+ onParsedPayload?: (payload: unknown) => void;
503
613
  onFirstOutput?: () => void;
614
+ /**
615
+ * Provider-scoped compatibility: persist the completed snapshot under the
616
+ * first response id exposed to the client when an upstream changes ids
617
+ * between `response.created` and `response.completed`.
618
+ */
619
+ pinCompletedResponseIdToFirstSeen?: boolean;
504
620
  };
505
621
 
506
622
  type CompletedOutputItem = { item: unknown; sourceBytes: number };
@@ -530,17 +646,6 @@ function delimiterLengthAt(
530
646
  return byteAt(index + 3) === 10 ? 4 : 0;
531
647
  }
532
648
 
533
- function joinedBytes(slices: readonly Uint8Array[], byteLength: number): Uint8Array {
534
- if (slices.length === 1 && slices[0]!.byteLength === byteLength) return slices[0]!;
535
- const joined = new Uint8Array(byteLength);
536
- let offset = 0;
537
- for (const slice of slices) {
538
- joined.set(slice, offset);
539
- offset += slice.byteLength;
540
- }
541
- return joined;
542
- }
543
-
544
649
  /**
545
650
  * Per-chunk SSE inspection state machine shared by consumeForInspection,
546
651
  * consumeForResponseLogMetadata, and the eager bounded relay (relay-eager.ts).
@@ -561,8 +666,8 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
561
666
  let reported = false;
562
667
  let sawTerminal = false;
563
668
  let disposed = false;
564
- let delimiterTail = new Uint8Array(0);
565
- let candidateSlices: Uint8Array[] = [];
669
+ let delimiterTail: Uint8Array = new Uint8Array(0);
670
+ let candidate: Uint8Array = new Uint8Array(0);
566
671
  let candidateBytes = 0;
567
672
  let discardingOversizedFrame = false;
568
673
  const reportFirstOutput = createFirstOutputReporter(handlers.onFirstOutput);
@@ -572,10 +677,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
572
677
  : null;
573
678
  let aggregateItemBytes = 0;
574
679
  let reconstructionTainted = false;
680
+ let firstResponseId: string | undefined;
575
681
 
576
682
  const clearFrameState = (): void => {
577
683
  delimiterTail = new Uint8Array(0);
578
- candidateSlices = [];
684
+ candidate = new Uint8Array(0);
579
685
  candidateBytes = 0;
580
686
  discardingOversizedFrame = false;
581
687
  };
@@ -592,6 +698,31 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
592
698
  decoder = null;
593
699
  clearFrameState();
594
700
  clearCompletedItems();
701
+ firstResponseId = undefined;
702
+ };
703
+
704
+ const ensureCandidateCapacity = (requiredBytes: number): void => {
705
+ if (candidate.byteLength >= requiredBytes) return;
706
+ let capacity = candidate.byteLength === 0
707
+ ? Math.min(MAX_INSPECTION_SSE_FRAME_BYTES, Math.max(requiredBytes, 4096))
708
+ : candidate.byteLength;
709
+ while (capacity < requiredBytes) {
710
+ capacity = Math.min(
711
+ MAX_INSPECTION_SSE_FRAME_BYTES,
712
+ Math.max(requiredBytes, capacity * 2),
713
+ );
714
+ }
715
+ const grown = new Uint8Array(capacity);
716
+ if (candidateBytes > 0) grown.set(candidate.subarray(0, candidateBytes));
717
+ candidate = grown;
718
+ };
719
+
720
+ const takeCandidate = (): Uint8Array => {
721
+ if (candidateBytes === 0) return new Uint8Array(0);
722
+ const frame = candidate.slice(0, candidateBytes);
723
+ candidate = new Uint8Array(0);
724
+ candidateBytes = 0;
725
+ return frame;
595
726
  };
596
727
 
597
728
  const retainCandidateSlice = (slice: Uint8Array): void => {
@@ -602,7 +733,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
602
733
  Math.min(nextBytes, MAX_INSPECTION_SSE_FRAME_BYTES),
603
734
  );
604
735
  if (nextBytes > MAX_INSPECTION_SSE_FRAME_BYTES) {
605
- candidateSlices = [];
736
+ candidate = new Uint8Array(0);
606
737
  candidateBytes = 0;
607
738
  discardingOversizedFrame = true;
608
739
  inspectionCounters.frameCapOverflows += 1;
@@ -612,10 +743,8 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
612
743
  reconstructionTainted = true;
613
744
  return;
614
745
  }
615
- // `subarray()` aliases the upstream chunk's backing buffer. Copy only the
616
- // live candidate bytes so a tiny trailing frame cannot pin a multi-MiB
617
- // chunk whose preceding frames have already been consumed.
618
- candidateSlices.push(slice.slice());
746
+ ensureCandidateCapacity(nextBytes);
747
+ candidate.set(slice, candidateBytes);
619
748
  candidateBytes = nextBytes;
620
749
  };
621
750
 
@@ -664,6 +793,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
664
793
  if (!reported && handlers.logCtx) {
665
794
  inspectResponseLogSsePayloadParsed(handlers.logCtx, payload, parsed);
666
795
  }
796
+ // Before any terminal handling: a consumer deciding on the whole turn must observe this
797
+ // payload even when the terminal snapshot that follows no longer mentions it.
798
+ if (handlers.onParsedPayload && parsed !== undefined) {
799
+ try { handlers.onParsedPayload(parsed); } catch { /* inspection must never throw into the pump */ }
800
+ }
667
801
  reportFirstOutput.parsed(parsed);
668
802
  const status = terminalStatusFromParsed(parsed);
669
803
  if (status) sawTerminal = true;
@@ -686,6 +820,17 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
686
820
  const parsedEvent = parsed && typeof parsed === "object" && !Array.isArray(parsed)
687
821
  ? parsed as ParsedSseEvent
688
822
  : null;
823
+ const responseRecord = parsedEvent
824
+ && typeof parsedEvent.response === "object"
825
+ && parsedEvent.response !== null
826
+ && !Array.isArray(parsedEvent.response)
827
+ ? parsedEvent.response as { id?: unknown }
828
+ : null;
829
+ if (handlers.pinCompletedResponseIdToFirstSeen
830
+ && responseRecord
831
+ && typeof responseRecord.id === "string") {
832
+ firstResponseId ??= responseRecord.id;
833
+ }
689
834
  const doneItem = parsedEvent?.type === "response.output_item.done" ? parsedEvent.item : undefined;
690
835
  if (parsedEvent
691
836
  && doneItem !== undefined
@@ -700,6 +845,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
700
845
 
701
846
  let response = completedResponseFromParsedEvent(parsedEvent);
702
847
  if (response) {
848
+ if (handlers.pinCompletedResponseIdToFirstSeen
849
+ && firstResponseId !== undefined
850
+ && response.id !== firstResponseId) {
851
+ response = { ...response, id: firstResponseId };
852
+ }
703
853
  // Authoritative output is a NON-EMPTY ARRAY only. Anything else
704
854
  // (missing, null, scalar, object) keeps the historical backfill
705
855
  // behavior so a malformed terminal cannot reach rememberResponseState
@@ -735,9 +885,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
735
885
  return;
736
886
  }
737
887
  const sourceBytes = candidateBytes;
738
- const frame = joinedBytes(candidateSlices, sourceBytes);
739
- candidateSlices = [];
740
- candidateBytes = 0;
888
+ const frame = takeCandidate();
741
889
  if (reported && !handlers.onCompletedResponse) return;
742
890
  const decoded = decoder!.decode(frame);
743
891
  scanPayload(sseDataPayload(decoded), sourceBytes);
@@ -794,7 +942,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
794
942
  delimiterTail = new Uint8Array(0);
795
943
  if (!discardingOversizedFrame && candidateBytes > 0 && !reported) {
796
944
  const sourceBytes = candidateBytes;
797
- const decoded = decoder!.decode(joinedBytes(candidateSlices, sourceBytes));
945
+ const decoded = decoder!.decode(takeCandidate());
798
946
  scanPayload(decoded.trim() ? sseDataPayload(decoded) : null, sourceBytes);
799
947
  }
800
948
  } finally {
@@ -815,6 +963,10 @@ export type InspectionConsumerOptions = {
815
963
  drainBounds?: Partial<InspectionDrainBounds>;
816
964
  upstream?: AbortController;
817
965
  now?: () => number;
966
+ /** Forward provider-scoped response-id pinning to the owned inspector. */
967
+ pinCompletedResponseIdToFirstSeen?: boolean;
968
+ /** Observe every parsed SSE payload on the inspection side; see SseInspectorHandlers. */
969
+ onParsedPayload?: (payload: unknown) => void;
818
970
  /** Test seam for proving both public consumers dispose their owned inspector. */
819
971
  inspectorFactory?: (handlers: SseInspectorHandlers) => SseInspector;
820
972
  };
@@ -970,7 +1122,9 @@ export function consumeForInspection(
970
1122
  onTerminal,
971
1123
  logCtx,
972
1124
  onCompletedResponse,
1125
+ onParsedPayload: options?.onParsedPayload,
973
1126
  onFirstOutput,
1127
+ pinCompletedResponseIdToFirstSeen: options?.pinCompletedResponseIdToFirstSeen,
974
1128
  });
975
1129
  startBoundedInspectionPump({
976
1130
  ...options,
@@ -993,6 +1147,10 @@ export function consumeForInspection(
993
1147
  if (logCtx) {
994
1148
  logCtx.transportPhase = "mid_stream";
995
1149
  logCtx.terminalSource = "synthetic";
1150
+ // A truncated 200 body must not meter as a success the client never
1151
+ // received; the router's equivalent turn carries 502 + streamAborted
1152
+ // (codex-router #139).
1153
+ if (logCtx.activeAttempt) logCtx.activeAttempt.streamAborted = true;
996
1154
  }
997
1155
  onTerminal("failed", 502);
998
1156
  }
@@ -1015,7 +1173,9 @@ export function consumeForResponseLogMetadata(
1015
1173
  const inspector = (options?.inspectorFactory ?? createSseInspector)({
1016
1174
  logCtx,
1017
1175
  onCompletedResponse,
1176
+ onParsedPayload: options?.onParsedPayload,
1018
1177
  onFirstOutput,
1178
+ pinCompletedResponseIdToFirstSeen: options?.pinCompletedResponseIdToFirstSeen,
1019
1179
  });
1020
1180
  startBoundedInspectionPump({ ...options, reader, inspector, signal, onDone });
1021
1181
  }