@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
@@ -1,5 +1,7 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
- import type { CodexAccount } from "../types";
2
+ import type { CodexAccount, OcxConfig } from "../types";
3
+ import type { CodexAuthContext } from "./auth-context";
4
+ import { MAIN_CODEX_ACCOUNT_ID } from "./main-account";
3
5
 
4
6
  export const CODEX_ACCOUNT_LOG_LABEL_RE = /^p[a-f0-9]{6}$/;
5
7
 
@@ -22,6 +24,17 @@ export function codexAccountLogLabel(account: CodexAccount): string {
22
24
  : fallbackCodexAccountLogLabel(account.id);
23
25
  }
24
26
 
27
+ /** Effective durable label for a resolved Codex Pool account. */
28
+ export function codexAuthContextLogLabel(
29
+ authCtx: CodexAuthContext,
30
+ config: Pick<OcxConfig, "codexAccounts">,
31
+ ): "main" | `p${string}` | undefined {
32
+ if (authCtx.kind !== "pool" && authCtx.kind !== "main-pool") return undefined;
33
+ if (authCtx.accountId === MAIN_CODEX_ACCOUNT_ID) return "main";
34
+ const account = (config.codexAccounts ?? []).find(candidate => candidate.id === authCtx.accountId);
35
+ return account ? codexAccountLogLabel(account) as `p${string}` : undefined;
36
+ }
37
+
25
38
  export function withCodexAccountLogLabel(
26
39
  account: Omit<CodexAccount, "logLabel"> & Partial<Pick<CodexAccount, "logLabel">>,
27
40
  existingAccounts: readonly CodexAccount[],
@@ -1,3 +1,10 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import {
3
+ atomicWriteFile,
4
+ getConfigPath,
5
+ saveConfigPreservingClaudeCode,
6
+ withConfigMutationLockSync,
7
+ } from "../config";
1
8
  import { removeCodexAccountCredential } from "./account-store";
2
9
  import { clearAccountNeedsReauth } from "./account-runtime-state";
3
10
  import { getMainChatgptAccountId } from "./auth-collision";
@@ -5,18 +12,43 @@ import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "./main-account";
5
12
  import { clearAccountQuota } from "./quota";
6
13
  import { clearCodexUpstreamHealthForAccount, clearThreadAccountMapForAccount } from "./routing";
7
14
  import { invalidateCodexWebSocketsForAccount } from "./websocket-registry";
8
- import { clearMainAccountInfoCache } from "./main-account-cache";
15
+ import { clearMainAccountCredentialPresence, clearMainAccountInfoCache } from "./main-account-cache";
9
16
  import { forgetCodexAccountPause } from "./account-pause";
17
+ import { clearCodexAccountPin, forgetCodexAccountPriority } from "./account-priority";
18
+ import { codexAccountNamespaceEntries, codexAccountPickerEnabled } from "./account-namespaces";
10
19
  import type { OcxConfig } from "../types";
11
20
 
12
21
  let observedMainChatgptAccountId: string | undefined;
13
22
 
23
+ export class CodexAccountDeleteCleanupError extends Error {
24
+ constructor() {
25
+ super("Account deletion was saved, but local credential cleanup did not complete. Retry removal.");
26
+ this.name = "CodexAccountDeleteCleanupError";
27
+ }
28
+ }
29
+
30
+ export class CodexAccountDeleteRollbackError extends Error {
31
+ constructor() {
32
+ super("Account deletion failed and the previous config could not be restored. Restart before retrying.");
33
+ this.name = "CodexAccountDeleteRollbackError";
34
+ }
35
+ }
36
+
14
37
  export function purgeCodexAccountRuntimeState(accountId: string): void {
15
38
  clearAccountNeedsReauth(accountId);
16
39
  clearAccountQuota(accountId);
17
40
  clearThreadAccountMapForAccount(accountId);
18
41
  clearCodexUpstreamHealthForAccount(accountId);
19
- if (accountId === MAIN_CODEX_ACCOUNT_ID) clearMainAccountInfoCache();
42
+ if (accountId === MAIN_CODEX_ACCOUNT_ID) {
43
+ clearMainAccountInfoCache();
44
+ clearMainAccountCredentialPresence();
45
+ }
46
+ }
47
+
48
+ function purgeMainCodexAccountRuntimeState(): void {
49
+ purgeCodexAccountRuntimeState(MAIN_CODEX_ACCOUNT_ID);
50
+ setMainAccountPlan(null);
51
+ invalidateCodexWebSocketsForAccount(MAIN_CODEX_ACCOUNT_ID);
20
52
  }
21
53
 
22
54
  /**
@@ -34,22 +66,107 @@ export function reconcileMainCodexAccountRuntimeState(): boolean {
34
66
  observedMainChatgptAccountId = currentAccountId;
35
67
  if (previousAccountId === undefined || previousAccountId === currentAccountId) return false;
36
68
 
37
- purgeCodexAccountRuntimeState(MAIN_CODEX_ACCOUNT_ID);
38
- setMainAccountPlan(null);
39
- invalidateCodexWebSocketsForAccount(MAIN_CODEX_ACCOUNT_ID);
69
+ purgeMainCodexAccountRuntimeState();
70
+ return true;
71
+ }
72
+
73
+ /**
74
+ * Apply a transaction-confirmed physical native-login change without waiting for
75
+ * a later auth.json observation. The caller owns credential commit/rollback.
76
+ */
77
+ export function applyConfirmedMainCodexAccountTransition(
78
+ fromAccountId: string,
79
+ toAccountId: string,
80
+ ): boolean {
81
+ if (!fromAccountId || !toAccountId || fromAccountId === toAccountId) {
82
+ if (toAccountId) observedMainChatgptAccountId = toAccountId;
83
+ return false;
84
+ }
85
+ observedMainChatgptAccountId = toAccountId;
86
+ purgeMainCodexAccountRuntimeState();
40
87
  return true;
41
88
  }
42
89
 
43
90
  export function resetMainCodexAccountIdentityTrackingForTests(): void {
44
91
  observedMainChatgptAccountId = undefined;
92
+ clearMainAccountCredentialPresence();
93
+ }
94
+
95
+ function restoreRuntimeConfig(target: OcxConfig, snapshot: OcxConfig): void {
96
+ for (const key of Object.keys(target) as Array<keyof OcxConfig>) delete target[key];
97
+ Object.assign(target, snapshot);
98
+ }
99
+
100
+ function restorePersistedConfig(configPath: string, previousBytes: string): void {
101
+ try {
102
+ if (readFileSync(configPath, "utf8") === previousBytes) return;
103
+ } catch (error) {
104
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
105
+ }
106
+ atomicWriteFile(configPath, previousBytes);
45
107
  }
46
108
 
47
- export function deleteCodexAccount(runtimeConfig: OcxConfig, accountId: string): void {
48
- removeCodexAccountCredential(accountId);
49
- runtimeConfig.codexAccounts = (runtimeConfig.codexAccounts ?? [])
50
- .filter(account => account.isMain || account.id !== accountId);
51
- forgetCodexAccountPause(runtimeConfig, accountId);
52
- if (runtimeConfig.activeCodexAccountId === accountId) runtimeConfig.activeCodexAccountId = undefined;
53
- purgeCodexAccountRuntimeState(accountId);
54
- invalidateCodexWebSocketsForAccount(accountId);
109
+ /**
110
+ * Delete a stored account while retaining its selector binding.
111
+ *
112
+ * When the runtime config is backed by an existing config.json, commit the config deletion before
113
+ * credentials or runtime state are destroyed. Transient callers intentionally skip durable config
114
+ * persistence because they have no durable account row to protect. The whole sequence shares the
115
+ * config mutation coordinator so a cooperating writer cannot re-add a persisted account between
116
+ * the durable config commit and credential cleanup.
117
+ *
118
+ * Returns true when a picker-visible row disappeared and the catalog must converge.
119
+ */
120
+ export function deleteCodexAccount(runtimeConfig: OcxConfig, accountId: string): boolean {
121
+ let cleanupFailed = false;
122
+ const pickerVisibilityChanged = withConfigMutationLockSync(() => {
123
+ const previousConfig = structuredClone(runtimeConfig);
124
+ const configPath = getConfigPath();
125
+ const hasPersistedConfig = existsSync(configPath);
126
+ const previousPersistedConfig = hasPersistedConfig ? readFileSync(configPath, "utf8") : undefined;
127
+ const hadStoredAccount = (runtimeConfig.codexAccounts ?? [])
128
+ .some(account => !account.isMain && account.id === accountId);
129
+ const hadVisiblePickerBinding = hadStoredAccount
130
+ && codexAccountPickerEnabled(runtimeConfig)
131
+ && codexAccountNamespaceEntries(runtimeConfig)
132
+ .some(([, boundAccountId]) => boundAccountId === accountId);
133
+
134
+ runtimeConfig.codexAccounts = (runtimeConfig.codexAccounts ?? [])
135
+ .filter(account => account.isMain || account.id !== accountId);
136
+ forgetCodexAccountPause(runtimeConfig, accountId);
137
+ forgetCodexAccountPriority(runtimeConfig, accountId);
138
+ clearCodexAccountPin(runtimeConfig, accountId);
139
+ if (runtimeConfig.activeCodexAccountId === accountId) runtimeConfig.activeCodexAccountId = undefined;
140
+
141
+ if (previousPersistedConfig !== undefined) {
142
+ try {
143
+ // Persist first for durable configs. Destructive cleanup below must never run for a
144
+ // deletion that failed to commit. Transient configs intentionally skip this write.
145
+ saveConfigPreservingClaudeCode(runtimeConfig);
146
+ } catch (error) {
147
+ restoreRuntimeConfig(runtimeConfig, previousConfig);
148
+ try {
149
+ restorePersistedConfig(configPath, previousPersistedConfig);
150
+ } catch {
151
+ throw new CodexAccountDeleteRollbackError();
152
+ }
153
+ throw error;
154
+ }
155
+ }
156
+
157
+ try {
158
+ removeCodexAccountCredential(accountId);
159
+ purgeCodexAccountRuntimeState(accountId);
160
+ invalidateCodexWebSocketsForAccount(accountId);
161
+ } catch {
162
+ // Do not throw through the mutation coordinator after config.json committed: that would roll
163
+ // back only the SQLite generation transaction, not the already-atomic file replacement.
164
+ cleanupFailed = true;
165
+ }
166
+
167
+ return hadVisiblePickerBinding;
168
+ });
169
+
170
+ if (cleanupFailed) throw new CodexAccountDeleteCleanupError();
171
+ return pickerVisibilityChanged;
55
172
  }
@@ -1,6 +1,10 @@
1
1
  import type { CodexAccount, OcxConfig } from "../types";
2
2
  import { COMBO_NAMESPACE } from "../combos/types";
3
3
  import { OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
4
+ import {
5
+ POLICY_NAMESPACE,
6
+ routingProfileAliasNamespacePrefixes,
7
+ } from "../routing/profile-namespace";
4
8
  import {
5
9
  CODEX_ACCOUNT_LOG_LABEL_RE,
6
10
  createCodexAccountLogLabel,
@@ -21,6 +25,7 @@ const RESERVED_NAMESPACE_KEYS = new Set([
21
25
  "constructor",
22
26
  COMBO_NAMESPACE,
23
27
  OPENAI_CODEX_PROVIDER_ID,
28
+ POLICY_NAMESPACE,
24
29
  ].map(codexProviderNamespaceKey));
25
30
  const PUBLIC_ACCOUNT_SELECTOR_MAX_ATTEMPTS = 16;
26
31
 
@@ -68,17 +73,21 @@ function claimNamespace(requested: string, used: Set<string>): string {
68
73
  return namespace;
69
74
  }
70
75
 
71
- function occupiedNamespaces(config: Pick<OcxConfig, "combos" | "providers">): Set<string> {
76
+ /** Collect every public namespace that a generated account selector must not claim. */
77
+ function occupiedNamespaces(
78
+ config: Pick<OcxConfig, "combos" | "providers" | "routingProfiles">,
79
+ ): Set<string> {
72
80
  return new Set([
73
81
  ...Object.keys(config.providers).map(codexProviderNamespaceKey),
74
82
  ...comboAliasNamespaces(config),
83
+ ...routingProfileAliasNamespacePrefixes(config),
75
84
  ...RESERVED_NAMESPACE_KEYS,
76
85
  ]);
77
86
  }
78
87
 
79
88
  /** Build an initial account-selector map without deriving public selectors from aliases or ids. */
80
89
  export function defaultCodexAccountNamespaces(
81
- config: Pick<OcxConfig, "codexAccounts" | "combos" | "providers">,
90
+ config: Pick<OcxConfig, "codexAccounts" | "combos" | "providers" | "routingProfiles">,
82
91
  ): Record<string, string> {
83
92
  const namespaces: Record<string, string> = {};
84
93
  const used = occupiedNamespaces(config);
@@ -99,13 +108,39 @@ export function defaultCodexAccountNamespaces(
99
108
  return namespaces;
100
109
  }
101
110
 
111
+ /**
112
+ * Initialize generated selectors only for an explicit opt-in with no existing bindings.
113
+ * A true result means the map was replaced and the caller must persist the updated config.
114
+ */
115
+ export function initializeDefaultCodexAccountNamespaces(
116
+ config: Pick<
117
+ OcxConfig,
118
+ | "codexAccountPickerEnabled"
119
+ | "codexAccountNamespaces"
120
+ | "codexAccounts"
121
+ | "combos"
122
+ | "providers"
123
+ | "routingProfiles"
124
+ >,
125
+ ): boolean {
126
+ if (config.codexAccountPickerEnabled !== true
127
+ || Object.keys(config.codexAccountNamespaces ?? {}).length > 0) return false;
128
+
129
+ const namespaces = defaultCodexAccountNamespaces(config);
130
+ config.codexAccountNamespaces = namespaces;
131
+ return true;
132
+ }
133
+
102
134
  /**
103
135
  * Add one account to a generated map without renaming or replacing explicit existing entries.
104
136
  * The account-creation layer must reject a new id that already equals an existing selector key.
105
137
  * A true result means the map was mutated in place; callers must persist the updated config.
106
138
  */
107
139
  export function appendDefaultCodexAccountNamespace(
108
- config: Pick<OcxConfig, "codexAccountNamespaces" | "codexAccounts" | "combos" | "providers">,
140
+ config: Pick<
141
+ OcxConfig,
142
+ "codexAccountNamespaces" | "codexAccounts" | "combos" | "providers" | "routingProfiles"
143
+ >,
109
144
  account: Pick<CodexAccount, "id" | "isMain" | "logLabel">,
110
145
  ): boolean {
111
146
  const namespaces = config.codexAccountNamespaces;
@@ -147,3 +182,14 @@ export function codexAccountNamespaceEntries(
147
182
  return Object.entries(config.codexAccountNamespaces ?? {})
148
183
  .map(([namespace, accountId]) => [namespace, normalizeCodexAccountNamespaceTarget(accountId)]);
149
184
  }
185
+
186
+ /**
187
+ * Whether generated account-qualified rows are enabled for catalog discovery.
188
+ * A non-empty hand-written map predating the explicit override remains enabled.
189
+ */
190
+ export function codexAccountPickerEnabled(
191
+ config: Pick<OcxConfig, "codexAccountNamespaces" | "codexAccountPickerEnabled">,
192
+ ): boolean {
193
+ return (config.codexAccountPickerEnabled === undefined || config.codexAccountPickerEnabled === true)
194
+ && Object.keys(config.codexAccountNamespaces ?? {}).length > 0;
195
+ }
@@ -0,0 +1,83 @@
1
+ import { isValidCodexAccountId, MAIN_CODEX_ACCOUNT_ID } from "./account-id";
2
+ import { DEFAULT_ACCOUNT_PRIORITY, normalizeAccountPriority } from "./pool-rotation";
3
+ import type { OcxConfig } from "../types";
4
+
5
+ /**
6
+ * Which ids may carry a selection order: any pool account, plus the synthetic
7
+ * `__main__` Desktop login. Owned here rather than by the config schema because
8
+ * every writer needs it — the schema rejects a bad key on load, but the management
9
+ * API has to reject one before `setCodexAccountPriority` persists it as an own
10
+ * property that the schema would then reject, degrading the whole map.
11
+ */
12
+ export function isCodexAccountPriorityKey(key: unknown): key is string {
13
+ return key === MAIN_CODEX_ACCOUNT_ID || isValidCodexAccountId(key);
14
+ }
15
+
16
+ /**
17
+ * Persisted selection order for one account: higher numbers are used earlier.
18
+ * Stored as a config sidecar rather than a `codexAccounts` row field because the
19
+ * Codex Desktop login (`__main__`) has no row and must be orderable too.
20
+ */
21
+ export function getCodexAccountPriority(config: OcxConfig, accountId: string): number {
22
+ return codexAccountPriorityLookup(config)(accountId);
23
+ }
24
+
25
+ /**
26
+ * Write one account's selection order. The default is stored as absence, so a
27
+ * pool that was never ordered keeps no map at all and routing takes its fast path.
28
+ * Entries are rebuilt through `Object.fromEntries` so a reserved key such as
29
+ * `__proto__` becomes an own data property instead of invoking a prototype setter.
30
+ */
31
+ export function setCodexAccountPriority(config: OcxConfig, accountId: string, priority: number): void {
32
+ const entries = new Map(Object.entries(config.codexAccountPriorities ?? {}));
33
+ if (priority === DEFAULT_ACCOUNT_PRIORITY) entries.delete(accountId);
34
+ else entries.set(accountId, priority);
35
+
36
+ if (entries.size > 0) config.codexAccountPriorities = Object.fromEntries(entries);
37
+ else delete config.codexAccountPriorities;
38
+ }
39
+
40
+ export function forgetCodexAccountPriority(config: OcxConfig, accountId: string): void {
41
+ setCodexAccountPriority(config, accountId, DEFAULT_ACCOUNT_PRIORITY);
42
+ }
43
+
44
+ /**
45
+ * Stable lookup for one selection pass. Routing calls this once per pick and
46
+ * hands the closure to `selectPriorityTier`, so a pool without stored order pays
47
+ * a single map read rather than one per candidate.
48
+ */
49
+ export function codexAccountPriorityLookup(config: OcxConfig): (accountId: string) => number {
50
+ const priorities = config.codexAccountPriorities;
51
+ if (!priorities) return () => DEFAULT_ACCOUNT_PRIORITY;
52
+ return accountId => (
53
+ Object.hasOwn(priorities, accountId)
54
+ ? normalizeAccountPriority(priorities[accountId])
55
+ : DEFAULT_ACCOUNT_PRIORITY
56
+ );
57
+ }
58
+
59
+ /**
60
+ * The account an operator most recently selected by hand. While pinned, priority
61
+ * never preempts upward: the pin is a tier *ceiling* for round-robin/fill-first --
62
+ * `selectPriorityTier` skips every tier above the pinned account's, so higher-ordered
63
+ * accounts are suppressed rather than the pinned one being guaranteed -- and a veto in
64
+ * the quota path, until the account crosses the auto-switch threshold.
65
+ */
66
+ export function pinnedCodexAccountId(config: OcxConfig): string | undefined {
67
+ return config.activeCodexAccountPinned;
68
+ }
69
+
70
+ export function isCodexAccountPinned(config: OcxConfig, accountId: string): boolean {
71
+ return config.activeCodexAccountPinned === accountId;
72
+ }
73
+
74
+ export function setCodexAccountPin(config: OcxConfig, accountId: string): void {
75
+ config.activeCodexAccountPinned = accountId;
76
+ }
77
+
78
+ /** Release the pin. With `accountId` given, only when it is the pinned account. */
79
+ export function clearCodexAccountPin(config: OcxConfig, accountId?: string): void {
80
+ if (accountId === undefined || config.activeCodexAccountPinned === accountId) {
81
+ delete config.activeCodexAccountPinned;
82
+ }
83
+ }
@@ -386,6 +386,19 @@ function findFreshCredentialForGrant(
386
386
  return null;
387
387
  }
388
388
 
389
+ async function notePlanFromRefreshedAccessToken(
390
+ id: string,
391
+ accessToken: string,
392
+ generation: number,
393
+ ): Promise<void> {
394
+ try {
395
+ const { noteCodexAccountAccessToken } = await import("./plan-from-token");
396
+ noteCodexAccountAccessToken(id, accessToken, generation);
397
+ } catch {
398
+ // Derived plan metadata must not fail credential refresh.
399
+ }
400
+ }
401
+
389
402
  export async function getValidCodexToken(id: string): Promise<CodexTokenResult> {
390
403
  const record = readCodexAccountRecord(id);
391
404
  const cred = record?.deletedAt == null ? record?.credential : undefined;
@@ -415,10 +428,12 @@ export async function getValidCodexToken(id: string): Promise<CodexTokenResult>
415
428
  if (!saveCodexAccountCredentialIfGeneration(id, current.generation, refreshed.credential)) {
416
429
  throw new CodexCredentialGenerationConflictError();
417
430
  }
431
+ const generation = current.generation + 1;
432
+ await notePlanFromRefreshedAccessToken(id, refreshed.credential.accessToken, generation);
418
433
  return {
419
434
  accessToken: refreshed.credential.accessToken,
420
435
  chatgptAccountId: refreshed.credential.chatgptAccountId,
421
- generation: current.generation + 1,
436
+ generation,
422
437
  };
423
438
  }
424
439
  return getValidCodexToken(id);
@@ -491,11 +506,22 @@ export async function getValidCodexToken(id: string): Promise<CodexTokenResult>
491
506
  throw new TokenRefreshError(reason, `Codex token refresh failed (${reason}); reauthenticate the account.`);
492
507
  }
493
508
  const data = (await res.json()) as { access_token: string; refresh_token?: string; expires_in: number };
509
+ // Guard against a missing/non-finite/negative expires_in (malformed upstream
510
+ // response): a NaN expiry would never compare as expired, and a negative
511
+ // duration would stamp an already-past expiry — both block refresh semantics.
512
+ const expiresIn =
513
+ typeof data.expires_in === "number" && Number.isFinite(data.expires_in) && data.expires_in >= 0
514
+ ? data.expires_in
515
+ : 3600;
516
+ // The computed timestamp itself must stay finite: Number.MAX_VALUE passes
517
+ // Number.isFinite but overflows to Infinity once multiplied by 1000.
518
+ const expiresAt = Date.now() + expiresIn * 1000;
519
+ const safeExpiresAt = Number.isFinite(expiresAt) ? expiresAt : Date.now() + 3600 * 1000;
494
520
 
495
521
  const updated: CodexAccountCredentials = {
496
522
  accessToken: data.access_token,
497
523
  refreshToken: data.refresh_token ?? lockedCred.refreshToken,
498
- expiresAt: Date.now() + data.expires_in * 1000,
524
+ expiresAt: safeExpiresAt,
499
525
  chatgptAccountId: lockedCred.chatgptAccountId,
500
526
  };
501
527
  if (!saveCodexAccountCredentialIfGeneration(id, startGeneration, updated)) {
@@ -509,6 +535,7 @@ export async function getValidCodexToken(id: string): Promise<CodexTokenResult>
509
535
  flight = { promise: refreshPromise, startedAt: Date.now(), abort };
510
536
  refreshLocks.set(refreshGrantFingerprint, flight);
511
537
  const result = await refreshPromise;
538
+ await notePlanFromRefreshedAccessToken(id, result.accessToken, result.generation);
512
539
  return {
513
540
  accessToken: result.accessToken,
514
541
  chatgptAccountId: result.chatgptAccountId,
@@ -3,14 +3,37 @@ import { isAccountNeedsReauth } from "./account-runtime-state";
3
3
  import { MAIN_CODEX_ACCOUNT_ID, isMainAccountTokenLive } from "./main-account";
4
4
  import { hasLegacyMainCodexPoolAccount, isSelectableCodexPoolAccount } from "./account-id";
5
5
  import type { OcxConfig } from "../types";
6
+ import { isNativeMainTrafficBlocked } from "./native-profile-startup";
6
7
 
7
- export function isCodexAccountUsable(config: OcxConfig, accountId: string): boolean {
8
+ export interface CodexAccountUsabilityOptions {
9
+ /** Route using cached runtime state only; the caller must reject selected main before auth. */
10
+ nativeMainSelectionOnly?: boolean;
11
+ /** Test seam for proving whether routing attempted a physical native-token read. */
12
+ isMainAccountTokenLive?: typeof isMainAccountTokenLive;
13
+ /** Confirmed account ids for an account-gated model; omitted for ordinary native models. */
14
+ modelEligibleAccountIds?: ReadonlySet<string>;
15
+ }
16
+
17
+ export function isCodexAccountUsable(
18
+ config: OcxConfig,
19
+ accountId: string,
20
+ options: CodexAccountUsabilityOptions = {},
21
+ ): boolean {
22
+ if (options.modelEligibleAccountIds && !options.modelEligibleAccountIds.has(accountId)) return false;
8
23
  if (accountId === MAIN_CODEX_ACCOUNT_ID) {
24
+ // Startup recovery owns the physical auth/vault boundary. Never parse or select
25
+ // native __main__ while an encrypted switch journal is pending or inconclusive.
26
+ if (!options.nativeMainSelectionOnly && isNativeMainTrafficBlocked()) return false;
9
27
  // A legacy pool row with the sentinel makes an active `__main__` ambiguous.
10
28
  // Fail closed until the authenticated compatibility-delete path removes it.
11
29
  if (hasLegacyMainCodexPoolAccount(config.codexAccounts)) return false;
30
+ if (isAccountNeedsReauth(accountId)) return false;
31
+ // A selection-only caller owns the recovery/drain fence and will reject main
32
+ // before reservation or token materialization. Treat cached main as a routing
33
+ // candidate without touching the credential file so affinity is not rebound.
34
+ if (options.nativeMainSelectionOnly) return true;
12
35
  // Main account: credential is the read-only ~/.codex/auth.json token (Option A).
13
- return isMainAccountTokenLive() && !isAccountNeedsReauth(accountId);
36
+ return (options.isMainAccountTokenLive ?? isMainAccountTokenLive)();
14
37
  }
15
38
  const exists = (config.codexAccounts ?? [])
16
39
  .some(account => isSelectableCodexPoolAccount(account) && account.id === accountId);