@bitkyc08/opencodex 2.80.0 → 2.82.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 (376) hide show
  1. package/README.md +3 -3
  2. package/bin/ocx.mjs +166 -73
  3. package/gui/dist/assets/App-Ds_qL7o8.js +54 -0
  4. package/gui/dist/assets/Tray-BqHF5Trd.js +1 -0
  5. package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
  6. package/gui/dist/assets/index-D3FBCNiP.js +94 -0
  7. package/gui/dist/assets/quota-summary-DTBC8n7-.js +1 -0
  8. package/gui/dist/index.html +2 -2
  9. package/gui/dist/provider-icons/claude-green.svg +1 -0
  10. package/package.json +3 -2
  11. package/src/adapters/anthropic-model-contract.ts +8 -2
  12. package/src/adapters/anthropic.ts +8 -3
  13. package/src/adapters/codebuddy/mcp-server.ts +2 -25
  14. package/src/adapters/codebuddy/tool-bridge.ts +1 -7
  15. package/src/adapters/coding-agent/mcp-server.ts +33 -0
  16. package/src/adapters/coding-agent/protocol.ts +122 -17
  17. package/src/adapters/coding-agent/tool-catalog.ts +75 -0
  18. package/src/adapters/coding-agent/turn.ts +101 -44
  19. package/src/adapters/cursor/catalog.ts +8 -0
  20. package/src/adapters/cursor/effort-map.ts +2 -0
  21. package/src/adapters/devin/live-models.ts +2 -0
  22. package/src/adapters/kiro-retry.ts +9 -4
  23. package/src/adapters/openai-chat/messages.ts +7 -6
  24. package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
  25. package/src/adapters/openai-responses/passthrough.ts +9 -4
  26. package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
  27. package/src/adapters/physical-send.ts +8 -5
  28. package/src/adapters/qoder/adapter.ts +41 -6
  29. package/src/adapters/qoder/scaffold-guard.ts +2 -3
  30. package/src/adapters/zed.ts +16 -1
  31. package/src/claude/agents-inject.ts +14 -3
  32. package/src/claude/context-windows.ts +19 -17
  33. package/src/claude/desktop-3p.ts +88 -12
  34. package/src/claude/desktop-profile.ts +2 -1
  35. package/src/claude/gateway-cache.ts +18 -1
  36. package/src/claude/inbound-cache-stabilize.ts +4 -9
  37. package/src/claude/inbound.ts +78 -3
  38. package/src/claude/intercept/cli-catalog.ts +3 -0
  39. package/src/claude/intercept/model-bindings.ts +1 -0
  40. package/src/claude/intercept/picker-ca-persistence.ts +7 -6
  41. package/src/claude/intercept/picker-listener.ts +71 -4
  42. package/src/claude/intercept/picker-models.ts +14 -6
  43. package/src/claude/intercept/settings.ts +3 -0
  44. package/src/claude/long-context.ts +66 -0
  45. package/src/claude/model-info.ts +19 -16
  46. package/src/claude/outbound.ts +94 -9
  47. package/src/claude/subagent-model.ts +40 -11
  48. package/src/cli/account-anthropic-threshold.ts +14 -5
  49. package/src/cli/account-api.ts +3 -1
  50. package/src/cli/account-extended.ts +13 -9
  51. package/src/cli/account-policy-dto.ts +1 -1
  52. package/src/cli/account-policy.ts +13 -4
  53. package/src/cli/account.ts +3 -3
  54. package/src/cli/agent.ts +9 -5
  55. package/src/cli/aside-profile-recovery.ts +33 -0
  56. package/src/cli/capabilities-accounts.ts +2 -2
  57. package/src/cli/capabilities-agents-routing.ts +24 -0
  58. package/src/cli/capabilities-base.ts +5 -5
  59. package/src/cli/capabilities-integrations.ts +18 -2
  60. package/src/cli/cli-path-diagnostics.ts +132 -0
  61. package/src/cli/codex-shim-autorestore.ts +3 -0
  62. package/src/cli/desktop-runtime-guidance.ts +65 -0
  63. package/src/cli/dispatch.ts +15 -1
  64. package/src/cli/doctor.ts +16 -3
  65. package/src/cli/help.ts +4 -1
  66. package/src/cli/index.ts +25 -14
  67. package/src/cli/integration-aside-sync.ts +2 -1
  68. package/src/cli/integration-plan-dto.ts +1 -0
  69. package/src/cli/integration-preview.ts +8 -1
  70. package/src/cli/integrations.ts +48 -6
  71. package/src/cli/message-args.ts +34 -0
  72. package/src/cli/message-command.ts +43 -0
  73. package/src/cli/message-runtime.ts +6 -0
  74. package/src/cli/observe.ts +3 -1
  75. package/src/cli/provider.ts +29 -6
  76. package/src/cli/registry.ts +24 -2
  77. package/src/cli/resolve.ts +25 -2
  78. package/src/cli/root.ts +4 -2
  79. package/src/cli/status.ts +64 -12
  80. package/src/cli/update-restart-child.ts +4 -2
  81. package/src/cli/update-restart-home.ts +28 -10
  82. package/src/cli/update-restart-service-record.ts +116 -0
  83. package/src/cli/update-restart-supervision.ts +96 -0
  84. package/src/cli/update-restart.ts +59 -13
  85. package/src/cli/v2.ts +27 -20
  86. package/src/cli/version-skew-notice.ts +77 -0
  87. package/src/clients/config-export/commandcode.ts +131 -0
  88. package/src/clients/config-export/contracts.ts +12 -0
  89. package/src/clients/config-export.ts +64 -1
  90. package/src/clients/lazycodex.ts +1 -1
  91. package/src/clients/omo-role-models.ts +32 -7
  92. package/src/codex/auth-api/account-list.ts +11 -3
  93. package/src/codex/auth-api/account-selection.ts +107 -0
  94. package/src/codex/auth-api/main-account-probe.ts +25 -8
  95. package/src/codex/auth-api/pool-mode-gate.ts +33 -9
  96. package/src/codex/auth-api/pool-quota-probe.ts +15 -1
  97. package/src/codex/auth-api/routes.ts +11 -49
  98. package/src/codex/auth-context.ts +20 -1
  99. package/src/codex/autostart-health.ts +12 -3
  100. package/src/codex/catalog/auto-review.ts +13 -6
  101. package/src/codex/catalog/build-entries.ts +33 -7
  102. package/src/codex/catalog/bundled.ts +155 -26
  103. package/src/codex/catalog/combo-member.ts +3 -2
  104. package/src/codex/catalog/control-plane.ts +45 -0
  105. package/src/codex/catalog/effort.ts +37 -6
  106. package/src/codex/catalog/gather-capture.ts +10 -3
  107. package/src/codex/catalog/model-hints.ts +15 -8
  108. package/src/codex/catalog/model-visibility.ts +3 -1
  109. package/src/codex/catalog/operator-tiers.ts +38 -0
  110. package/src/codex/catalog/parsing.ts +2 -1
  111. package/src/codex/catalog/provider-models.ts +58 -44
  112. package/src/codex/catalog/retained-sync.ts +7 -5
  113. package/src/codex/catalog/routed-gather.ts +15 -1
  114. package/src/codex/catalog-auto-refresh-sources.ts +3 -4
  115. package/src/codex/catalog-auto-refresh.ts +19 -0
  116. package/src/codex/catalog.ts +1 -1
  117. package/src/codex/codex-home-owner.ts +3 -0
  118. package/src/codex/config-write-lock.ts +333 -0
  119. package/src/codex/control-plane-models.ts +6 -0
  120. package/src/codex/convergence.ts +2 -1
  121. package/src/codex/features.ts +257 -200
  122. package/src/codex/inject/config-write-section.ts +34 -0
  123. package/src/codex/inject/multi-agent-v2.ts +14 -6
  124. package/src/codex/inject/remove.ts +36 -11
  125. package/src/codex/inject/restore.ts +85 -20
  126. package/src/codex/inject-coordination.ts +15 -6
  127. package/src/codex/inject.ts +62 -20
  128. package/src/codex/journal.ts +62 -17
  129. package/src/codex/main-account-cache.ts +43 -0
  130. package/src/codex/paths.ts +2 -0
  131. package/src/codex/prepared-home.ts +18 -0
  132. package/src/codex/prompt-journal.ts +25 -12
  133. package/src/codex/prompt-layers.ts +49 -26
  134. package/src/codex/prompt-lock-claim.ts +134 -0
  135. package/src/codex/prompt-lock-evidence.ts +26 -0
  136. package/src/codex/prompt-lock-io.ts +16 -0
  137. package/src/codex/prompt-lock-owner.ts +130 -0
  138. package/src/codex/prompt-lock.ts +84 -53
  139. package/src/codex/routing/failure-window.ts +146 -0
  140. package/src/codex/routing/selection.ts +4 -1
  141. package/src/codex/routing.ts +13 -17
  142. package/src/codex/runtime.ts +106 -18
  143. package/src/codex/shim.ts +45 -19
  144. package/src/combos/jev-decision-contract.ts +25 -2
  145. package/src/combos/jev-service-exchange.ts +281 -0
  146. package/src/combos/jev.ts +34 -219
  147. package/src/combos/types.ts +1 -1
  148. package/src/config/atomic-write.ts +1 -1
  149. package/src/config/codex-ws-reuse-setting.ts +10 -0
  150. package/src/config/diagnostics.ts +27 -16
  151. package/src/config/live-reconcile.ts +17 -0
  152. package/src/config/load-degrade.ts +42 -0
  153. package/src/config/rebase-provenance.ts +11 -0
  154. package/src/config/schema/anthropic-account-pool.ts +143 -0
  155. package/src/config/schema/config-schema.ts +11 -1
  156. package/src/config/schema/leaf-validators.ts +4 -0
  157. package/src/config.ts +2 -0
  158. package/src/generated/compatibility-version.json +566 -298
  159. package/src/generated/model-metadata.ts +7 -6
  160. package/src/grok/inject.ts +50 -4
  161. package/src/grok/sync.ts +2 -1
  162. package/src/images/loop.ts +30 -11
  163. package/src/integrations/aside-profiles.ts +10 -3
  164. package/src/integrations/catalog-refresh.ts +19 -3
  165. package/src/integrations/mutation-plan.ts +7 -0
  166. package/src/integrations/registry.ts +8 -0
  167. package/src/integrations/state.ts +9 -2
  168. package/src/integrations/writer.ts +17 -5
  169. package/src/lib/bun-path-runtime.d.mts +32 -0
  170. package/src/lib/bun-path-runtime.mjs +95 -0
  171. package/src/lib/bun-runtime-preflight.ts +140 -0
  172. package/src/lib/desktop-cli-handoff.d.mts +20 -0
  173. package/src/lib/desktop-cli-handoff.mjs +92 -0
  174. package/src/lib/desktop-cli-record.d.mts +29 -0
  175. package/src/lib/desktop-cli-record.mjs +102 -0
  176. package/src/lib/lab-live-route-production.ts +9 -1
  177. package/src/lib/request-execution-budget.ts +244 -58
  178. package/src/lib/spend-pool-alias-validation.ts +79 -0
  179. package/src/lib/spend-pool-continuity.ts +34 -0
  180. package/src/lib/spend-reservation-ledger.ts +412 -50
  181. package/src/lib/state-store-registrations.ts +20 -3
  182. package/src/lib/synced-state-location.ts +46 -6
  183. package/src/lib/test-home-guard.ts +87 -1
  184. package/src/lib/translator-budget.ts +17 -4
  185. package/src/lib/upstream-retry.ts +17 -5
  186. package/src/lib/windows-atomic-replace.ts +38 -16
  187. package/src/lib/windows-elevation.ts +6 -0
  188. package/src/lib/windows-secret-acl.ts +92 -25
  189. package/src/lib/winsw.ts +2 -3
  190. package/src/lib/workflow-budget.ts +53 -11
  191. package/src/messaging/budget.ts +45 -0
  192. package/src/messaging/discovery.ts +57 -0
  193. package/src/messaging/envelope.ts +49 -0
  194. package/src/messaging/input.ts +37 -0
  195. package/src/messaging/rpc.ts +196 -0
  196. package/src/messaging/send.ts +58 -0
  197. package/src/messaging/socket.ts +72 -0
  198. package/src/messaging/types.ts +29 -0
  199. package/src/oauth/anthropic-account-refusal.ts +90 -18
  200. package/src/oauth/anthropic-account-threshold.ts +8 -2
  201. package/src/oauth/anthropic-continuity.ts +15 -1
  202. package/src/oauth/anthropic-model-quota.ts +120 -48
  203. package/src/oauth/anthropic-model-routes.ts +11 -3
  204. package/src/oauth/anthropic-oauth-definitions.ts +98 -0
  205. package/src/oauth/anthropic-pool-config.ts +30 -0
  206. package/src/oauth/anthropic-rate-limit-policy.ts +64 -9
  207. package/src/oauth/anthropic-routing.ts +1202 -866
  208. package/src/oauth/anthropic-send-ownership.ts +41 -0
  209. package/src/oauth/anthropic.ts +4 -1
  210. package/src/oauth/chatgpt.ts +113 -41
  211. package/src/oauth/generic-account-failover.ts +3 -1
  212. package/src/oauth/health.ts +8 -6
  213. package/src/oauth/index.ts +96 -175
  214. package/src/oauth/kiro.ts +22 -9
  215. package/src/oauth/login-cli.ts +2 -0
  216. package/src/oauth/model-discovery-auth.ts +43 -0
  217. package/src/oauth/pool-kernel.ts +11 -5
  218. package/src/oauth/pool-settings-capability.ts +5 -3
  219. package/src/oauth/store-anthropic-instance.ts +87 -0
  220. package/src/oauth/store.ts +68 -10
  221. package/src/oauth/token-guardian.ts +2 -0
  222. package/src/oauth/types.ts +2 -0
  223. package/src/protocols/plan-snapshot.ts +5 -0
  224. package/src/protocols/settings.ts +20 -5
  225. package/src/providers/anthropic-instance-id.ts +47 -0
  226. package/src/providers/anthropic-instance.ts +48 -0
  227. package/src/providers/anthropic-reset-grant-ledger.ts +11 -1
  228. package/src/providers/azure-model-metadata.ts +115 -0
  229. package/src/providers/derive.ts +23 -0
  230. package/src/providers/kiro-models.ts +3 -0
  231. package/src/providers/label.ts +1 -1
  232. package/src/providers/model-rename-fields.ts +2 -0
  233. package/src/providers/quota/account-cache.ts +37 -11
  234. package/src/providers/quota/anthropic-account-quota.ts +93 -0
  235. package/src/providers/quota/anthropic-cooldown-recovery.ts +222 -111
  236. package/src/providers/quota/report-cache.ts +24 -1
  237. package/src/providers/quota/vendor-probes-key.ts +127 -17
  238. package/src/providers/quota/vendor-probes-oauth.ts +46 -14
  239. package/src/providers/quota.ts +23 -33
  240. package/src/providers/registry/entries-core.ts +35 -30
  241. package/src/providers/registry/model-ids.ts +1 -0
  242. package/src/providers/registry/model-seeds.ts +7 -4
  243. package/src/providers/registry/types.ts +3 -0
  244. package/src/providers/registry.ts +3 -3
  245. package/src/responses/reasoning-envelope.ts +29 -1
  246. package/src/responses/reasoning-replay-cache.ts +17 -1
  247. package/src/responses/spill-store.ts +20 -3
  248. package/src/responses/state/metrics.ts +95 -0
  249. package/src/responses/state/snapshot-codec.ts +6 -0
  250. package/src/responses/state/spill-failure.ts +12 -0
  251. package/src/responses/state/spill-queue.ts +13 -5
  252. package/src/responses/state/unforced-store-false.ts +55 -0
  253. package/src/responses/state.ts +68 -76
  254. package/src/responses/task-input.ts +17 -0
  255. package/src/router.ts +28 -4
  256. package/src/routing/compatibility/assemble.ts +1 -1
  257. package/src/routing/quota.ts +7 -3
  258. package/src/server/auth-cors.ts +5 -0
  259. package/src/server/background-lifecycle.ts +27 -0
  260. package/src/server/chat-completions.ts +7 -1
  261. package/src/server/chat-native.ts +64 -28
  262. package/src/server/claude-messages.ts +59 -8
  263. package/src/server/gui-static.ts +38 -4
  264. package/src/server/inbound-body-admission.ts +1 -0
  265. package/src/server/index/claude-intercept-lifecycle.ts +3 -1
  266. package/src/server/index/serve-options.ts +10 -2
  267. package/src/server/index/spend-ledger-lifecycle.ts +12 -5
  268. package/src/server/index/startup-warnings.ts +19 -0
  269. package/src/server/index.ts +5 -2
  270. package/src/server/inference/context.ts +1 -1
  271. package/src/server/lifecycle.ts +1 -1
  272. package/src/server/management/agent-settings-routes.ts +123 -38
  273. package/src/server/management/anthropic-account-threshold.ts +12 -9
  274. package/src/server/management/anthropic-pool-settings.ts +72 -0
  275. package/src/server/management/anthropic-reset-grant-routes.ts +98 -39
  276. package/src/server/management/codex-agent-role-routes.ts +4 -2
  277. package/src/server/management/codex-prompt-routes.ts +1 -0
  278. package/src/server/management/codex-role-auto-assign.ts +13 -2
  279. package/src/server/management/config-routes.ts +85 -14
  280. package/src/server/management/context.ts +2 -2
  281. package/src/server/management/decision-routes.ts +2 -1
  282. package/src/server/management/integration-routes.ts +25 -2
  283. package/src/server/management/oauth-account-routes.ts +79 -98
  284. package/src/server/management/provider-instance-ownership.ts +44 -0
  285. package/src/server/management/provider-routes.ts +21 -28
  286. package/src/server/management/route-registry.ts +3 -1
  287. package/src/server/management/routing-profile-routes.ts +4 -4
  288. package/src/server/management/shared.ts +3 -3
  289. package/src/server/management/system-restart.ts +44 -14
  290. package/src/server/management/system-routes.ts +24 -2
  291. package/src/server/management/vision-sidecar-options.ts +9 -6
  292. package/src/server/management/web-search-sidecar-options.ts +51 -2
  293. package/src/server/management-auth.ts +6 -0
  294. package/src/server/messages-native-eligibility.ts +3 -2
  295. package/src/server/messages-native-oauth.ts +91 -45
  296. package/src/server/messages-native-selector.ts +39 -0
  297. package/src/server/messages-native.ts +133 -38
  298. package/src/server/messages-response-headers.ts +14 -0
  299. package/src/server/request-log-conversation.ts +48 -5
  300. package/src/server/request-log.ts +36 -2
  301. package/src/server/responses/adapter-continuation.ts +31 -19
  302. package/src/server/responses/adapter-dispatch.ts +75 -24
  303. package/src/server/responses/antigravity-validation-refusal.ts +20 -6
  304. package/src/server/responses/codex-ws-exchange.ts +17 -2
  305. package/src/server/responses/codex-ws-pool.ts +100 -13
  306. package/src/server/responses/codex-ws-wire.ts +9 -0
  307. package/src/server/responses/combo-requested-effort.ts +3 -1
  308. package/src/server/responses/compact.ts +25 -8
  309. package/src/server/responses/compaction-recovery.ts +1 -1
  310. package/src/server/responses/core-codex-account.ts +22 -1
  311. package/src/server/responses/core-combo-native.ts +24 -4
  312. package/src/server/responses/core-combo.ts +38 -25
  313. package/src/server/responses/core-lifetime.ts +3 -36
  314. package/src/server/responses/core-normalize.ts +1 -0
  315. package/src/server/responses/core-options.ts +8 -1
  316. package/src/server/responses/core-replay.ts +78 -0
  317. package/src/server/responses/core.ts +3 -3
  318. package/src/server/responses/fetch-helpers.ts +26 -3
  319. package/src/server/responses/passthrough-delivery.ts +30 -4
  320. package/src/server/responses/passthrough-dispatch.ts +39 -9
  321. package/src/server/responses/request-prepare.ts +41 -5
  322. package/src/server/responses/request-send-budget.ts +150 -50
  323. package/src/server/responses/request-spend.ts +325 -33
  324. package/src/server/responses/request-transport.ts +132 -52
  325. package/src/server/responses/response-effects.ts +1 -0
  326. package/src/server/responses/run-turn-execution.ts +13 -3
  327. package/src/server/responses/sidecar-execution.ts +113 -22
  328. package/src/server/responses/sidecar-send-budget.ts +58 -0
  329. package/src/server/responses/ws-upstream.ts +19 -6
  330. package/src/server/responses-undeclared-tool-guard.ts +5 -1
  331. package/src/server/startup-health-cache.ts +2 -1
  332. package/src/server/workflow-refusal.ts +33 -0
  333. package/src/service/cli.ts +20 -4
  334. package/src/service/desktop-command-guard.ts +32 -0
  335. package/src/service/desktop-startup.ts +66 -40
  336. package/src/service/desktop-supervision.d.mts +26 -0
  337. package/src/service/desktop-supervision.mjs +140 -0
  338. package/src/service/managing-cli.ts +1 -0
  339. package/src/service/orchestration.ts +46 -20
  340. package/src/service/ownership-mutation-lease.d.mts +1 -1
  341. package/src/service/ownership-mutation-lease.mjs +5 -7
  342. package/src/service/repair.ts +25 -9
  343. package/src/service/state.ts +4 -3
  344. package/src/service/systemd.ts +17 -8
  345. package/src/service/windows-ops.ts +61 -22
  346. package/src/sidecar/anthropic-binding.ts +79 -0
  347. package/src/sidecar/auth.ts +76 -2
  348. package/src/storage/policy-job.ts +5 -1
  349. package/src/storage/policy-worker.ts +3 -1
  350. package/src/storage/policy.ts +9 -0
  351. package/src/types/anthropic-account-pool.ts +33 -0
  352. package/src/types/config.ts +33 -28
  353. package/src/types/provider.ts +5 -0
  354. package/src/types/request.ts +5 -0
  355. package/src/types/tools.ts +7 -0
  356. package/src/types/wire.ts +1 -0
  357. package/src/types.ts +4 -0
  358. package/src/update/index.ts +57 -9
  359. package/src/update/restart-ownership.ts +10 -3
  360. package/src/update/runtime-ownership.d.mts +6 -0
  361. package/src/update/runtime-ownership.mjs +23 -7
  362. package/src/usage/cost.ts +3 -2
  363. package/src/usage/expected-prices.ts +66 -14
  364. package/src/vision/anthropic-describe.ts +16 -3
  365. package/src/vision/index.ts +3 -0
  366. package/src/vision/plan.ts +19 -6
  367. package/src/web-search/alpha-search.ts +7 -1
  368. package/src/web-search/anthropic-executor.ts +16 -4
  369. package/src/web-search/index.ts +7 -3
  370. package/src/web-search/loop.ts +32 -7
  371. package/src/web-search/passthrough-bridge.ts +4 -1
  372. package/src/web-search/sidecar-providers.ts +4 -3
  373. package/gui/dist/assets/App-MbDVfUeC.js +0 -54
  374. package/gui/dist/assets/Tray-CzkxK82A.js +0 -1
  375. package/gui/dist/assets/index-UJt6npXk.js +0 -94
  376. package/gui/dist/assets/quota-summary-DU3sD6Z-.js +0 -1
