@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,338 @@
1
+ /**
2
+ * Client-facing repair for GitHub Copilot's `vscode-chat` Responses stream.
3
+ *
4
+ * Copilot can rotate opaque response/item ids between lifecycle events, expose
5
+ * provider-private reasoning ciphertext, and attach per-delta obfuscation
6
+ * padding while the authoritative complete tool input arrives on `.done`.
7
+ * Stock Responses clients cannot reconcile that dialect. This stateful block
8
+ * rewrite emits one coherent Responses SSE stream while the inspection branch
9
+ * keeps the raw upstream snapshot for provider replay.
10
+ */
11
+ import {
12
+ TranslatorBudgetExceededError,
13
+ type TranslatorBudget,
14
+ } from "../lib/translator-budget";
15
+ import {
16
+ replaceSseDataPayload,
17
+ sseDataPayload,
18
+ type SseBlockRewrite,
19
+ } from "./sse-payload-rewrite";
20
+
21
+ const MAX_TRACKED_ITEMS = 256;
22
+ const MAX_TRACKED_DEFERRED_CALLS = 256;
23
+ const RETAINED_STATE_LIMIT_BYTES = 256 * 1024;
24
+
25
+ type JsonRecord = Record<string, unknown>;
26
+
27
+ type TrackedItem = {
28
+ id: string;
29
+ type?: string;
30
+ encryptedReasoning: boolean;
31
+ };
32
+
33
+ type DeferredCallKind = "function" | "custom";
34
+
35
+ function isRecord(value: unknown): value is JsonRecord {
36
+ return typeof value === "object" && value !== null && !Array.isArray(value);
37
+ }
38
+
39
+ function outputIndexOf(value: unknown): number | undefined {
40
+ return typeof value === "number" && Number.isInteger(value) && value >= 0
41
+ ? value
42
+ : undefined;
43
+ }
44
+
45
+ function byteLength(value: unknown): number {
46
+ return Buffer.byteLength(JSON.stringify(value), "utf8");
47
+ }
48
+
49
+ function blockNewline(block: string): "\r\n" | "\n" {
50
+ return block.includes("\r\n") ? "\r\n" : "\n";
51
+ }
52
+
53
+ /** Keep a named SSE block's `event:` field aligned with its JSON `type`. */
54
+ function withEventName(block: string, eventName: string): string {
55
+ const newline = blockNewline(block);
56
+ const lines = block.split(/\r?\n/);
57
+ let replaced = false;
58
+ const rewritten = lines.flatMap((line) => {
59
+ if (!line.startsWith("event:")) return [line];
60
+ if (replaced) return [];
61
+ replaced = true;
62
+ return [`event: ${eventName}`];
63
+ });
64
+ if (!replaced) {
65
+ const dataIndex = rewritten.findIndex(line => line.startsWith("data:"));
66
+ rewritten.splice(dataIndex >= 0 ? dataIndex : 0, 0, `event: ${eventName}`);
67
+ }
68
+ return rewritten.join(newline);
69
+ }
70
+
71
+ function rewriteJsonBlock(block: string, event: JsonRecord): string {
72
+ const type = typeof event.type === "string" ? event.type : "message";
73
+ return withEventName(replaceSseDataPayload(block, JSON.stringify(event)), type);
74
+ }
75
+
76
+ function syntheticJsonBlock(template: string, event: JsonRecord): string {
77
+ const newline = blockNewline(template);
78
+ const type = typeof event.type === "string" ? event.type : "message";
79
+ return `event: ${type}${newline}data: ${JSON.stringify(event)}`;
80
+ }
81
+
82
+ function callKindForDelta(type: unknown): DeferredCallKind | undefined {
83
+ if (type === "response.function_call_arguments.delta") return "function";
84
+ if (type === "response.custom_tool_call_input.delta") return "custom";
85
+ return undefined;
86
+ }
87
+
88
+ function callKindForDone(type: unknown): DeferredCallKind | undefined {
89
+ if (type === "response.function_call_arguments.done") return "function";
90
+ if (type === "response.custom_tool_call_input.done") return "custom";
91
+ return undefined;
92
+ }
93
+
94
+ function callKey(kind: DeferredCallKind, outputIndex: number): string {
95
+ return `${kind}:${outputIndex}`;
96
+ }
97
+
98
+ function deltaTypeFor(kind: DeferredCallKind): string {
99
+ return kind === "function"
100
+ ? "response.function_call_arguments.delta"
101
+ : "response.custom_tool_call_input.delta";
102
+ }
103
+
104
+ function completeValueFor(kind: DeferredCallKind, event: JsonRecord): string {
105
+ const value = kind === "function" ? event.arguments : event.input;
106
+ return typeof value === "string" ? value : "";
107
+ }
108
+
109
+ /**
110
+ * Create one provider-scoped block rewrite per upstream response.
111
+ *
112
+ * Retained ids and pending-call markers are charged to the request translator
113
+ * budget and hard-capped. `dispose` releases them on terminal, EOF, cancel, or
114
+ * relay failure through the shared block-rewrite lifecycle.
115
+ */
116
+ export function createGithubCopilotResponsesBlockRewrite(
117
+ budget?: TranslatorBudget,
118
+ ): SseBlockRewrite {
119
+ const items = new Map<number, TrackedItem>();
120
+ const deferredCalls = new Map<string, number>();
121
+ let responseId: string | undefined;
122
+ let itemStateBytes = 0;
123
+ let callStateBytes = 0;
124
+ let nextSequenceNumber = 0;
125
+ let itemTrackingTainted = false;
126
+ let disposed = false;
127
+
128
+ const ensureStateLimit = (nextBytes: number): void => {
129
+ if (itemStateBytes + callStateBytes + nextBytes > RETAINED_STATE_LIMIT_BYTES) {
130
+ throw new TranslatorBudgetExceededError("item_ids", RETAINED_STATE_LIMIT_BYTES);
131
+ }
132
+ };
133
+
134
+ const chargeItemState = (bytes: number): void => {
135
+ ensureStateLimit(bytes);
136
+ budget?.chargeRetained(bytes, { kind: "item_ids" });
137
+ itemStateBytes += bytes;
138
+ };
139
+
140
+ const chargeCallState = (bytes: number): void => {
141
+ ensureStateLimit(bytes);
142
+ budget?.chargeRetained(bytes, { kind: "retained_collectors" });
143
+ callStateBytes += bytes;
144
+ };
145
+
146
+ const releaseDeferredCall = (key: string): boolean => {
147
+ const bytes = deferredCalls.get(key);
148
+ if (bytes === undefined) return false;
149
+ deferredCalls.delete(key);
150
+ callStateBytes -= bytes;
151
+ budget?.releaseRetained(bytes, { kind: "retained_collectors" });
152
+ return true;
153
+ };
154
+
155
+ const rememberResponseId = (candidate: string): string => {
156
+ if (responseId !== undefined) return responseId;
157
+ const bytes = byteLength(candidate);
158
+ chargeItemState(bytes);
159
+ responseId = candidate;
160
+ return candidate;
161
+ };
162
+
163
+ const rememberItem = (
164
+ outputIndex: number,
165
+ candidateId: string,
166
+ itemType?: string,
167
+ encryptedReasoning = false,
168
+ ): TrackedItem => {
169
+ const existing = items.get(outputIndex);
170
+ if (existing) {
171
+ if (existing.type === undefined && itemType !== undefined) {
172
+ const extra = byteLength(itemType);
173
+ chargeItemState(extra);
174
+ existing.type = itemType;
175
+ }
176
+ existing.encryptedReasoning ||= encryptedReasoning;
177
+ return existing;
178
+ }
179
+ if (itemTrackingTainted || items.size >= MAX_TRACKED_ITEMS) {
180
+ // Keep relaying client-visible events after the count cap, but stop
181
+ // retaining new output-index mappings. The current event still receives
182
+ // the provider id, while earlier retained mappings remain available for
183
+ // stable ids. Byte-budget failures stay hard failures.
184
+ itemTrackingTainted = true;
185
+ return { id: candidateId, type: itemType, encryptedReasoning };
186
+ }
187
+ chargeItemState(byteLength([outputIndex, candidateId, itemType ?? null]));
188
+ const tracked = { id: candidateId, type: itemType, encryptedReasoning };
189
+ items.set(outputIndex, tracked);
190
+ return tracked;
191
+ };
192
+
193
+ const rememberDeferredCall = (key: string): void => {
194
+ if (deferredCalls.has(key)) return;
195
+ if (deferredCalls.size >= MAX_TRACKED_DEFERRED_CALLS) {
196
+ throw new TranslatorBudgetExceededError("retained_collectors", RETAINED_STATE_LIMIT_BYTES);
197
+ }
198
+ const bytes = byteLength(key);
199
+ chargeCallState(bytes);
200
+ deferredCalls.set(key, bytes);
201
+ };
202
+
203
+ const sanitizeReasoningItem = (
204
+ item: JsonRecord,
205
+ tracked: TrackedItem,
206
+ ): void => {
207
+ if (item.type !== "reasoning") return;
208
+ const encrypted = typeof item.encrypted_content === "string";
209
+ tracked.encryptedReasoning ||= encrypted;
210
+ if (encrypted) delete item.encrypted_content;
211
+ if (tracked.encryptedReasoning) {
212
+ const summary = Array.isArray(item.summary) ? item.summary : [];
213
+ const hasPlaintextSummary = summary.some(part =>
214
+ isRecord(part)
215
+ && part.type === "summary_text"
216
+ && typeof part.text === "string"
217
+ && part.text.length > 0);
218
+ if (!hasPlaintextSummary) item.summary = [{ type: "summary_text", text: "" }];
219
+ if (!Array.isArray(item.content)) item.content = [];
220
+ }
221
+ };
222
+
223
+ const normalizeNestedItem = (item: JsonRecord, outputIndex: number): void => {
224
+ const candidateId = typeof item.id === "string" ? item.id : undefined;
225
+ if (candidateId === undefined) return;
226
+ const itemType = typeof item.type === "string" ? item.type : undefined;
227
+ const tracked = rememberItem(
228
+ outputIndex,
229
+ candidateId,
230
+ itemType,
231
+ itemType === "reasoning" && typeof item.encrypted_content === "string",
232
+ );
233
+ item.id = tracked.id;
234
+ sanitizeReasoningItem(item, tracked);
235
+ };
236
+
237
+ const normalizeSequence = (event: JsonRecord): void => {
238
+ if (typeof event.sequence_number !== "number" || !Number.isFinite(event.sequence_number)) return;
239
+ event.sequence_number = nextSequenceNumber++;
240
+ };
241
+
242
+ const dispose = (): void => {
243
+ if (disposed) return;
244
+ disposed = true;
245
+ if (itemStateBytes > 0) budget?.releaseRetained(itemStateBytes, { kind: "item_ids" });
246
+ if (callStateBytes > 0) budget?.releaseRetained(callStateBytes, { kind: "retained_collectors" });
247
+ items.clear();
248
+ deferredCalls.clear();
249
+ responseId = undefined;
250
+ itemStateBytes = 0;
251
+ callStateBytes = 0;
252
+ itemTrackingTainted = false;
253
+ };
254
+
255
+ const rewrite: SseBlockRewrite = (block) => {
256
+ const payload = sseDataPayload(block);
257
+ if (payload === null || payload === "[DONE]") return [block];
258
+
259
+ let event: unknown;
260
+ try {
261
+ event = JSON.parse(payload);
262
+ } catch {
263
+ return [block];
264
+ }
265
+ if (!isRecord(event)) return [block];
266
+
267
+ if (typeof event.obfuscation === "string") delete event.obfuscation;
268
+
269
+ const type = event.type;
270
+ const outputIndex = outputIndexOf(event.output_index);
271
+ const deltaKind = callKindForDelta(type);
272
+ const deferToolDelta = deltaKind !== undefined
273
+ && outputIndex !== undefined;
274
+
275
+ if (isRecord(event.response) && typeof event.response.id === "string") {
276
+ event.response.id = rememberResponseId(event.response.id);
277
+ }
278
+
279
+ if (outputIndex !== undefined && isRecord(event.item)) {
280
+ normalizeNestedItem(event.item, outputIndex);
281
+ }
282
+ // A deferred delta is not client-visible, so it must not establish the
283
+ // public item id if a malformed provider sends it before output_item.added.
284
+ if (!deferToolDelta && outputIndex !== undefined && typeof event.item_id === "string") {
285
+ const tracked = rememberItem(outputIndex, event.item_id);
286
+ event.item_id = tracked.id;
287
+ }
288
+
289
+ if (type === "response.completed" && isRecord(event.response) && Array.isArray(event.response.output)) {
290
+ event.response.output.forEach((item, index) => {
291
+ if (isRecord(item)) normalizeNestedItem(item, index);
292
+ });
293
+ }
294
+
295
+ if (typeof type === "string" && type.startsWith("response.reasoning")) {
296
+ if (typeof event.encrypted_content === "string") delete event.encrypted_content;
297
+ // `encrypted_content` is opaque replay state; summary delta/text fields
298
+ // are a separate, potentially readable part of the public Responses
299
+ // contract and must survive when Copilot provides them.
300
+ }
301
+
302
+ if (deferToolDelta) {
303
+ rememberDeferredCall(callKey(deltaKind, outputIndex));
304
+ // The OpenAI `obfuscation` field is padding, not a decryption key. Defer
305
+ // every Copilot tool fragment anyway: mixed padded/unpadded fragments and
306
+ // rotating ids cannot then produce duplicate or irreconcilable input.
307
+ // `.done` carries the authoritative complete value, which is emitted as
308
+ // one canonical delta immediately before the original `.done` event.
309
+ return [];
310
+ }
311
+
312
+ const emitted: Array<{ event: JsonRecord; synthetic: boolean }> = [];
313
+ const doneKind = callKindForDone(type);
314
+ if (doneKind !== undefined && outputIndex !== undefined) {
315
+ const key = callKey(doneKind, outputIndex);
316
+ if (releaseDeferredCall(key)) {
317
+ emitted.push({
318
+ synthetic: true,
319
+ event: {
320
+ type: deltaTypeFor(doneKind),
321
+ output_index: outputIndex,
322
+ ...(typeof event.item_id === "string" ? { item_id: event.item_id } : {}),
323
+ ...(typeof event.sequence_number === "number" ? { sequence_number: event.sequence_number } : {}),
324
+ delta: completeValueFor(doneKind, event),
325
+ },
326
+ });
327
+ }
328
+ }
329
+ emitted.push({ event, synthetic: false });
330
+
331
+ for (const entry of emitted) normalizeSequence(entry.event);
332
+ return emitted.map(entry => entry.synthetic
333
+ ? syntheticJsonBlock(block, entry.event)
334
+ : rewriteJsonBlock(block, entry.event));
335
+ };
336
+ rewrite.dispose = dispose;
337
+ return rewrite;
338
+ }
@@ -56,16 +56,25 @@ function isFile(path: string): boolean {
56
56
  }
