@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -1,4 +1,4 @@
1
- import { realpathSync, statSync } from "node:fs";
1
+ import { readFileSync, realpathSync, statSync } from "node:fs";
2
2
  import { isAbsolute, join, resolve } from "node:path";
3
3
  import { expandUserPath } from "../config";
4
4
  import { defaultCodexHome } from "./home";
@@ -34,6 +34,85 @@ export function getCodexHome(): string {
34
34
  return resolveCodexHome();
35
35
  }
36
36
 
37
+ export interface CodexSqliteHomeDeps {
38
+ env?: NodeJS.ProcessEnv;
39
+ cwd?: () => string;
40
+ codexHome?: string;
41
+ readConfig?: (path: string) => string;
42
+ }
43
+
44
+ type RootTomlStringState =
45
+ | { kind: "absent" }
46
+ | { kind: "value"; value: string }
47
+ | { kind: "invalid" };
48
+
49
+ /**
50
+ * Parse the authoritative SQLite setting without changing the tolerant helper
51
+ * used by injection/catalog readers. History ownership must distinguish a
52
+ * missing key from a present value that Codex cannot interpret as a path.
53
+ */
54
+ function readAuthoritativeRootTomlString(content: string, key: string): RootTomlStringState {
55
+ let parsed: unknown;
56
+ try {
57
+ parsed = Bun.TOML.parse(content);
58
+ } catch {
59
+ return { kind: "invalid" };
60
+ }
61
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { kind: "invalid" };
62
+ const root = parsed as Record<string, unknown>;
63
+ if (!Object.prototype.hasOwnProperty.call(root, key)) return { kind: "absent" };
64
+ const value = root[key];
65
+ if (typeof value !== "string" || value.trim() === "") return { kind: "invalid" };
66
+ return { kind: "value", value: value.trim() };
67
+ }
68
+
69
+ /**
70
+ * Resolve Codex's SQLite state root at call time.
71
+ *
72
+ * Codex permits SQLite-backed state to live outside CODEX_HOME, especially for
73
+ * Windows Desktop sessions whose app-server runs in WSL. Keep the precedence
74
+ * identical to Codex: root config, then environment, then the effective home.
75
+ */
76
+ export function resolveCodexSqliteHome(deps: CodexSqliteHomeDeps = {}): string {
77
+ const codexHome = deps.codexHome ?? getCodexHome();
78
+ const readConfig = deps.readConfig ?? (path => readFileSync(path, "utf8"));
79
+ const configPath = join(codexHome, "config.toml");
80
+ let configured: RootTomlStringState = { kind: "absent" };
81
+ try {
82
+ configured = readAuthoritativeRootTomlString(readConfig(configPath), "sqlite_home");
83
+ } catch (cause) {
84
+ if ((cause as NodeJS.ErrnoException | undefined)?.code !== "ENOENT") {
85
+ throw new Error(
86
+ `Codex config could not be read while resolving sqlite_home: ${configPath}`,
87
+ { cause },
88
+ );
89
+ }
90
+ // A genuinely absent config cannot contain the authoritative root override,
91
+ // so only ENOENT may continue to the documented environment/home fallback.
92
+ }
93
+ if (configured.kind === "invalid") {
94
+ throw new Error(`Codex config has an invalid sqlite_home setting: ${configPath}`);
95
+ }
96
+ const raw = configured.kind === "value"
97
+ ? configured.value
98
+ : (deps.env ?? process.env).CODEX_SQLITE_HOME?.trim() || "";
99
+ if (!raw) return codexHome;
100
+ const expanded = expandUserPath(raw);
101
+ return isAbsolute(expanded)
102
+ ? resolve(expanded)
103
+ : resolve((deps.cwd ?? process.cwd)(), expanded);
104
+ }
105
+
106
+ /** Active Codex thread-state database, derived from the call-time SQLite root. */
107
+ export function resolveCodexStateDbPath(deps: CodexSqliteHomeDeps = {}): string {
108
+ return join(resolveCodexSqliteHome(deps), "state_5.sqlite");
109
+ }
110
+
111
+ /** Active Codex diagnostic-log database, derived from the call-time SQLite root. */
112
+ export function resolveCodexLogsDbPath(deps: CodexSqliteHomeDeps = {}): string {
113
+ return join(resolveCodexSqliteHome(deps), "logs_2.sqlite");
114
+ }
115
+
37
116
  export function tomlString(value: string): string {
38
117
  return JSON.stringify(value);
39
118
  }