@@ -0,0 +1,41 @@
1
+ /** Ownership captured before a physical send, independent of subsequent cooldown observations. */
2
+ import type { OAuthAccessSnapshot } from "./index";
3
+ import { credentialGeneration, getAccountSet, type AuthStore } from "./store";
4
+ import { isAnthropicInstanceId, type AnthropicInstanceId } from "../providers/anthropic-instance-id";
5
+ import { anthropicCooldownRecoveryFor } from "../providers/quota/anthropic-cooldown-recovery";
6
+ import { captureProviderAccountQuotaEpoch } from "../providers/quota/account-cache";
7
+
8
+ export type AnthropicPhysicalSendOwnership = Readonly<{
9
+ provider: AnthropicInstanceId;
10
+ accountId: string;
11
+ accessToken: string;
12
+ generation: string;
13
+ accountIncarnation: number;
14
+ loginId?: string;
15
+ addedAt?: number;
16
+ quotaEpoch: number;
17
+ }>;
18
+
19
+ /** Namespace API: config/target admission remains with the config-aware physical caller. */
20
+ export function captureAnthropicPhysicalSendOwnership(snapshot: OAuthAccessSnapshot): AnthropicPhysicalSendOwnership | null {
21
+ if (!isAnthropicInstanceId(snapshot.provider)) return null;
22
+ const row = getAccountSet(snapshot.provider)?.accounts.find(account => account.id === snapshot.accountId);
23
+ if (!row || row.paused || row.needsReauth || row.credential.access !== snapshot.accessToken
24
+ || credentialGeneration(row.credential) !== snapshot.generation) return null;
25
+ return Object.freeze({
26
+ provider: snapshot.provider, accountId: snapshot.accountId,
27
+ accessToken: snapshot.accessToken, generation: snapshot.generation,
28
+ accountIncarnation: anthropicCooldownRecoveryFor(snapshot.provider).reserveAnthropicAccountIncarnation(snapshot.accountId),
29
+ loginId: row.loginId, addedAt: row.addedAt,
30
+ quotaEpoch: captureProviderAccountQuotaEpoch(snapshot.provider),
31
+ });
32
+ }
33
+
34
+ /** Pure ownership read: never adopt or reserve the replacement account's current incarnation. */
35
+ export function anthropicPhysicalSendOwnershipIsCurrent(owner: AnthropicPhysicalSendOwnership, store?: AuthStore): boolean {
36
+ const row = (store ? store[owner.provider] : getAccountSet(owner.provider))?.accounts.find(account => account.id === owner.accountId);
37
+ return !!row && row.loginId === owner.loginId && row.addedAt === owner.addedAt
38
+ && row.credential.access === owner.accessToken && credentialGeneration(row.credential) === owner.generation
39
+ && anthropicCooldownRecoveryFor(owner.provider).anthropicAccountIncarnation(owner.accountId) === owner.accountIncarnation
40
+ && captureProviderAccountQuotaEpoch(owner.provider) === owner.quotaEpoch;
41
+ }
@@ -4,6 +4,8 @@ import { bindAnthropicIdentity, resolveAnthropicAccountIdentity } from "./anthro
4
4
  import { generatePKCE } from "./pkce";
