@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
@@ -0,0 +1,621 @@
1
+ /**
2
+ * Provider-opt-in repair for Responses-compatible gateways that return sparse
3
+ * lifecycle snapshots (#893): field backfills for missing canonical fields,
4
+ * AND lifecycle event injection so Codex clients actually commit the turn.
5
+ *
6
+ * Field-repair semantics (snapshot fields, item/part backfills, retention
7
+ * bounds) are adopted from PR #928 (0xWinner98) with attribution. The
8
+ * lifecycle-completion layer is new: #928's exact-issue test expects no
9
+ * `output_item.done` and a terminal `output: []` — normalization without
10
+ * commitment, which the canonical bridge contract (src/bridge.ts) shows is
11
+ * not enough for Codex to commit the message.
12
+ *
13
+ * Design:
14
+ * - One stateful tracker per stream. Existing upstream values are always
15
+ * authoritative; only absent or structurally invalid fields are backfilled.
16
+ * - Event injection happens only for items PROVEN open at a terminal event
17
+ * (never for content the gateway closed itself).
18
+ * - Ambiguous, gapped, malformed, oversized, or contradictory shapes taint
19
+ * the tracker: no injections and no output reconstruction afterwards
20
+ * (fail closed; explicit `output: []` from the gateway stays authoritative).
21
+ */
22
+
23
+ import type { TranslatorBudget } from "../lib/translator-budget";
24
+ import {
25
+ MAX_COMPLETED_OUTPUT_ITEMS,
26
+ MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES,
27
+ } from "./relay";
28
+ import { sseDataPayload, type SseBlockRewrite } from "./sse-payload-rewrite";
29
+
30
+ const RESPONSE_EVENT_STATUSES: Readonly<Record<string, string>> = {
31
+ "response.created": "in_progress",
32
+ "response.in_progress": "in_progress",
33
+ "response.completed": "completed",
34
+ "response.failed": "failed",
35
+ "response.incomplete": "incomplete",
36
+ "response.queued": "queued",
37
+ };
38
+
39
+ type RequestDefaults = {
40
+ parallelToolCalls: boolean;
41
+ toolChoice: unknown;
42
+ tools: unknown[];
43
+ };
44
+
45
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
46
+ return !!value && typeof value === "object" && !Array.isArray(value);
47
+ }
48
+
49
+ function isStructurallyValidToolChoice(value: unknown): boolean {
50
+ return (typeof value === "string" && value.trim().length > 0)
51
+ || (isPlainObject(value) && typeof value.type === "string" && value.type.trim().length > 0);
52
+ }
53
+
54
+ function requestDefaults(requestBody: unknown): RequestDefaults {
55
+ const request = isPlainObject(requestBody) ? requestBody : {};
56
+ return {
57
+ parallelToolCalls: typeof request.parallel_tool_calls === "boolean"
58
+ ? request.parallel_tool_calls
59
+ : true,
60
+ toolChoice: isStructurallyValidToolChoice(request.tool_choice) ? request.tool_choice : "auto",
61
+ tools: Array.isArray(request.tools) ? request.tools : [],
62
+ };
63
+ }
64
+
65
+ function repairOutputTextPart(part: Record<string, unknown>): Record<string, unknown> {
66
+ if (part.type !== "output_text") return part;
67
+ const needsText = typeof part.text !== "string";
68
+ const needsAnnotations = !Array.isArray(part.annotations);
69
+ if (!needsText && !needsAnnotations) return part;
70
+ return {
71
+ ...part,
72
+ ...(needsText ? { text: "" } : {}),
73
+ ...(needsAnnotations ? { annotations: [] } : {}),
74
+ };
75
+ }
76
+
77
+ function repairSummaryPart(part: Record<string, unknown>): Record<string, unknown> {
78
+ if (part.type !== "summary_text" || typeof part.text === "string") return part;
79
+ return { ...part, text: "" };
80
+ }
81
+
82
+ function repairOutputItem(
83
+ item: Record<string, unknown>,
84
+ inferredStatus?: string,
85
+ ): Record<string, unknown> {
86
+ let repaired = item;
87
+ let changed = false;
88
+
89
+ if (item.type === "reasoning") {
90
+ const rawSummary = item.summary;
91
+ const summary = Array.isArray(rawSummary)
92
+ ? rawSummary.map((part) => isPlainObject(part) ? repairSummaryPart(part) : part)
93
+ : [];
94
+ changed = !Array.isArray(rawSummary)
95
+ || summary.some((part, index) => part !== rawSummary[index]);
96
+ if (changed) repaired = { ...repaired, summary };
97
+ } else if (item.type === "message") {
98
+ const rawContent = item.content;
99
+ const content = Array.isArray(rawContent)
100
+ ? rawContent.map((part) => isPlainObject(part) ? repairOutputTextPart(part) : part)
101
+ : [];
102
+ changed = !Array.isArray(rawContent)
103
+ || content.some((part, index) => part !== rawContent[index]);
104
+ // Responses output-message roles are the literal "assistant"; input roles are invalid here.
105
+ changed = changed || item.role !== "assistant";
106
+ if (changed) repaired = { ...repaired, content, role: "assistant" };
107
+ }
108
+
109
+ if (inferredStatus && (typeof repaired.status !== "string" || repaired.status.trim().length === 0)) {
110
+ repaired = { ...repaired, status: inferredStatus };
111
+ }
112
+ return repaired;
113
+ }
114
+
115
+ function repairResponseSnapshot(
116
+ response: Record<string, unknown>,
117
+ defaultStatus: string,
118
+ defaults: RequestDefaults,
119
+ reconstructedOutput?: Record<string, unknown>[],
120
+ ): Record<string, unknown> {
121
+ const repaired = { ...response };
122
+ let changed = false;
123
+ const effectiveResponseStatus = typeof response.status === "string" && response.status.trim().length > 0
124
+ ? response.status
125
+ : defaultStatus;
126
+ const outputStatus = effectiveResponseStatus === "completed" || effectiveResponseStatus === "incomplete"
127
+ ? effectiveResponseStatus
128
+ : undefined;
129
+
130
+ if (reconstructedOutput) {
131
+ repaired.output = reconstructedOutput;
132
+ changed = true;
133
+ } else if (Array.isArray(repaired.output)) {
134
+ const output = repaired.output.map((item) => {
135
+ if (!isPlainObject(item)) return item;
136
+ const next = repairOutputItem(item, outputStatus);
137
+ changed = changed || next !== item;
138
+ return next;
139
+ });
140
+ if (changed) repaired.output = output;
141
+ }
142
+ if (typeof repaired.parallel_tool_calls !== "boolean") {
143
+ repaired.parallel_tool_calls = defaults.parallelToolCalls;
144
+ changed = true;
145
+ }
146
+ if (!isStructurallyValidToolChoice(repaired.tool_choice)) {
147
+ repaired.tool_choice = defaults.toolChoice;
148
+ changed = true;
149
+ }
150
+ if (!Array.isArray(repaired.tools)) {
151
+ repaired.tools = defaults.tools;
152
+ changed = true;
153
+ }
154
+ if (typeof repaired.status !== "string" || repaired.status.trim().length === 0) {
155
+ repaired.status = defaultStatus;
156
+ changed = true;
157
+ }
158
+
159
+ return changed ? repaired : response;
160
+ }
161
+
162
+ type OpenItem = {
163
+ itemId: string;
164
+ outputIndex: number;
165
+ type: string;
166
+ /** Message/reasoning items get lifecycle injections; other types never do. */
167
+ injectable: boolean;
168
+ /** The gateway opened a content part explicitly (or we injected one). */
169
+ contentPartOpen: boolean;
170
+ /** The gateway sent output_text.done for this item. */
171
+ textDone: boolean;
172
+ /** The gateway sent content_part.done for this item. */
173
+ partDone: boolean;
174
+ text: string;
175
+ item: Record<string, unknown>;
176
+ };
177
+
178
+ /** Open-item retention bounds (#893 review): aggregate, not just per-item. */
179
+ const MAX_OPEN_ITEMS = MAX_COMPLETED_OUTPUT_ITEMS;
180
+ const MAX_OPEN_ITEM_AGGREGATE_TEXT_BYTES = MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES;
181
+
182
+ type RetainedOutputItem = {
183
+ item: Record<string, unknown>;
184
+ sourceBytes: number;
185
+ };
186
+
187
+ function jsonBlock(event: Record<string, unknown>): string {
188
+ return `data: ${JSON.stringify(event)}`;
189
+ }
190
+
191
+ /**
192
+ * Stateful block rewrite: field backfills + lifecycle completion injection.
193
+ * `budget` bounds retained completed items (reconstruction only).
194
+ */
195
+ export function createResponsesSnapshotBlockRewrite(
196
+ requestBody?: unknown,
197
+ budget?: TranslatorBudget,
198
+ ): SseBlockRewrite {
199
+ const defaults = requestDefaults(requestBody);
200
+ const openItems = new Map<number, OpenItem>();
201
+ const completedItems = new Map<number, RetainedOutputItem>();
202
+ let aggregateItemBytes = 0;
203
+ let aggregateOpenTextBytes = 0;
204
+ let tainted = false;
205
+
206
+ const releaseRetained = (): void => {
207
+ if (aggregateItemBytes > 0) {
208
+ budget?.releaseRetained(aggregateItemBytes, { kind: "retained_collectors" });
209
+ }
210
+ completedItems.clear();
211
+ openItems.clear();
212
+ aggregateItemBytes = 0;
213
+ aggregateOpenTextBytes = 0;
214
+ tainted = false;
215
+ };
216
+
217
+ const taintAndRelease = (): void => {
218
+ // Fail closed means stop RETAINING too: open state and charged collectors
219
+ // are released immediately, and no further state accumulates (#893 review).
220
+ if (aggregateItemBytes > 0) {
221
+ budget?.releaseRetained(aggregateItemBytes, { kind: "retained_collectors" });
222
+ }
223
+ completedItems.clear();
224
+ openItems.clear();
225
+ aggregateItemBytes = 0;
226
+ aggregateOpenTextBytes = 0;
227
+ tainted = true;
228
+ };
229
+
230
+ /** Drop one open item and refund its accumulated text from the aggregate. */
231
+ const closeOpenItem = (index: number): void => {
232
+ const open = openItems.get(index);
233
+ if (!open) return;
234
+ aggregateOpenTextBytes -= Buffer.byteLength(open.text, "utf8");
235
+ openItems.delete(index);
236
+ };
237
+
238
+ const retainCompletedItem = (index: number, item: Record<string, unknown>): void => {
239
+ if (tainted) return; // fail closed means stop retaining (#893 review)
240
+ const sourceBytes = Buffer.byteLength(JSON.stringify(item), "utf8");
241
+ const previous = completedItems.get(index);
242
+ if (sourceBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES) {
243
+ if (previous) {
244
+ completedItems.delete(index);
245
+ aggregateItemBytes -= previous.sourceBytes;
246
+ budget?.releaseRetained(previous.sourceBytes, { kind: "retained_collectors" });
247
+ }
248
+ taintAndRelease();
249
+ return;
250
+ }
251
+ const retainedDelta = sourceBytes - (previous?.sourceBytes ?? 0);
252
+ if (retainedDelta > 0) {
253
+ budget?.chargeRetained(retainedDelta, { kind: "retained_collectors" });
254
+ } else if (retainedDelta < 0) {
255
+ budget?.releaseRetained(-retainedDelta, { kind: "retained_collectors" });
256
+ }
257
+ completedItems.set(index, { item, sourceBytes });
258
+ aggregateItemBytes += retainedDelta;
259
+ while (completedItems.size > MAX_COMPLETED_OUTPUT_ITEMS
260
+ || aggregateItemBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES) {
261
+ let highestIndex = -1;
262
+ for (const retainedIndex of completedItems.keys()) {
263
+ if (retainedIndex > highestIndex) highestIndex = retainedIndex;
264
+ }
265
+ const evicted = completedItems.get(highestIndex);
266
+ if (!evicted) break;
267
+ completedItems.delete(highestIndex);
268
+ aggregateItemBytes -= evicted.sourceBytes;
269
+ budget?.releaseRetained(evicted.sourceBytes, { kind: "retained_collectors" });
270
+ taintAndRelease();
271
+ return;
272
+ }
273
+ };
274
+
275
+ const completedItemSnapshot = (open: OpenItem): Record<string, unknown> => {
276
+ if (open.type === "message") {
277
+ return repairOutputItem({
278
+ ...open.item,
279
+ status: "completed",
280
+ role: "assistant",
281
+ content: [{ type: "output_text", text: open.text, annotations: [] }],
282
+ }, "completed");
283
+ }
284
+ return repairOutputItem({ ...open.item, status: "completed" }, "completed");
285
+ };
286
+
287
+ const rewrite: SseBlockRewrite = (block: string): readonly string[] => {
288
+ const payload = sseDataPayload(block);
289
+ if (payload === null) return [block];
290
+ let event: unknown;
291
+ try {
292
+ event = JSON.parse(payload);
293
+ } catch {
294
+ return [block];
295
+ }
296
+ if (!isPlainObject(event)) return [block];
297
+ const type = typeof event.type === "string" ? event.type : "";
298
+ let nextEvent: Record<string, unknown> = event;
299
+ let changed = false;
300
+ const outputIndex = Number.isInteger(event.output_index) && (event.output_index as number) >= 0
301
+ ? event.output_index as number
302
+ : undefined;
303
+ const itemId = typeof event.item_id === "string" ? event.item_id : undefined;
304
+
305
+ // --- item lifecycle tracking + field backfills -------------------------
306
+ if (type === "response.output_item.added" && isPlainObject(event.item)) {
307
+ const itemType = typeof event.item.type === "string" ? event.item.type : "";
308
+ const id = typeof event.item.id === "string" ? event.item.id : undefined;
309
+ if (outputIndex === undefined || !id) {
310
+ taintAndRelease();
311
+ } else {
312
+ if (openItems.has(outputIndex)) taintAndRelease(); // contradictory reuse of an open index
313
+ if (openItems.size >= MAX_OPEN_ITEMS) taintAndRelease(); // aggregate retention bound
314
+ // Unsupported types (function_call, …) reserve their index but are
315
+ // never injected — a sparse gateway that leaves one open blocks only
316
+ // the terminal reconstruction, not message repair (#893 review).
317
+ const injectable = itemType === "message" || itemType === "reasoning";
318
+ if (!tainted) {
319
+ openItems.set(outputIndex, {
320
+ itemId: id,
321
+ outputIndex,
322
+ type: itemType,
323
+ injectable,
324
+ contentPartOpen: false,
325
+ textDone: false,
326
+ partDone: false,
327
+ text: "",
328
+ item: event.item,
329
+ });
330
+ }
331
+ }
332
+ const item = repairOutputItem(event.item, "in_progress");
333
+ if (item !== event.item) {
334
+ nextEvent = { ...nextEvent, item };
335
+ changed = true;
336
+ }
337
+ }
338
+
339
+ if (type === "response.output_item.done" && !isPlainObject(event.item)) {
340
+ taintAndRelease();
341
+ }
342
+
343
+ if (type === "response.output_item.done" && isPlainObject(event.item)) {
344
+ const item = repairOutputItem(event.item, "completed");
345
+ if (item !== event.item) {
346
+ nextEvent = { ...nextEvent, item };
347
+ changed = true;
348
+ }
349
+ // Identity correlation: a done event only closes the tracked item when
350
+ // id AND type agree — a mismatched done is a contradictory stream and
351
+ // must go fail-closed rather than close/reconstruct the wrong item.
352
+ const tracked = outputIndex !== undefined ? openItems.get(outputIndex) : undefined;
353
+ const doneId = typeof event.item.id === "string" ? event.item.id : undefined;
354
+ const doneType = typeof event.item.type === "string" ? event.item.type : undefined;
355
+ if (tracked && (doneId !== tracked.itemId || doneType !== tracked.type)) {
356
+ taintAndRelease();
357
+ return [changed ? jsonBlock(nextEvent) : block];
358
+ }
359
+ if (outputIndex !== undefined && typeof item.type === "string" && item.type.trim().length > 0) {
360
+ closeOpenItem(outputIndex);
361
+ retainCompletedItem(outputIndex, item);
362
+ } else {
363
+ taintAndRelease();
364
+ }
365
+ }
366
+
367
+ if ((type === "response.content_part.added" || type === "response.content_part.done")
368
+ && isPlainObject(event.part)) {
369
+ if (outputIndex !== undefined) {
370
+ const open = openItems.get(outputIndex);
371
+ // A PRESENT-but-mismatched item_id is contradictory lifecycle evidence,
372
+ // exactly like output_item.done and output_text.done: the stream is
373
+ // telling us our identity model for this index is wrong. Merely
374
+ // ignoring it left the item open and let the terminal fabricate a full
375
+ // closure sequence (content_part.added → output_text.done →
376
+ // content_part.done → output_item.done) on top of a stream we do not
377
+ // understand. Go fail-closed instead. An OMITTED item_id stays
378
+ // legitimate and is still correlated by output_index.
379
+ if (open && itemId !== undefined && itemId !== open.itemId) {
380
+ taintAndRelease();
381
+ return [changed ? jsonBlock(nextEvent) : block];
382
+ }
383
+ // Correlate by item_id when present: a mismatched event must not
384
+ // mutate (or suppress injections for) the tracked item (#893 review).
385
+ if (open && (itemId === undefined || itemId === open.itemId)) {
386
+ if (type === "response.content_part.added") open.contentPartOpen = true;
387
+ else open.partDone = true;
388
+ }
389
+ }
390
+ const part = repairOutputTextPart(event.part);
391
+ if (part !== event.part) {
392
+ nextEvent = { ...nextEvent, part };
393
+ changed = true;
394
+ }
395
+ }
396
+
397
+ if ((type === "response.reasoning_summary_part.added"
398
+ || type === "response.reasoning_summary_part.done") && isPlainObject(event.part)) {
399
+ const part = repairSummaryPart(event.part);
400
+ if (part !== event.part) {
401
+ nextEvent = { ...nextEvent, part };
402
+ changed = true;
403
+ }
404
+ }
405
+
406
+ if ((type === "response.output_text.delta" || type === "response.output_text.done")
407
+ && !Array.isArray(event.logprobs)) {
408
+ nextEvent = { ...nextEvent, logprobs: [] };
409
+ changed = true;
410
+ }
411
+ if (type === "response.output_text.delta" && typeof event.delta === "string" && outputIndex !== undefined) {
412
+ const open = openItems.get(outputIndex);
413
+ // Same identity contract as the *.done terminals: a present-but-foreign
414
+ // item_id on a tracked index means our model of this index is wrong, and
415
+ // reconstructing from the text we DID accept would ship a message the
416
+ // upstream never assembled that way.
417
+ if (open && itemId !== undefined && itemId !== open.itemId) {
418
+ taintAndRelease();
419
+ return [changed ? jsonBlock(nextEvent) : block];
420
+ }
421
+ if (open && (itemId === undefined || itemId === open.itemId)) {
422
+ const deltaBytes = Buffer.byteLength(event.delta, "utf8");
423
+ open.text += event.delta;
424
+ aggregateOpenTextBytes += deltaBytes;
425
+ // Unbounded text accumulation is a retention hole (#893 review):
426
+ // overshoot per-item or aggregate caps and the stream goes fail-closed.
427
+ if (Buffer.byteLength(open.text, "utf8") > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES
428
+ || aggregateOpenTextBytes > MAX_OPEN_ITEM_AGGREGATE_TEXT_BYTES) {
429
+ taintAndRelease();
430
+ }
431
+ }
432
+ }
433
+ if (type === "response.output_text.done") {
434
+ if (outputIndex !== undefined) {
435
+ const open = openItems.get(outputIndex);
436
+ // Identity correlation, same contract as output_item.done above: a
437
+ // text-done carrying a DIFFERENT item_id for a tracked index is a
438
+ // contradictory stream. Silently ignoring it used to leave the item
439
+ // open, so the terminal then synthesized a second output_text.done and
440
+ // output_item.done — a double close built on a stream we do not
441
+ // understand (#1025 review blocker 2). Go fail-closed instead: forward
442
+ // the block untouched and stop injecting for the rest of the stream.
443
+ if (open && itemId !== undefined && itemId !== open.itemId) {
444
+ taintAndRelease();
445
+ return [changed ? jsonBlock(nextEvent) : block];
446
+ }
447
+ if (open && (itemId === undefined || itemId === open.itemId)) {
448
+ open.textDone = true;
449
+ if (typeof event.text === "string") {
450
+ // Replacement must keep the aggregate honest and bounded, the
451
+ // same as delta accumulation (#893 review).
452
+ const previousBytes = Buffer.byteLength(open.text, "utf8");
453
+ const nextBytes = Buffer.byteLength(event.text, "utf8");
454
+ open.text = event.text;
455
+ aggregateOpenTextBytes += nextBytes - previousBytes;
456
+ if (nextBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES
457
+ || aggregateOpenTextBytes > MAX_OPEN_ITEM_AGGREGATE_TEXT_BYTES) {
458
+ taintAndRelease();
459
+ }
460
+ }
461
+ }
462
+ }
463
+ if (typeof event.text !== "string") {
464
+ nextEvent = { ...nextEvent, text: "" };
465
+ changed = true;
466
+ }
467
+ }
468
+
469
+ // --- lifecycle response snapshots --------------------------------------
470
+ const responseStatus = Object.prototype.hasOwnProperty.call(RESPONSE_EVENT_STATUSES, type)
471
+ ? RESPONSE_EVENT_STATUSES[type]
472
+ : undefined;
473
+ const isTerminal = type === "response.completed"
474
+ || type === "response.failed"
475
+ || type === "response.incomplete";
476
+
477
+ if (responseStatus && isPlainObject(event.response)) {
478
+ // Terminal output reconstruction stays in the injection layer below;
479
+ // here the snapshot only gets field backfills.
480
+ const response = repairResponseSnapshot(event.response, responseStatus, defaults);
481
+ if (response !== event.response) {
482
+ nextEvent = { ...nextEvent, response };
483
+ changed = true;
484
+ }
485
+ }
486
+
487
+ // --- lifecycle completion injection ------------------------------------
488
+ // Only response.completed justifies synthesized closing events: a failed
489
+ // or incomplete terminal must never fabricate completed output (#893 review).
490
+ const isCompletedTerminal = type === "response.completed";
491
+ const out: string[] = [];
492
+ if (!tainted) {
493
+ // A text delta for an item whose content part was never opened needs the
494
+ // opening event first, or Codex never binds the text to a committed part.
495
+ if (type === "response.output_text.delta" && outputIndex !== undefined) {
496
+ const open = openItems.get(outputIndex);
497
+ if (open && open.type === "message" && !open.contentPartOpen) {
498
+ out.push(jsonBlock({
499
+ type: "response.content_part.added",
500
+ item_id: open.itemId,
501
+ output_index: open.outputIndex,
502
+ content_index: 0,
503
+ part: { type: "output_text", text: "", annotations: [] },
504
+ }));
505
+ open.contentPartOpen = true;
506
+ }
507
+ }
508
+
509
+ if (isCompletedTerminal && openItems.size > 0) {
510
+ const closing = [...openItems.values()].sort((a, b) => a.outputIndex - b.outputIndex);
511
+ for (const open of closing) {
512
+ if (open.injectable && open.type === "message") {
513
+ if (!open.contentPartOpen) {
514
+ out.push(jsonBlock({
515
+ type: "response.content_part.added",
516
+ item_id: open.itemId,
517
+ output_index: open.outputIndex,
518
+ content_index: 0,
519
+ part: { type: "output_text", text: "", annotations: [] },
520
+ }));
521
+ open.contentPartOpen = true;
522
+ }
523
+ if (!open.textDone) {
524
+ out.push(jsonBlock({
525
+ type: "response.output_text.done",
526
+ item_id: open.itemId,
527
+ output_index: open.outputIndex,
528
+ content_index: 0,
529
+ logprobs: [],
530
+ text: open.text,
531
+ }));
532
+ open.textDone = true;
533
+ }
534
+ if (!open.partDone) {
535
+ out.push(jsonBlock({
536
+ type: "response.content_part.done",
537
+ item_id: open.itemId,
538
+ output_index: open.outputIndex,
539
+ content_index: 0,
540
+ part: { type: "output_text", text: open.text, annotations: [] },
541
+ }));
542
+ open.partDone = true;
543
+ }
544
+ }
545
+ if (!open.injectable) continue; // never fabricate completions for other types
546
+ const snapshot = completedItemSnapshot(open);
547
+ out.push(jsonBlock({
548
+ type: "response.output_item.done",
549
+ output_index: open.outputIndex,
550
+ item: snapshot,
551
+ }));
552
+ closeOpenItem(open.outputIndex);
553
+ retainCompletedItem(open.outputIndex, snapshot);
554
+ }
555
+ }
556
+ }
557
+
558
+ // Terminal output reconstruction/canonical backfill: an explicit
559
+ // `output: []` is authoritative; absent or malformed output on a
560
+ // completed terminal becomes the retained items or the canonical empty
561
+ // list (#893 review). Leftover non-injectable open items block
562
+ // reconstruction only, not the message closing above.
563
+ if (isCompletedTerminal && !tainted && isPlainObject(nextEvent.response)) {
564
+ const response = nextEvent.response;
565
+ const outputValue = (response as Record<string, unknown>).output;
566
+ const outputExplicitArray = Array.isArray(outputValue);
567
+ if (!outputExplicitArray) {
568
+ const injectableOpen = [...openItems.values()].filter(open => open.injectable);
569
+ const nonInjectableOpen = [...openItems.values()].filter(open => !open.injectable);
570
+ if (completedItems.size > 0 && injectableOpen.length === 0 && nonInjectableOpen.length === 0) {
571
+ const ordered = [...completedItems.entries()].sort(([left], [right]) => left - right);
572
+ if (ordered.every(([index], position) => index === position)) {
573
+ nextEvent = {
574
+ ...nextEvent,
575
+ response: { ...response, output: ordered.map(([, retained]) => retained.item) },
576
+ };
577
+ changed = true;
578
+ } else {
579
+ // A gap means at least one completed item is missing. Never compact
580
+ // later indexes into a shorter array that only appears complete.
581
+ tainted = true;
582
+ }
583
+ } else if (completedItems.size === 0 && openItems.size === 0) {
584
+ nextEvent = { ...nextEvent, response: { ...response, output: [] } };
585
+ changed = true;
586
+ }
587
+ }
588
+ }
589
+
590
+ out.push(changed ? jsonBlock(nextEvent) : block);
591
+ if (isTerminal) releaseRetained();
592
+ return out;
593
+ };
594
+ // Relays call this on every teardown path (terminal, EOF, cancel, error):
595
+ // retained collectors and open-item state never outlive the stream.
596
+ rewrite.dispose = releaseRetained;
597
+ return rewrite;
598
+ }
599
+
600
+ /** Repair a non-streaming Responses JSON object without changing raw inspection state. */
601
+ export function repairResponsesSnapshotJson(payload: string, requestBody?: unknown): string {
602
+ let response: unknown;
603
+ try {
604
+ response = JSON.parse(payload);
605
+ } catch {
606
+ return payload;
607
+ }
608
+ if (!isPlainObject(response)) return payload;
609
+ // Canonical output for non-stream completed responses: absent or malformed
610
+ // output becomes the canonical empty list; explicit arrays stay authoritative.
611
+ if (!Array.isArray(response.output)) {
612
+ const repaired = repairResponseSnapshot({ ...response, output: [] }, "completed", requestDefaults(requestBody));
613
+ return JSON.stringify(repaired);
614
+ }
615
+ const repaired = repairResponseSnapshot(response, "completed", requestDefaults(requestBody));
616
+ return repaired === response ? payload : JSON.stringify(repaired);
617
+ }
618
+
619
+ export function hasResponsesSnapshotRepair(enabled: boolean | undefined): enabled is true {
620
+ return enabled === true;
621
+ }