@@ -0,0 +1,140 @@
1
+ import {
2
+ ConfigMutationLockError,
3
+ loadConfig,
4
+ mutatePersistedConfig,
5
+ } from "../config";
6
+ import type { CodexAccount, OcxConfig } from "../types";
7
+ import { isSelectableCodexPoolAccount, isValidCodexAccountId } from "./account-id";
8
+ import {
9
+ getCodexAccountCredential,
10
+ isCodexAccountGenerationLive,
11
+ readCodexAccountRecord,
12
+ } from "./account-store";
13
+ import { extractChatgptPlanType, codexPlanValue } from "./plan";
14
+
15
+ interface FreshPoolPlanUpdate {
16
+ accountId: string;
17
+ plan: string;
18
+ credentialGeneration: number;
19
+ }
20
+
21
+ function configuredPoolAccount(config: OcxConfig, accountId: string): CodexAccount | null {
22
+ if (!isValidCodexAccountId(accountId)) return null;
23
+ return (config.codexAccounts ?? [])
24
+ .find(account => account.id === accountId && isSelectableCodexPoolAccount(account)) ?? null;
25
+ }
26
+
27
+ function jwtPlanFromPoolCredential(accountId: string): string | undefined {
28
+ const cred = getCodexAccountCredential(accountId);
29
+ return cred ? extractChatgptPlanType(undefined, cred.accessToken) : undefined;
30
+ }
31
+
32
+ /**
33
+ * WHAM-wins gate (release-audit fix). A JWT-derived plan may be persisted only when no
34
+ * WHAM-sourced plan exists for the CURRENT credential generation. A token refresh bumps the
35
+ * generation, and the refreshed JWT is then genuinely newer information than the previous
36
+ * generation's WHAM read, so it may write again until WHAM re-observes. Records without
37
+ * provenance (legacy) stay writable so the original #1989 recovery still works.
38
+ */
39
+ function jwtMayWritePlan(account: CodexAccount, generation: number): boolean {
40
+ if (account.planSource !== "wham") return true;
41
+ const whamGeneration = account.planCredentialGeneration;
42
+ return whamGeneration !== undefined && generation > whamGeneration;
43
+ }
44
+
45
+ function collectJwtPoolPlanUpdates(runtimeConfig: OcxConfig): FreshPoolPlanUpdate[] {
46
+ const updates: FreshPoolPlanUpdate[] = [];
47
+ for (const account of (runtimeConfig.codexAccounts ?? []).filter(isSelectableCodexPoolAccount)) {
48
+ const jwtPlan = jwtPlanFromPoolCredential(account.id);
49
+ if (!jwtPlan || codexPlanValue(account.plan) === jwtPlan) continue;
50
+ const generation = readCodexAccountRecord(account.id)?.generation;
51
+ if (generation === undefined) continue;
52
+ if (!jwtMayWritePlan(account, generation)) continue;
53
+ updates.push({ accountId: account.id, plan: jwtPlan, credentialGeneration: generation });
54
+ }
55
+ return updates;
56
+ }
57
+
58
+ const appliedJwtPlans = new Map<string, string>();
59
+
60
+ function persistJwtPlanUpdates(runtimeConfig: OcxConfig, updates: FreshPoolPlanUpdate[]): void {
61
+ if (updates.length === 0) return;
62
+ let outcome: ReturnType<typeof mutatePersistedConfig<FreshPoolPlanUpdate[]>>;
63
+ try {
64
+ outcome = mutatePersistedConfig(persistedConfig => {
65
+ const accepted: FreshPoolPlanUpdate[] = [];
66
+ let changed = false;
67
+ for (const update of updates) {
68
+ if (!isCodexAccountGenerationLive(update.accountId, update.credentialGeneration)) continue;
69
+ const liveAccount = configuredPoolAccount(runtimeConfig, update.accountId);
70
+ const persistedAccount = configuredPoolAccount(persistedConfig, update.accountId);
71
+ if (!liveAccount || !persistedAccount) continue;
72
+ // Re-check against the PERSISTED row: another process may have landed a WHAM
73
+ // observation between collect and this mutation.
74
+ if (!jwtMayWritePlan(persistedAccount, update.credentialGeneration)) continue;
75
+ accepted.push(update);
76
+ if (persistedAccount.plan !== update.plan) {
77
+ persistedAccount.plan = update.plan;
78
+ changed = true;
79
+ }
80
+ if (persistedAccount.planSource !== "jwt" || persistedAccount.planCredentialGeneration !== update.credentialGeneration) {
81
+ persistedAccount.planSource = "jwt";
82
+ persistedAccount.planCredentialGeneration = update.credentialGeneration;
83
+ changed = true;
84
+ }
85
+ }
86
+ return { changed, value: accepted };
87
+ });
88
+ } catch (error) {
89
+ if (error instanceof ConfigMutationLockError) return;
90
+ throw error;
91
+ }
92
+ if (outcome.status === "unavailable") return;
93
+ for (const update of outcome.value) {
94
+ if (!isCodexAccountGenerationLive(update.accountId, update.credentialGeneration)) continue;
95
+ const liveAccount = configuredPoolAccount(runtimeConfig, update.accountId);
96
+ if (liveAccount) {
97
+ liveAccount.plan = update.plan;
98
+ liveAccount.planSource = "jwt";
99
+ liveAccount.planCredentialGeneration = update.credentialGeneration;
100
+ appliedJwtPlans.set(update.accountId, update.plan);
101
+ }
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Persist JWT `chatgpt_plan_type` onto `codexAccounts[].plan` when it contradicts the stored
107
+ * label. Generation-gated, same fail-closed lock policy as the WHAM plan patch. Does not
108
+ * overwrite a plan that already matches the token.
109
+ */
110
+ export function reconcileCodexPlansFromTokens(runtimeConfig: OcxConfig = loadConfig()): void {
111
+ persistJwtPlanUpdates(runtimeConfig, collectJwtPoolPlanUpdates(runtimeConfig));
112
+ }
113
+
114
+ export function resetJwtPlanNotesForTests(): void {
115
+ appliedJwtPlans.clear();
116
+ }
117
+
118
+ /** Apply one account's live token claim without blocking the credential read path. */
119
+ export function noteCodexAccountAccessToken(
120
+ accountId: string,
121
+ accessToken: string,
122
+ credentialGeneration: number,
123
+ ): void {
124
+ const jwtPlan = extractChatgptPlanType(undefined, accessToken);
125
+ if (!jwtPlan) return;
126
+ if (appliedJwtPlans.get(accountId) === jwtPlan) return;
127
+ try {
128
+ const runtimeConfig = loadConfig();
129
+ const live = configuredPoolAccount(runtimeConfig, accountId);
130
+ if (!live || codexPlanValue(live.plan) === jwtPlan) {
131
+ appliedJwtPlans.set(accountId, jwtPlan);
132
+ return;
133
+ }
134
+ if (!jwtMayWritePlan(live, credentialGeneration)) return;
135
+ persistJwtPlanUpdates(runtimeConfig, [{ accountId, plan: jwtPlan, credentialGeneration }]);
136
+ if (codexPlanValue(live.plan) === jwtPlan) appliedJwtPlans.set(accountId, jwtPlan);
137
+ } catch {
138
+ appliedJwtPlans.delete(accountId);
139
+ }
140
+ }
@@ -0,0 +1,40 @@
1
+ import { decodeJwtPayload } from "../oauth/chatgpt";
2
+
3
+ /** Preserve user/provider plan labels only when they are usable strings. */
4
+ export function codexPlanValue(value: unknown): string | undefined {
5
+ if (typeof value !== "string") return undefined;
6
+ return value.trim() ? value : undefined;
7
+ }
8
+
9
+ /** Case-insensitive key used by quota, capacity, and collision policy. */
10
+ export function codexPlanKey(value: unknown): string | undefined {
11
+ return codexPlanValue(value)?.trim().toLowerCase();
12
+ }
13
+
14
+ export function isThirtyDayOnlyCodexPlan(value: unknown): boolean {
15
+ const key = codexPlanKey(value);
16
+ return key === "go" || key === "free";
17
+ }
18
+
19
+ /**
20
+ * ChatGPT plan label from a live access/id token (`chatgpt_plan_type`).
21
+ * Used when WHAM has not run yet so a stale stored `free` cannot outrank the token (#1989).
22
+ */
23
+ export function extractChatgptPlanType(idToken?: string, accessToken?: string): string | undefined {
24
+ for (const token of [idToken, accessToken]) {
25
+ if (!token) continue;
26
+ const payload = decodeJwtPayload(token);
27
+ if (!payload) continue;
28
+ if (typeof payload.chatgpt_plan_type === "string") {
29
+ const plan = codexPlanValue(payload.chatgpt_plan_type);
30
+ if (plan) return plan;
31
+ }
32
+ const ns = payload["https://api.openai.com/auth"];
33
+ if (ns && typeof ns === "object") {
34
+ const nested = (ns as Record<string, unknown>).chatgpt_plan_type;
35
+ const plan = codexPlanValue(nested);
36
+ if (plan) return plan;
37
+ }
38
+ }
39
+ return undefined;
40
+ }
@@ -59,7 +59,7 @@ function readMarketplaceTable(configText: string, name: string): Record<string,
59
59
  for (let i = start; i < lines.length; i++) {
60
60
  const line = lines[i] ?? "";
61
61
  if (/^\s*\[/.test(line)) break; // next table starts; stop
62
- const m = line.match(/^\s*([A-Za-z0-9_-]+)\s*=\s*("(?:\\.|[^"])*"|'[^']*'|[^#]+?)\s*(?:#.*)?$/);
62
+ const m = line.match(/^\s*([A-Za-z0-9_-]+)\s*=\s*("(?:\\.|[^"\\])*"|'[^']*'|(?!["'])[^\s#]+)\s*(?:#.*)?$/);
63
63
  if (!m) continue;
64
64
  table[m[1]] = unquoteTomlValue(m[2].trim());
65
65
  }
@@ -19,6 +19,11 @@ const MAX_STICKY_LIMIT = 100;
19
19
  const DEFAULT_STRATEGY: OcxAccountPoolRotationStrategy = "quota";
20
20
  const VALID_STRATEGIES = new Set<OcxAccountPoolRotationStrategy>(["quota", "round-robin", "fill-first"]);
21
21
 
22
+ /** Selection order for an account with no stored preference: one flat tier. */
23
+ export const DEFAULT_ACCOUNT_PRIORITY = 0;
24
+ export const MIN_ACCOUNT_PRIORITY = -100;
25
+ export const MAX_ACCOUNT_PRIORITY = 100;
26
+
22
27
  /** Strict parse for management APIs — returns null instead of defaulting. */
23
28
  export function parseAccountPoolStrategy(raw: unknown): OcxAccountPoolRotationStrategy | null {
24
29
  if (typeof raw === "string" && VALID_STRATEGIES.has(raw as OcxAccountPoolRotationStrategy)) {
@@ -43,6 +48,71 @@ export function normalizeAccountPoolStickyLimit(raw: unknown): number {
43
48
  return parseAccountPoolStickyLimit(raw) ?? DEFAULT_STICKY_LIMIT;
44
49
  }
45
50
 
51
+ /** Strict parse for management APIs — returns null instead of defaulting. */
52
+ export function parseAccountPriority(raw: unknown): number | null {
53
+ if (
54
+ typeof raw === "number"
55
+ && Number.isInteger(raw)
56
+ && raw >= MIN_ACCOUNT_PRIORITY
57
+ && raw <= MAX_ACCOUNT_PRIORITY
58
+ ) {
59
+ return raw;
60
+ }
61
+ return null;
62
+ }
63
+
64
+ export function normalizeAccountPriority(raw: unknown): number {
65
+ return parseAccountPriority(raw) ?? DEFAULT_ACCOUNT_PRIORITY;
66
+ }
67
+
68
+ /**
69
+ * Narrow an already-eligible account list to the highest selection-order tier that
70
+ * still has usable quota. Priority is an *ordering* boundary layered on top of
71
+ * eligibility: it never admits an account the caller already filtered out, and it
72
+ * never keeps the pool on a tier whose every member is drained.
73
+ *
74
+ * Contract (each clause is load-bearing for "no behavior change when unconfigured"):
75
+ * - one distinct priority across `ids` (the unconfigured case) returns `ids` unchanged,
76
+ * so today's pick sequence is preserved byte for byte;
77
+ * - input order is preserved inside the returned tier, which keeps the `__main__`
78
+ * head-of-list bias and the first-index tie-break used by SWRR/lowest-usage;
79
+ * - every tier drained returns `ids` unchanged, reproducing today's
80
+ * stay-put-until-429 behavior rather than inventing a pick;
81
+ * - a `pinnedId` that is present *and* has headroom lowers the ceiling to its own
82
+ * tier, which is what makes a manual "use this now" survive round-robin and
83
+ * fill-first without any mutable selection state. A drained or absent pin is
84
+ * ignored, so the pin expires on its own once the account crosses the threshold.
85
+ */
86
+ export function selectPriorityTier(
87
+ ids: readonly string[],
88
+ priorityOf: (id: string) => number,
89
+ hasHeadroom: (id: string) => boolean,
90
+ pinnedId?: string,
91
+ ): readonly string[] {
92
+ // Readonly out as well as in: the no-change cases return the caller's own array, so a
93
+ // mutating caller would corrupt its input in exactly the cases that must not change.
94
+ const list = ids;
95
+ if (list.length <= 1) return list;
96
+
97
+ const priorities = list.map(priorityOf);
98
+ const firstPriority = priorities[0]!;
99
+ if (priorities.every(priority => priority === firstPriority)) return list;
100
+
101
+ let ceiling = Number.POSITIVE_INFINITY;
102
+ if (pinnedId !== undefined) {
103
+ const pinnedIndex = list.indexOf(pinnedId);
104
+ if (pinnedIndex >= 0 && hasHeadroom(pinnedId)) ceiling = priorities[pinnedIndex]!;
105
+ }
106
+
107
+ const tiers = [...new Set(priorities)].sort((a, b) => b - a);
108
+ for (const tier of tiers) {
109
+ if (tier > ceiling) continue;
110
+ const members = list.filter((_, index) => priorities[index] === tier);
111
+ if (members.some(hasHeadroom)) return members;
112
+ }
113
+ return list;
114
+ }
115
+
46
116
  function getOrCreateState(poolKey: string): SelectionState {
47
117
  let state = selectionState.get(poolKey);
48
118
  if (!state) {
@@ -60,7 +130,7 @@ function cloneSelectionState(state: SelectionState): SelectionState {
60
130
  };
61
131
  }
62
132
 
63
- function smoothWeightedIndex(ids: string[], state: SelectionState): number {
133
+ function smoothWeightedIndex(ids: readonly string[], state: SelectionState): number {
64
134
  let best = -1;
65
135
  let bestScore = Number.NEGATIVE_INFINITY;
66
136
  let total = 0;
@@ -87,7 +157,7 @@ function smoothWeightedIndex(ids: string[], state: SelectionState): number {
87
157
  * either the live map entry or a scratch/clone for dry-run peek.
88
158
  */
89
159
  function pickRoundRobinFromState(
90
- eligibleIds: string[],
160
+ eligibleIds: readonly string[],
91
161
  stickyLimit: number,
92
162
  state: SelectionState,
93
163
  commitSticky: boolean,
@@ -118,7 +188,7 @@ function pickRoundRobinFromState(
118
188
 
119
189
  export function pickRoundRobinAccount(
120
190
  poolKey: string,
121
- eligibleIds: string[],
191
+ eligibleIds: readonly string[],
122
192
  stickyLimit: number,
123
193
  ): string | null {
124
194
  return pickRoundRobinFromState(eligibleIds, stickyLimit, getOrCreateState(poolKey), true);
@@ -130,7 +200,7 @@ export function pickRoundRobinAccount(
130
200
  */
131
201
  export function peekRoundRobinAccount(
132
202
  poolKey: string,
133
- eligibleIds: string[],
203
+ eligibleIds: readonly string[],
134
204
  stickyLimit: number,
135
205
  ): string | null {
136
206
  const live = selectionState.get(poolKey);
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
2
2
  import path, { dirname, join, resolve } from "node:path";
3
3
  import { expandUserPath } from "../config";
4
4
  import { defaultCodexHome } from "./home";
@@ -70,7 +70,7 @@ export function parseTomlDocument(content: string): TomlDocument {
70
70
  current = section;
71
71
  continue;
72
72
  }
73
- const kv = line.match(/^\s*([A-Za-z0-9_.-]+)\s*=\s*("(?:\\.|[^"])*"|'[^']*'|[^\s#]+)\s*(?:#.*)?$/);
73
+ const kv = line.match(/^\s*([A-Za-z0-9_.-]+)\s*=\s*("(?:\\.|[^"\\])*"|'[^']*'|[^\s#]+)\s*(?:#.*)?$/);
74
74
  if (kv) current[kv[1]!] = parseTomlString(kv[2]!);
75
75
  }
76
76
 
@@ -252,9 +252,23 @@ export function discoverProjectCodexConfigPaths(options: {
252
252
  } = {}): string[] {
253
253
  const found = new Set<string>();
254
254
  const codexConfigPath = options.codexConfigPath ?? resolveCodexConfigPath();
255
+ // A parent walk can reach the user's home and rediscover this global file as
256
+ // `$HOME/.codex/config.toml`; compare real paths so symlink aliases are excluded too.
257
+ const normalizeExistingPath = (candidate: string): string | null => {
258
+ if (!existsSync(candidate)) return null;
259
+ let canonical: string;
260
+ try {
261
+ canonical = realpathSync.native(candidate);
262
+ } catch {
263
+ canonical = resolve(candidate);
264
+ }
265
+ return process.platform === "win32" ? canonical.toLowerCase() : canonical;
266
+ };
267
+ const globalConfigIdentity = normalizeExistingPath(codexConfigPath);
255
268
  const addIfExists = (projectRoot: string) => {
256
- const path = join(resolve(projectRoot), ".codex", "config.toml");
257
- if (existsSync(path)) found.add(path);
269
+ const candidate = join(resolve(projectRoot), ".codex", "config.toml");
270
+ const candidateIdentity = normalizeExistingPath(candidate);
271
+ if (candidateIdentity && candidateIdentity !== globalConfigIdentity) found.add(candidate);
258
272
  };
259
273
 
260
274
  let cwd = resolve(options.cwd ?? process.cwd());
@@ -339,7 +353,7 @@ export function summarizeProjectCodexIssue(warning: ProjectCodexConfigWarning):
339
353
 
340
354
  function humanizeProviderDetail(detail: string): string {
341
355
  if (detail === "opencode_go") return "OpenCode Go";
342
- if (detail.startsWith("opencode")) return "OpenCode";
356
+ if (/^opencode(?:$|[-_.:/])/.test(detail)) return "OpenCode";
343
357
  if (detail === "opencodex") return "OpenCodex";
344
358
  return detail;
345
359
  }
@@ -408,4 +422,4 @@ export function printProjectCodexConfigWarnings(
408
422
  }
409
423
  }
410
424
  return warnings;
411
- }
425
+ }