@iislee/opencodex 2.11.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -14,12 +14,15 @@ import type { AdapterRequest, IncomingMeta, ProviderAdapter } from "../adapters/
14
14
  import { existsSync } from "node:fs";
15
15
  import { pathToFileURL } from "node:url";
16
16
  import { createAdapterEventQueue } from "../adapters/run-turn-queue";
17
- import type { AdapterEvent, OcxMessage, OcxParsedRequest, OcxProviderContinuationState, OcxRequestOptions, OcxThinkingContent, OcxUsage } from "../types";
18
- import { namespacedToolName } from "../types";
17
+ import type { AdapterEvent, OcxMessage, OcxParsedRequest, OcxProviderContinuationState, OcxProviderOpaqueToolCallMetadata, OcxRequestOptions, OcxThinkingContent, OcxUsage, RateLimitRetryPolicy } from "../types";
18
+ import { namespacedToolName, toolChoiceToolPredicate } from "../types";
19
+ import { cloneProviderOpaqueToolCallMetadata } from "../responses/provider-opaque-metadata";
20
+ import type { AttemptRecoveryKind } from "../usage/log";
19
21
  import { bridgeToResponsesSSE } from "../bridge";
20
22
  import { clearableDeadline, idleDeadline } from "../lib/abort";
21
23
  import { readBoundedResponseBody } from "../lib/bounded-body";