57
57
  }
58
58
 
59
- function htmlResponse(path: string, session?: GuiSessionBootstrap): Response {
60
- let html = readFileSync(path, "utf8");
61
- if (session) {
62
- const bootstrap = [
63
- `<meta name="opencodex-session-token" content="${session.token}">`,
64
- `<meta name="opencodex-session-csrf" content="${session.csrfToken}">`,
65
- `<meta name="opencodex-session-origin" content="${session.origin}">`,
66
- ].join("");
67
- html = html.includes("</head>") ? html.replace("</head>", `${bootstrap}</head>`) : `${bootstrap}${html}`;
68
- }
59
+ /** HTML-attribute escape for values interpolated into meta tags. */
60
+ function escapeHtmlAttribute(value: string): string {
61
+ return value
62
+ .replaceAll("&", "&amp;")
63
+ .replaceAll('"', "&quot;")
64
+ .replaceAll("<", "&lt;")
65
+ .replaceAll(">", "&gt;");
66
+ }
67
+
68
+ /** Shared session meta-tag block, escaped for quoted attribute interpolation. */
69
+ function sessionBootstrapMeta(session: GuiSessionBootstrap): string {
70
+ return [
71
+ `<meta name="opencodex-session-token" content="${escapeHtmlAttribute(session.token)}">`,
72
+ `<meta name="opencodex-session-csrf" content="${escapeHtmlAttribute(session.csrfToken)}">`,
73
+ `<meta name="opencodex-session-origin" content="${escapeHtmlAttribute(session.origin)}">`,
74
+ ].join("");
75
+ }
76
+
77
+ function htmlDocumentResponse(html: string): Response {
69
78
  return new Response(html, {
70
79
  headers: {
71
80
  "Content-Type": "text/html",
@@ -76,6 +85,26 @@ function htmlResponse(path: string, session?: GuiSessionBootstrap): Response {
76
85
  });
77
86
  }
78
87
 
88
+ function htmlResponse(path: string, session?: GuiSessionBootstrap): Response {
89
+ let html = readFileSync(path, "utf8");
90
+ if (session) {
91
+ const bootstrap = sessionBootstrapMeta(session);
92
+ html = html.includes("</head>") ? html.replace("</head>", `${bootstrap}</head>`) : `${bootstrap}${html}`;
93
+ }
94
+ return htmlDocumentResponse(html);
95
+ }
96
+
97
+ /**
98
+ * Minimal session-bootstrap document, independent of any packaged GUI build. The dev
99
+ * GUI (Vite) proxies /opencodex-session to the backend with the original host so the
100
+ * backend can mint an origin-bound loopback session even when gui/dist does not exist.
101
+ */
102
+ export function serveSessionBootstrap(session: GuiSessionBootstrap): Response {
103
+ const bootstrap = sessionBootstrapMeta(session);
104
+ const html = `<!doctype html><html><head><meta charset="utf-8">${bootstrap}</head><body></body></html>`;
105
+ return htmlDocumentResponse(html);
106
+ }
107
+
79
108
  export function serveGuiFile(
80
109
  pathname: string,
81
110
  guiDist = findGuiDist(),
@@ -15,13 +15,16 @@
15
15
  import { formatErrorResponse } from "../bridge";
16
16
  import {
17
17
  CodexAccountCooldownError,
18
+ codexMainProfileDrainingResponse,
18
19
  cooldownErrorResponse,
19
20
  CodexAuthContextError,
21
+ CodexMainProfileDrainingError,
20
22
  CodexPoolAuthenticationError,
21
23
  CodexThreadAffinityExpiredError,
22
24
  } from "../codex/auth-context";
23
25
  import { formatCodexProviderForLog } from "../codex/routing";
24
26
  import { signalWithTimeout } from "../lib/abort";
27
+ import { readBoundedResponseBytes, type BoundedBytesResult } from "../lib/bounded-body";
25
28
  import { sidecarEnter } from "../lib/sidecar-tracker";
26
29
  import type { OcxConfig } from "../types";
27
30
  import { resolveFirstUsableOpenAiSidecar, selectImagesProvider } from "../providers/openai-sidecar";
@@ -35,6 +38,8 @@ import { safeAntigravityHttpErrorMessage } from "../adapters/google-errors";
35
38
  import { sanitizeUpstreamErrorText } from "../adapters/upstream-http-error";
36
39
  import { ANTIGRAVITY_REQUEST_UA } from "../adapters/google-antigravity-wire";
37
40
  import { decodeValidatedImageBase64, MAX_ENCODED_BYTES_PER_IMAGE } from "../images/artifacts";
41
+ import type { AdmissionLease } from "../lib/admission";
42
+ import { codexAccountSelectionForTurn } from "./lifecycle";
38
43
 
39
44
  export type ImagesEndpoint = "generations" | "edits";
40
45
 
@@ -46,7 +51,56 @@ const IMAGES_UPSTREAM_TIMEOUT_MS = 300_000;
46
51
  * containing base64-encoded images — typically a few MB. This prevents an oversized or malicious
47
52
  * response from exhausting process memory.
48
53
  */
49
- const IMAGES_RESPONSE_MAX_BYTES = 100 * 1024 * 1024;
54
+ export const IMAGES_RESPONSE_MAX_BYTES = 100 * 1024 * 1024;
55
+
56
+ interface ImageResponseBytesOptions {
57
+ signal?: AbortSignal;
58
+ /** Smaller values are used only by focused reader tests. */
59
+ maxBytes?: number;
60
+ }
61
+
62
+ function cancelUnlockedResponseBody(response: Response | undefined, reason?: unknown): void {
63
+ const body = response?.body;
64
+ if (!body || body.locked) return;
65
+ try {
66
+ void body.cancel(reason).catch(() => undefined);
67
+ } catch {
68
+ // A broken stream can throw synchronously from cancel().
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Read one image relay response as exact raw bytes under the same cap used by
74
+ * the public handler. A trustworthy Content-Length can reject obvious excess
75
+ * before attaching a reader; the streaming reader remains authoritative when
76
+ * the header is absent or understated.
77
+ */
78
+ export async function readImageResponseBytes(
79
+ response: Response,
80
+ options: ImageResponseBytesOptions = {},
81
+ ): Promise<BoundedBytesResult> {
82
+ const signal = options.signal;
83
+ if (signal?.aborted) {
84
+ cancelUnlockedResponseBody(response, signal.reason);
85
+ throw signal.reason;
86
+ }
87
+ if (response.body === null) {
88
+ return { bytes: new Uint8Array(0), oversized: false };
89
+ }
90
+
91
+ const maxBytes = options.maxBytes ?? IMAGES_RESPONSE_MAX_BYTES;
92
+ const contentLength = response.headers.get("content-length");
93
+ const declaredBytes = contentLength === null ? Number.NaN : Number(contentLength);
94
+ if (Number.isSafeInteger(declaredBytes) && declaredBytes > maxBytes) {
95
+ cancelUnlockedResponseBody(
96
+ response,
97
+ new DOMException("Response body size limit reached", "QuotaExceededError"),
98
+ );
99
+ return { bytes: new Uint8Array(0), oversized: true };
100
+ }
101
+
102
+ return readBoundedResponseBytes(response, { maxBytes, signal });
103
+ }
50
104
 
51
105
  const CCA_IMAGE_MODEL = "gemini-3.1-flash-image";
52
106
 
@@ -323,6 +377,7 @@ export async function handleImages(
323
377
  config: OcxConfig,
324
378
  endpoint: ImagesEndpoint,
325
379
  logCtx: RequestLogContext,
380
+ turnAdmissionLease?: AdmissionLease,
326
381
  ): Promise<Response> {
327
382
  const candidates = selectImagesProvider(config);
328
383
  if (candidates.error) {
@@ -375,11 +430,15 @@ export async function handleImages(
375
430
  let forwardAuthError: Response | undefined;
376
431
  if (canUseOpenAiForward) {
377
432
  try {
378
- forward = await resolveFirstUsableOpenAiSidecar(candidates.forwardCandidates, req.headers, config);
433
+ forward = await resolveFirstUsableOpenAiSidecar(candidates.forwardCandidates, req.headers, config, {
434
+ beginCodexAccountSelection: codexAccountSelectionForTurn(turnAdmissionLease),
435
+ });
379
436
  if (forward) logCtx.provider = formatCodexProviderForLog(forward.providerName, codexLogAccountId(forward.authContext), config);
380
437
  } catch (err) {
381
438
  if (err instanceof CodexAccountCooldownError) {
382
439
  forwardAuthError = cooldownErrorResponse(err);
440
+ } else if (err instanceof CodexMainProfileDrainingError) {
441
+ forwardAuthError = codexMainProfileDrainingResponse();
383
442
  } else if (err instanceof CodexThreadAffinityExpiredError) {
384
443
  forwardAuthError = formatErrorResponse(409, "invalid_request_error", "Codex thread account affinity expired; start a new session");
385
444
  } else if (err instanceof CodexAuthContextError) {
@@ -431,34 +490,53 @@ export async function handleImages(
431
490
  const timeoutMs = config.images?.timeoutMs ?? IMAGES_UPSTREAM_TIMEOUT_MS;
432
491
  const linkedSignal = signalWithTimeout(timeoutMs, req.signal);
433
492
  const sidecarExit = sidecarEnter("images");
493
+ let upstreamResponse: Response | undefined;
434
494
  try {
435
495
  // Images POSTs create paid, non-idempotent work. One fetch only: no reset retry without a
436
496
  // source-proven idempotency contract.
437
- const upstreamResponse = await fetch(url, {
497
+ upstreamResponse = await fetch(url, {
438
498
  method: "POST",
439
499
  headers,
440
500
  body: JSON.stringify(body),
441
501
  signal: linkedSignal.signal,
502
+ // Do not follow a cross-origin 3xx while carrying Codex credentials. Bun strips
503
+ // `Authorization` across origins but forwards nonstandard headers, so
504
+ // `chatgpt-account-id`, `session_id`, and `x-codex-turn-metadata` would reach the
505
+ // redirect target. Verified with a two-server probe. The Responses path and native
506
+ // compact already set this; the credential-bearing sidecars did not.
507
+ redirect: "manual",
442
508
  });
443
- // Buffer rather than stream: the payload is one JSON document (base64 image, typically a few
444
- // MB), and buffering keeps the timeout window covering the whole exchange. Cap the size to
445
- // prevent an oversized response from exhausting process memory.
446
- const payload = await upstreamResponse.arrayBuffer();
447
- if (payload.byteLength > IMAGES_RESPONSE_MAX_BYTES) {
448
- return formatErrorResponse(502, "upstream_error", `image ${endpoint} response too large (${payload.byteLength} bytes)`);
509
+ const observed = await readImageResponseBytes(upstreamResponse, {
510
+ maxBytes: IMAGES_RESPONSE_MAX_BYTES,
511
+ signal: linkedSignal.signal,
512
+ });
513
+ if (observed.oversized) {
514
+ forward?.recordOutcome?.(upstreamResponse.status);
515
+ return formatErrorResponse(
516
+ 502,
517
+ "upstream_error",
518
+ `image ${endpoint} response too large (exceeded ${IMAGES_RESPONSE_MAX_BYTES} bytes)`,
519
+ );
449
520
  }
450
- forward?.recordOutcome?.(upstreamResponse.status);
451
521
  const relayHeaders: Record<string, string> = {};
452
522
  const contentType = upstreamResponse.headers.get("content-type");
453
523
  if (contentType) relayHeaders["content-type"] = contentType;
454
- return new Response(payload, { status: upstreamResponse.status, headers: relayHeaders });
524
+ // Fetch represents 204/205/304 responses with a null body. Preserve that
525
+ // invariant: constructing those statuses with even an empty Uint8Array throws.
526
+ const relayBody = upstreamResponse.body === null ? null : observed.bytes;
527
+ const relayResponse = new Response(relayBody, {
528
+ status: upstreamResponse.status,
529
+ headers: relayHeaders,
530
+ });
531
+ forward?.recordOutcome?.(upstreamResponse.status);
532
+ return relayResponse;
455
533
  } catch (err) {
456
534
  // Client cancel first: it aborts the linked signal too, and must not be logged as an
457
535
  // upstream failure (499 maps to client_closed_request in the request log).
458
536
  if (req.signal.aborted) {
459
537
  return formatErrorResponse(499, "client_closed_request", `image ${endpoint} request canceled by client`);
460
538
  }
461
- if (err instanceof Error && err.name === "TimeoutError") {
539
+ if (linkedSignal.signal.aborted || (err instanceof Error && err.name === "TimeoutError")) {
462
540
  forward?.recordOutcome?.("timeout");
463
541
  // codex retries 5xx up to 4 more times; a retried 504 is acceptable for a transient hang.
464
542
  return formatErrorResponse(504, "upstream_error", `image ${endpoint} upstream timed out`);
@@ -472,5 +550,9 @@ export async function handleImages(
472
550
  } finally {
473
551
  sidecarExit();
474
552
  linkedSignal.cleanup();
553
+ // If cancellation won before readImageResponseBytes attached its reader, the
554
+ // response still owns an upstream body/socket. Consumed or locked bodies are
555
+ // already owned by the reader and need no second cancellation.
556
+ cancelUnlockedResponseBody(upstreamResponse);
475
557
  }
476
558
  }