5
5
  import type { LocalTokenImportMode, OAuthController, OAuthCredentials } from "./types";
6
6
  import { outboundProxyConfigured, startupOutboundProxyConfigured } from "../lib/proxy-env";
7
+ import type { AnthropicInstanceId } from "../providers/anthropic-instance-id";
8
+ import { AnthropicLocalCliImportError } from "./store-anthropic-instance";
7
9
 
8
10
  const CLIENT_ID = atob("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
9
11
  const AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
@@ -178,9 +180,10 @@ export class AnthropicOAuthFlow extends OAuthCallbackFlow {
178
180
 
179
181
  export async function loginAnthropic(
180
182
  ctrl: OAuthController,
181
- opts?: { importLocal?: LocalTokenImportMode },
183
+ opts?: { importLocal?: LocalTokenImportMode; instance?: AnthropicInstanceId },
182
184
  ): Promise<OAuthCredentials> {
183
185
  const importLocal = opts?.importLocal ?? "off";
186
+ if (opts?.instance === "anthropic2" && importLocal !== "off") throw new AnthropicLocalCliImportError();
184
187
  if (importLocal !== "off") {
185
188
  const { detectClaudeCodeToken } = await import("./local-token-detect");
186
189
  const local = detectClaudeCodeToken();
@@ -1,6 +1,106 @@
1
1
  import { OAuthCallbackFlow } from "./callback-server";
2
2
  import type { OAuthController, OAuthCredentials } from "./types";
3
3
  import { generatePKCE } from "./pkce";
4
+ import { classifyChatgptRefreshFailure } from "../codex/chatgpt-refresh-failure";
5
+ import { readBoundedResponseBytes } from "../lib/bounded-body";
6
+
7
+ /**
8
+ * Per-fetch deadline for ChatGPT auth endpoint calls. The deviceauth grant got the
9
+ * same bound in #3898 after one stuck TCP connection held the login slot for the
10
+ * whole grant; a hung refresh would pin the refresh intent lock indefinitely.
11
+ */
12
+ export const CHATGPT_FETCH_TIMEOUT_MS = 30_000;
13
+
14
+ /** Non-HTTP failures retain no caller reason, upstream error, or cause. */
15
+ export class ChatGptTokenRequestError extends Error {
16
+ readonly terminal = false;
17
+
18
+ constructor(kind: "abort" | "timeout" | "transport") {
19
+ super(kind === "abort" ? "ChatGPT token request cancelled"
20
+ : kind === "timeout" ? "ChatGPT token request timed out" : "ChatGPT token request failed");
21
+ this.name = kind === "abort" ? "AbortError" : kind === "timeout" ? "TimeoutError" : "ChatGptTokenRequestError";
22
+ }
23
+ }
24
+
25
+ const CHATGPT_ERROR_BODY_MAX_BYTES = 16 * 1024;
26
+ const CHATGPT_SUCCESS_BODY_MAX_BYTES = 64 * 1024;
27
+
28
+ /** One deadline covers headers and body; every settled call detaches its caller. */
29
+ async function chatGptTokenRequest(
30
+ body: URLSearchParams,
31
+ label: "ChatGPT refresh" | "ChatGPT token exchange",
32
+ options: { signal?: AbortSignal; timeoutMs?: number },
33
+ ): Promise<OAuthCredentials> {
34
+ const controller = new AbortController();
35
+ const onAbort = () => controller.abort(new ChatGptTokenRequestError("abort"));
36
+ options.signal?.addEventListener("abort", onAbort, { once: true });
37
+ if (options.signal?.aborted) onAbort();
38
+ const timer = setTimeout(() => controller.abort(new ChatGptTokenRequestError("timeout")),
39
+ options.timeoutMs ?? CHATGPT_FETCH_TIMEOUT_MS);
40
+ let endpointError: ChatGptTokenError | undefined;
41
+ try {
42
+ controller.signal.throwIfAborted();
43
+ const response = await fetch(TOKEN_URL, {
44
+ method: "POST",
45
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
46
+ body: body.toString(),
47
+ signal: controller.signal,
48
+ });
49
+ const result = await readBoundedResponseBytes(response, {
50
+ signal: controller.signal,
51
+ maxBytes: response.ok ? CHATGPT_SUCCESS_BODY_MAX_BYTES : CHATGPT_ERROR_BODY_MAX_BYTES,
52
+ });
53
+ controller.signal.throwIfAborted();
54
+ const text = new TextDecoder().decode(result.bytes);
55
+ if (!response.ok) {
56
+ endpointError = chatGptTokenError(response.status, result.oversized ? "" : text, label);
57
+ throw endpointError;
58
+ }
59
+ if (result.oversized) throw new ChatGptTokenRequestError("transport");
60
+ return credsFromToken(JSON.parse(text) as Record<string, unknown>);
61
+ } catch (error) {
62
+ if (controller.signal.aborted) throw controller.signal.reason;
63
+ if (endpointError && error === endpointError) throw endpointError;
64
+ throw new ChatGptTokenRequestError("transport");
65
+ } finally {
66
+ clearTimeout(timer);
67
+ options.signal?.removeEventListener("abort", onAbort);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Token-endpoint failure carrying the HTTP status, the allowlisted OAuth error code,
73
+ * and a terminal verdict requiring an explicit grant-refusal code. The shared
74
+ * Codex classifier supplies the code vocabulary; free text is never grant evidence.
75
+ */
76
+ export class ChatGptTokenError extends Error {
77
+ constructor(
78
+ public readonly httpStatus: number,
79
+ public readonly oauthError: string | undefined,
80
+ public readonly terminal: boolean,
81
+ message: string,
82
+ ) {
83
+ super(message);
84
+ this.name = "ChatGptTokenError";
85
+ }
86
+ }
87
+
88
+ function chatGptTokenError(status: number, body: string, label: string): ChatGptTokenError {
89
+ const failure = classifyChatgptRefreshFailure(status, body);
90
+ // Reclassify the allowlisted code alone to reuse the shared terminal vocabulary
91
+ // without its description-only compatibility rule for other Codex callers.
92
+ const terminal = failure.reason !== "unknown" && failure.code !== undefined
93
+ && classifyChatgptRefreshFailure(status, JSON.stringify({ error: failure.code })).reason !== "unknown";
94
+ // The message carries the status and the allowlisted OAuth code only — never the
95
+ // free-text `error_description`, which can echo OAuth material into log surfaces
96
+ // (the same closed vocabulary the pool's noteChatgptRefreshFailure logs with).
97
+ return new ChatGptTokenError(
98
+ status,
99
+ failure.code,
100
+ terminal,
101
+ `${label} failed: ${status} code=${failure.code ?? "none"}`,
102
+ );
103
+ }
4
104
 
5
105
  const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
6
106
  const AUTH_URL = "https://auth.openai.com/oauth/authorize";
@@ -202,34 +302,16 @@ export class ChatGPTOAuthFlow extends OAuthCallbackFlow {
202
302
 
203
303
  async exchangeToken(code: string, _state: string, redirectUri: string): Promise<OAuthCredentials> {
204
304
  if (!this.#verifier) throw new Error("ChatGPT PKCE verifier not initialized");
205
- const resp = await fetch(TOKEN_URL, {
206
- method: "POST",
207
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
208
- body: new URLSearchParams({
209
- grant_type: "authorization_code",
210
- client_id: CLIENT_ID,
211
- code,
212
- redirect_uri: redirectUri,
213
- code_verifier: this.#verifier,
214
- }).toString(),
215
- });
216
- if (!resp.ok) {
217
- const errDesc = await safeErrorDescription(resp);
218
- throw new Error(`ChatGPT token exchange failed: ${resp.status} ${errDesc}`);
219
- }
220
- return credsFromToken((await resp.json()) as Record<string, unknown>);
305
+ return chatGptTokenRequest(new URLSearchParams({
306
+ grant_type: "authorization_code",
307
+ client_id: CLIENT_ID,
308
+ code,
309
+ redirect_uri: redirectUri,
310
+ code_verifier: this.#verifier,
311
+ }), "ChatGPT token exchange", { signal: this.ctrl.signal });
221
312
  }
222
313
  }
223
314
 
224
- function safeErrorDescription(resp: Response): Promise<string> {
225
- return resp.text().catch(() => "").then(text => {
226
- try {
227
- const parsed = JSON.parse(text) as { error?: string; error_description?: string };
228
- return [parsed.error, parsed.error_description].filter(Boolean).join(": ") || `HTTP ${resp.status}`;
229
- } catch { return `HTTP ${resp.status}`; }
230
- });
231
- }
232
-
233
315
  /**
234
316
  * How the user proves identity. `browser` runs the localhost:1455 callback flow;
235
317
  * `device` runs the deviceauth grant, which needs no local browser or listener
@@ -255,21 +337,11 @@ export async function loginChatGPT(
255
337
  // Codex-rs uses JSON for refresh — intentional divergence; both accepted by auth.openai.com.
256
338
  export async function refreshChatGPTToken(
257
339
  refreshToken: string,
258
- options: { signal?: AbortSignal } = {},
340
+ options: { signal?: AbortSignal; timeoutMs?: number } = {},
259
341
  ): Promise<OAuthCredentials> {
260
- const resp = await fetch(TOKEN_URL, {
261
- method: "POST",
262
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
263
- body: new URLSearchParams({
264
- grant_type: "refresh_token",
265
- client_id: CLIENT_ID,
266
- refresh_token: refreshToken,
267
- }).toString(),
268
- signal: options.signal,
269
- });
270
- if (!resp.ok) {
271
- const errDesc = await safeErrorDescription(resp);
272
- throw new Error(`ChatGPT refresh failed: ${resp.status} ${errDesc}`);
273
- }
274
- return credsFromToken((await resp.json()) as Record<string, unknown>);
342
+ return chatGptTokenRequest(new URLSearchParams({
343
+ grant_type: "refresh_token",
344
+ client_id: CLIENT_ID,
345
+ refresh_token: refreshToken,
346
+ }), "ChatGPT refresh", options);
275
347
  }
@@ -1,3 +1,4 @@
1
+ import { isBuiltinAnthropicInstanceRow } from "../providers/anthropic-instance";
1
2
  /**
2
3
  * Generic OAuth multi-account 429 failover (#2568).
3
4
  *
@@ -157,7 +158,8 @@ export function kiroAutoSelection(
157
158
 
158
159
  /** True when this provider participates in generic rotation at all. */
159
160
  export function isGenericFailoverProvider(providerName: string, provider: OcxProviderConfig): boolean {
160
- return provider.authMode === "oauth" && !EXCLUDED_PROVIDERS.has(providerName);
161
+ return provider.authMode === "oauth" && !EXCLUDED_PROVIDERS.has(providerName)
162
+ && !isBuiltinAnthropicInstanceRow(providerName, provider);
161
163
  }
162
164
 
163
165
  /**
@@ -1,7 +1,8 @@
1
+ import { isAnthropicInstanceId } from "../providers/anthropic-instance-id";
1
2
  import type { MainAccountHardLockStatus } from "../codex/main-account-hard-lock";
2
3
  import type { MainAccountExternalUsageWarning } from "../codex/main-account-external-usage";
3
4
  import { getCodexAccountHealthSnapshot, type CodexCooldownSource } from "../codex/routing";
4
- import { getAnthropicAccountHealthSnapshot } from "./anthropic-routing";
5
+ import { anthropicRoutingFor } from "./anthropic-routing";
5
6
  import { isAccountNeedsReauth } from "../codex/account-runtime-state";
6
7
  import { getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord } from "../codex/account-store";
7
8
  import { MAIN_CODEX_ACCOUNT_ID } from "../codex/main-account";
@@ -10,7 +11,7 @@ import { LOCAL_MANAGEMENT_READ_PATHS } from "../lib/local-management-capability"
10
11
  import { maskAccountId } from "../lib/privacy";
11
12
  import { findLiveProxy } from "../server/proxy-liveness";
12
13
  import { fetchBoundLocalManagementRead } from "../server/local-management-read-client";
13
- import { loadAuthStore, peekAuthStore, peekOAuthRefreshIntent, readOAuthRefreshIntent } from "./store";
14
+ import { accountNeedsReauthForStatus, loadAuthStore, peekAuthStore, peekOAuthRefreshIntent, readOAuthRefreshIntent } from "./store";
14
15
  import type { ProviderAccount } from "./types";
15
16
 
16
17
  export type OAuthAccountHealth =
@@ -207,12 +208,13 @@ export function projectStoredOAuthAccountHealth(
207
208
  now = Date.now(),
208
209
  opts: { observeOnly?: boolean } = {},
209
210
  ): OAuthAccountHealth {
210
- const anthropicSnap = provider === "anthropic"
211
- ? getAnthropicAccountHealthSnapshot(account.id, now)
211
+ const anthropicSnap = isAnthropicInstanceId(provider)
212
+ ? anthropicRoutingFor(provider).getAnthropicAccountHealthSnapshot(account.id, now)
212
213
  : null;
214
+ const needsReauth = accountNeedsReauthForStatus(provider, account, now);
213
215
  return projectOAuthAccountHealth({
214
- needsReauth: account.needsReauth === true,
215
- reauthReason: account.needsReauth === true
216
+ needsReauth,
217
+ reauthReason: needsReauth
216
218
  ? (account.needsReauthReason ?? "refresh_failed")
217
219
  : undefined,
218
220
  cooldownUntilMs: anthropicSnap?.cooldownUntil,