22
- import { fetchWithResetRetry } from "../lib/upstream-retry";
24
+ import { fetchWithResetRetry, prepareSameTarget429Wait } from "../lib/upstream-retry";
25
+ import { rateLimitRetryDelayMs } from "../providers/key-failover";
23
26
  import {
24
27
  isTranslatorBudgetExceededError,
25
28
  TRANSLATOR_MAX_TURN_BYTES,
@@ -91,6 +94,11 @@ interface ImageCall {
91
94
  id: string;
92
95
  name: string;
93
96
  args: string;
97
+ /**
98
+ * Provider-opaque metadata from the originating part (issue #1735). Stored PER CALL: a
99
+ * signature belongs to one specific part, so parallel calls must not share one value.
100
+ */
101
+ providerMetadata?: OcxProviderOpaqueToolCallMetadata;
94
102
  }
95
103
 
96
104
  /**
@@ -107,13 +115,13 @@ function scanEventsForImageCall(events: AdapterEvent[], toolNames: Set<string>):
107
115
  const calls: ImageCall[] = [];
108
116
  const passthrough: AdapterEvent[] = [];
109
117
  let hasRealToolCall = false;
110
- let pending: { name: string; id: string; argsBuf: string; events: AdapterEvent[] } | null = null;
118
+ let pending: { name: string; id: string; argsBuf: string; events: AdapterEvent[]; providerMetadata?: OcxProviderOpaqueToolCallMetadata } | null = null;
111
119
  const flushPending = (): void => {
112
120
  if (!pending) return;
113
121
  if (toolNames.has(pending.name)) {
114
122
  // Unterminated image call still carries buffered args — fulfill so malformed JSON
115
123
  // becomes a normal tool_result error instead of silently vanishing.
116
- calls.push({ id: pending.id, name: pending.name, args: pending.argsBuf });
124
+ calls.push({ id: pending.id, name: pending.name, args: pending.argsBuf, providerMetadata: pending.providerMetadata });
117
125
  } else {
118
126
  passthrough.push(...pending.events);
119
127
  hasRealToolCall = true;
@@ -123,14 +131,14 @@ function scanEventsForImageCall(events: AdapterEvent[], toolNames: Set<string>):
123
131
  for (const e of events) {
124
132
  if (e.type === "tool_call_start") {
125
133
  flushPending();
126
- pending = { name: e.name, id: e.id, argsBuf: "", events: [e] };
134
+ pending = { name: e.name, id: e.id, argsBuf: "", events: [e], providerMetadata: e.providerMetadata };
127
135
  } else if (e.type === "tool_call_delta" && pending) {
128
136
  pending.argsBuf += e.arguments;
129
137
  pending.events.push(e);
130
138
  } else if (e.type === "tool_call_end" && pending) {
131
139
  pending.events.push(e);
132
140
  if (toolNames.has(pending.name)) {
133
- calls.push({ id: pending.id, name: pending.name, args: pending.argsBuf });
141
+ calls.push({ id: pending.id, name: pending.name, args: pending.argsBuf, providerMetadata: pending.providerMetadata });
134
142
  } else {
135
143
  passthrough.push(...pending.events);
136
144
  hasRealToolCall = true;
@@ -159,6 +167,7 @@ function extractIterationThinking(events: AdapterEvent[]): OcxThinkingContent[]
159
167
  const parts: OcxThinkingContent[] = [];
160
168
  let thinking = "";
161
169
  let signature: string | undefined;
170
+ let rawReasoning = "";
162
171
 
163
172
  const flushVisible = () => {
164
173
  if (!thinking && !signature) return;
@@ -170,19 +179,33 @@ function extractIterationThinking(events: AdapterEvent[]): OcxThinkingContent[]
170
179
  thinking = "";
171
180
  signature = undefined;
172
181
  };
182
+ const flushRaw = () => {
183
+ if (!rawReasoning) return;
184
+ parts.push({ type: "thinking", thinking: rawReasoning });
185
+ rawReasoning = "";
186
+ };
173
187
 
174
188
  for (const e of events) {
175
189
  if (e.type === "thinking_delta") {
190
+ flushRaw();
176
191
  thinking += e.thinking;
192
+ } else if (e.type === "reasoning_raw_delta") {
193
+ // OpenAI-compatible providers emit raw reasoning instead of signed
194
+ // thinking; DeepSeek thinking mode requires it back alongside replayed
195
+ // tool_calls (mirrors src/web-search/loop.ts, issue #950).
196
+ flushVisible();
197
+ rawReasoning += e.text;
177
198
  } else if (e.type === "thinking_signature") {
178
199
  signature = e.signature;
179
200
  flushVisible();
180
201
  } else if (e.type === "redacted_thinking") {
181
202
  flushVisible();
203
+ flushRaw();
182
204
  parts.push({ type: "thinking", thinking: "", redacted: [e.data] });
183
205
  }
184
206
  }
185
207
  flushVisible();
208
+ flushRaw();
186
209
  return parts;
187
210
  }
188
211
 
@@ -202,6 +225,10 @@ class LoopError extends Error {
202
225
  }
203
226
  }
204
227
 
228
+ /**
229
+ * Dependencies for one image-bridge iteration: parsed request, active adapter, incoming
230
+ * metadata, and the optional image/video bridge plans.
231
+ */
205
232
  export interface ImageBridgeDeps {
206
233
  parsed: OcxParsedRequest;
207
234
  adapter: ProviderAdapter;
@@ -212,8 +239,8 @@ export interface ImageBridgeDeps {
212
239
  videoTimeoutMs?: number;
213
240
  /** Headers forwarded from the original request (e.g. Codex auth). Cloned per iteration. */
214
241
  forwardHeaders?: Headers;
215
- /** Called before each routed-model dispatch in the bridge loop, for attempt telemetry. */
216
- onAttemptSend?: () => void;
242
+ /** Called before each routed-model dispatch in the bridge loop, for attempt telemetry. Same-target 429 replays pass the `rate-limit-429` recovery kind. */
243
+ onAttemptSend?: (recovery?: AttemptRecoveryKind) => void;
217
244
  /** Called after each upstream request is built (parity with web-search / normal path). */
218
245
  onRequestBuilt?: (request: AdapterRequest) => void;
219
246
  abortSignal?: AbortSignal;
@@ -226,6 +253,8 @@ export interface ImageBridgeDeps {
226
253
  stallTimeoutSec?: number;
227
254
  /** Provider-specific fetch (e.g. xAI transport wrapper). Falls back to global fetch. */
228
255
  fetchImpl?: typeof globalThis.fetch;
256
+ /** Reserve the routed provider's next request-start slot before each adapter dispatch. */
257
+ waitForRequestSlot?: (signal?: AbortSignal) => Promise<void>;
229
258
  /** Raw adapter usage at the terminal event, pre wire-normalization (see bridgeToResponsesSSE onUsage). */
230
259
  onUsage?: (usage: OcxUsage | undefined) => void;
231
260
  /**
@@ -233,6 +262,8 @@ export interface ImageBridgeDeps {
233
262
  * rotated key, or null when the pool is exhausted.
234
263
  */
235
264
  on429?: (retryAfterHeader: string | null) => ProviderAdapter | null;
265
+ /** Opt-in same-target 429 policy (key-auth providers). When present, 429 replays on the SAME key before on429 rotation. */
266
+ retryOn429Policy?: Required<RateLimitRetryPolicy> | null;
236
267
  /** Called when the bridged Responses stream completes (parity with runTurn / routed paths). */
237
268
  onCompletedResponse?: (response: Record<string, unknown>, providerState?: OcxProviderContinuationState) => void;
238
269
  /** WebSocket Responses path only — leave response id empty for protocol compatibility. */
@@ -331,9 +362,20 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
331
362
  }
332
363
  type IterationSplit = ReturnType<typeof scanEventsForImageCall>;
333
364
 
365
+ // Same-target 429 budget is per REQUEST, not per model iteration: later image rounds inherit
366
+ // what earlier rounds left of `attempts`, so a bounded multi-round turn can never exceed the
367
+ // configured replay count in total (a per-round reset would multiply it by maxRounds).
368
+ const rateLimitRetryPolicy = deps.retryOn429Policy ?? null;
369
+ let rateLimitRetries = 0;
370
+
334
371
  // Acquire one iteration's final response headers. The first call is drained eagerly so an initial
335
372
  // connect/header/HTTP failure stays a non-2xx JSON response — except for runTurn adapters, which
336
373
  // have no HTTP status surface and must not block SSE headers behind queue.collect().
374
+ /**
375
+ * Fetch one image-bridge iteration's final response headers, applying the response-header
376
+ * deadline and the same-target 429 retry policy (with awaited body release and deadline
377
+ * restart) before the `on429` key rotation.
378
+ */
337
379
  const prepareIterationEvents = async function* (forceFinal: boolean): AsyncGenerator<AdapterEvent, IterationResponse> {
338
380
  const iterParsed: OcxParsedRequest = {
339
381
  ...parsed,
@@ -346,6 +388,7 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
346
388
  // expose buildRequest/fetchResponse/parseStream to the bridge, so collect their events through
347
389
  // an AdapterEventQueue and wrap them in a pseudo-response whose parseStream replays them.
348
390
  if (adapter.runTurn) {
391
+ await deps.waitForRequestSlot?.(signal);
349
392
  const queue = createAdapterEventQueue({
350
393
  onBacklogExceeded: () => internalAbort.abort("runTurn backlog exceeded"),
351
394
  });
@@ -422,27 +465,59 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
422
465
  return { response: new Response(new Uint8Array(0), { status: 200 }), responseAdapter: wrappedAdapter };
423
466
  }
424
467
 
425
- const headerDeadline = clearableDeadline(connectTimeoutMs, signal);
468
+ let headerDeadline = clearableDeadline(connectTimeoutMs, signal);
469
+ const paceThenResetHeaderDeadline = async (): Promise<void> => {
470
+ headerDeadline.clear();
471
+ await deps.waitForRequestSlot?.(signal);
472
+ headerDeadline = clearableDeadline(connectTimeoutMs, signal);
473
+ };
426
474
  try {
427
- const fetchOnce = async (requestAdapter: ProviderAdapter): Promise<IterationResponse> => {
428
- const request = await requestAdapter.buildRequest(iterParsed, {
429
- headers: deps.forwardHeaders ? new Headers(deps.forwardHeaders) : new Headers(),
430
- abortSignal: headerDeadline.signal,
431
- translatorBudget,
432
- });
433
- try { deps.onRequestBuilt?.(request); } catch { /* diagnostics are best-effort */ }
434
- deps.onAttemptSend?.();
475
+ /**
476
+ * Build and fetch one image-bridge iteration on the given adapter, under the iteration
477
+ * header deadline. The caller owns same-target 429 replays and key rotation around it.
478
+ * The outbound request is cached per adapter so a same-target replay reuses the EXACT
479
+ * URL, serialized body, and headers (builder runs once per target sequence).
480
+ */
481
+ let cachedRequest: AdapterRequest | undefined;
482
+ let cachedAdapter: ProviderAdapter | undefined;
483
+ /**
484
+ * Build and fetch one image-bridge iteration on the given adapter, under the iteration
485
+ * header deadline. The caller owns same-target 429 replays and key rotation around it.
486
+ */
487
+ const fetchOnce = async (requestAdapter: ProviderAdapter, recovery?: AttemptRecoveryKind): Promise<IterationResponse> => {
488
+ let request: AdapterRequest;
489
+ if (cachedRequest !== undefined && cachedAdapter === requestAdapter) {
490
+ request = cachedRequest;
491
+ } else {
492
+ request = await requestAdapter.buildRequest(iterParsed, {
493
+ headers: deps.forwardHeaders ? new Headers(deps.forwardHeaders) : new Headers(),
494
+ abortSignal: headerDeadline.signal,
495
+ translatorBudget,
496
+ });
497
+ try { deps.onRequestBuilt?.(request); } catch { /* diagnostics are best-effort */ }
498
+ cachedRequest = request;
499
+ cachedAdapter = requestAdapter;
500
+ }
435
501
  let response: Response;
436
502
  try {
437
- response = requestAdapter.fetchResponse
438
- ? await requestAdapter.fetchResponse(request, {
503
+ if (requestAdapter.fetchResponse) {
504
+ await paceThenResetHeaderDeadline();
505
+ deps.onAttemptSend?.(recovery);
506
+ response = await requestAdapter.fetchResponse(request, {
439
507
  abortSignal: headerDeadline.signal,
440
508
  timeoutMs: connectTimeoutMs,
441
509
  returnRawErrors: true,
442
510
  stream: true,
443
- })
444
- : await fetchWithResetRetry(
445
- () => {
511
+ executor: fetchImpl,
512
+ });
513
+ } else {
514
+ response = await fetchWithResetRetry(
515
+ async (retryRecovery) => {
516
+ await paceThenResetHeaderDeadline();
517
+ // Record every helper-driven send (the callback runs for the first attempt and
518
+ // each connection-reset replay); preserve the caller's recovery kind
519
+ // (rate-limit-429 / key-429) when the retry layer supplies none.
520
+ deps.onAttemptSend?.(retryRecovery ?? recovery);
446
521
  const h = new Headers(request.headers);
447
522
  if (!h.has("accept-encoding")) h.set("accept-encoding", "identity");
448
523
  return fetchImpl(request.url, {
@@ -453,7 +528,8 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
453
528
  });
454
529
  },
455
530
  { abortSignal: headerDeadline.signal, label: "image-bridge-loop" },
456
- );
531
+ );
532
+ }
457
533
  } finally {
458
534
  request.releaseBodyObservation?.();
459
535
  }
@@ -461,6 +537,39 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
461
537
  };
462
538
 
463
539
  let prepared = await fetchOnce(adapter);
540
+ // Same-target 429 wait-and-retry (opt-in `retryOn429`) BEFORE key rotation: a primary-key
541
+ // rate-limit blip replays on the SAME key; rotation only runs after attempts exhaust.
542
+ while (
543
+ prepared.response.status === 429
544
+ && rateLimitRetryPolicy !== null
545
+ && rateLimitRetries < rateLimitRetryPolicy.attempts
546
+ ) {
547
+ rateLimitRetries += 1;
548
+ // Release unread body + heartbeat-fed wait via the shared same-target helper.
549
+ const retryAfterHeader = prepared.response.headers.get("retry-after");
550
+ // The old header deadline must not stay armed across the deliberate wait: clear it
551
+ // before sleeping so a stale expiry can never race the client-cancel path.
552
+ headerDeadline.clear();
553
+ try {
554
+ yield* prepareSameTarget429Wait({
555
+ body: prepared.response.body,
556
+ signal,
557
+ delayMs: rateLimitRetryDelayMs(rateLimitRetryPolicy, retryAfterHeader, Date.now()),
558
+ heartbeatIntervalMs: Math.min(10_000, Math.max(250, stallTimeoutMs / 2)),
559
+ });
560
+ } catch {
561
+ throw new LoopError(499, "client closed request during image-bridge");
562
+ }
563
+ // Client cancellation wins over any stale-deadline edge: re-check before telemetry/replay.
564
+ if (signal.aborted) throw new LoopError(499, "client closed request during image-bridge");
565
+ // The deliberate backoff must not consume the cumulative response-header deadline:
566
+ // start a fresh one so the replay gets a new connect budget (504 stays reserved for real
567
+ // upstream latency).
568
+ headerDeadline = clearableDeadline(connectTimeoutMs, signal);
569
+ // Stall-watchdog seam between bounded retry fetches.
570
+ yield { type: "heartbeat" };
571
+ prepared = await fetchOnce(adapter, "rate-limit-429");
572
+ }
464
573
  // 429 key-failover parity with web-search / normal routed path.
465
574
  while (prepared.response.status === 429 && deps.on429) {
466
575
  const rotated = deps.on429(prepared.response.headers.get("retry-after"));
@@ -468,7 +577,7 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
468
577
  try { void prepared.response.body?.cancel().catch(() => {}); } catch { /* already closed */ }
469
578
  adapter = rotated;
470
579
  yield { type: "heartbeat" };
471
- prepared = await fetchOnce(adapter);
580
+ prepared = await fetchOnce(adapter, "key-429");
472
581
  }
473
582
 
474
583
  // Final headers have arrived. Clear only the deadline timer before ANY body read.
@@ -567,11 +676,20 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
567
676
  }
568
677
  }
569
678
 
570
- const toolNsMap = new Map<string, { namespace: string; name: string }>();
679
+ const toolNsMap = new Map<string, { namespace: string; name: string; freeform?: true }>();
571
680
  const freeform = new Set<string>();
572
681
  const toolSearch = new Set<string>();
573
- for (const t of parsed.context.tools ?? []) {
574
- if (t.namespace) toolNsMap.set(namespacedToolName(t.namespace, t.name), { namespace: t.namespace, name: t.name });
682
+ const requestedTools = parsed.context.tools ?? [];
683
+ const toolAllowed = toolChoiceToolPredicate(parsed.options.toolChoice, requestedTools);
684
+ for (const t of requestedTools) {
685
+ if (!toolAllowed(t)) continue;
686
+ if (t.namespace) {
687
+ toolNsMap.set(namespacedToolName(t.namespace, t.name), {
688
+ namespace: t.namespace,
689
+ name: t.name,
690
+ ...(t.freeform ? { freeform: true } : {}),
691
+ });
692
+ }
575
693
  if (t.freeform) freeform.add(t.name);
576
694
  if (t.toolSearch) toolSearch.add(t.name);
577
695
  }
@@ -767,6 +885,10 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
767
885
  id: call.id,
768
886
  name: call.name,
769
887
  arguments: args,
888
+ // Clone per call: parallel media calls each keep their own signature.
889
+ ...(cloneProviderOpaqueToolCallMetadata(call.providerMetadata)
890
+ ? { providerMetadata: cloneProviderOpaqueToolCallMetadata(call.providerMetadata) }
891
+ : {}),
770
892
  })),
771
893
  ],
772
894
  timestamp: now,
@@ -808,11 +930,12 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
808
930
  }
809
931
 
810
932
  const sse = bridgeToResponsesSSE(
811
- produce(), parsed.modelId, toolNsMap, freeform, toolSearch, () => {
933
+ produce(), parsed._responseModelId ?? parsed.modelId, toolNsMap, freeform, toolSearch, () => {
812
934
  internalAbort.abort("client closed responses stream");
813
935
  }, 2_000,
814
936
  {
815
937
  translatorBudget,
938
+ replayCacheScope: parsed._reasoningReplayScope,
816
939
  ...(deps.forceEmptyResponseId ? { responseId: "" } : {}),
817
940
  hideThinkingSummary: parsed.options.hideThinkingSummary,
818
941
  stallTimeoutSec: deps.stallTimeoutSec,
@@ -1,4 +1,5 @@
1
1
  import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../types";
2
+ import { toolChoiceToolPredicate } from "../types";
2
3
  import type { ImageBridgePlan, VideoBridgePlan } from "./types";
3
4
  import { resolveEnvValue } from "../config";
4
5
  import { getProviderRegistryEntry } from "../providers/registry";
@@ -46,6 +47,12 @@ export async function planImageBridge(
46
47
  ): Promise<ImageBridgePlan | undefined> {
47
48
  if (config.images?.bridgeEnabled !== true) return undefined;
48
49
  if (!parsed._imageGeneration) return undefined;
50
+ const toolAllowed = toolChoiceToolPredicate(parsed.options.toolChoice);
51
+ const toolNames = new Set(
52
+ [...parsed._imageGeneration.toolNames, IMAGE_GEN_TOOL_NAME]
53
+ .filter(name => toolAllowed({ name })),
54
+ );
55
+ if (toolNames.size === 0) return undefined;
49
56
  // Don't intercept for OpenAI native passthrough
50
57
  const host = (() => { try { return new URL(routedProvider.baseUrl).hostname; } catch { return ""; } })();
51
58
  if (host === "api.openai.com") return undefined;
@@ -57,9 +64,7 @@ export async function planImageBridge(
57
64
  const registryEntry = getProviderRegistryEntry("xai");
58
65
  const pinnedBaseUrl = (registryEntry?.baseUrl ?? "https://api.x.ai/v1").replace(/\/+$/, "");
59
66
  // The synthetic tool injected into the conversation is named IMAGE_GEN_TOOL_NAME,
60
- // which is what the model will actually call. Merge it with any original hosted tool names.
61
- const toolNames = new Set(parsed._imageGeneration.toolNames);
62
- toolNames.add(IMAGE_GEN_TOOL_NAME);
67
+ // which is what the model will actually call. toolNames also retains authorized hosted aliases.
63
68
  const original = parsed._imageGeneration.originalTool;
64
69
  const hostedSize = typeof original?.size === "string" ? original.size : undefined;
65
70
  const hostedQuality = typeof original?.quality === "string" ? original.quality : undefined;
@@ -95,16 +100,6 @@ export async function planVideoBridge(
95
100
  routedProvider: OcxProviderConfig,
96
101
  ): Promise<VideoBridgePlan | undefined> {
97
102
  if (config.images?.videoBridgeEnabled !== true) return undefined;
98
- // Don't intercept for OpenAI native passthrough
99
- const host = (() => { try { return new URL(routedProvider.baseUrl).hostname; } catch { return ""; } })();
100
- if (host === "api.openai.com") return undefined;
101
- const found = findXaiProvider(config);
102
- if (!found) return undefined;
103
- const token = resolveXaiImageApiKey(found.provider);
104
- if (!token) return undefined;
105
- // Pin the baseUrl to the registry entry, ignoring any config-level baseUrl override.
106
- const registryEntry = getProviderRegistryEntry("xai");
107
- const pinnedBaseUrl = (registryEntry?.baseUrl ?? "https://api.x.ai/v1").replace(/\/+$/, "");
108
103
  const toolNames = new Set<string>();
109
104
  toolNames.add(VIDEO_GEN_TOOL_NAME);
110
105
  // Collect any existing function tools whose name matches a video_gen alias
@@ -118,6 +113,21 @@ export async function planVideoBridge(
118
113
  toolNames.add(fnName);
119
114
  }
120
115
  }
116
+ const toolAllowed = toolChoiceToolPredicate(parsed.options?.toolChoice);
117
+ for (const name of toolNames) {
118
+ if (!toolAllowed({ name })) toolNames.delete(name);
119
+ }
120
+ if (toolNames.size === 0) return undefined;
121
+ // Don't intercept for OpenAI native passthrough
122
+ const host = (() => { try { return new URL(routedProvider.baseUrl).hostname; } catch { return ""; } })();
123
+ if (host === "api.openai.com") return undefined;
124
+ const found = findXaiProvider(config);
125
+ if (!found) return undefined;
126
+ const token = resolveXaiImageApiKey(found.provider);
127
+ if (!token) return undefined;
128
+ // Pin the baseUrl to the registry entry, ignoring any config-level baseUrl override.
129
+ const registryEntry = getProviderRegistryEntry("xai");
130
+ const pinnedBaseUrl = (registryEntry?.baseUrl ?? "https://api.x.ai/v1").replace(/\/+$/, "");
121
131
  const timeoutMs = clampImageTimeoutMs(config.images?.videoTimeoutMs);
122
132
  const keepRaw = config.images?.artifactsKeepCount;
123
133
  const artifactsKeepCount =