codex-multi-auth 2.17.0 → 2.17.3

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 (450) hide show
  1. package/.codex-plugin/plugin.json +9 -9
  2. package/LICENSE +21 -21
  3. package/README.md +142 -484
  4. package/assets/codex-multi-auth-icon.svg +39 -39
  5. package/assets/readme-hero.svg +31 -31
  6. package/config/README.md +31 -31
  7. package/config/codex-legacy.json +1221 -1221
  8. package/config/codex-modern.json +423 -423
  9. package/config/minimal-codex.json +15 -15
  10. package/dist/index.d.ts +0 -1
  11. package/dist/lib/account-policy.d.ts +18 -2
  12. package/dist/lib/account-policy.js +97 -40
  13. package/dist/lib/accounts/rate-limits.d.ts +0 -1
  14. package/dist/lib/accounts.d.ts +1 -8
  15. package/dist/lib/accounts.d.ts.map +1 -1
  16. package/dist/lib/accounts.js +7 -19
  17. package/dist/lib/api-route-store.d.ts +0 -1
  18. package/dist/lib/audit.d.ts +0 -1
  19. package/dist/lib/audit.js +43 -12
  20. package/dist/lib/auth/account-access.d.ts +0 -1
  21. package/dist/lib/auth/account-access.js +5 -1
  22. package/dist/lib/auth/auth.d.ts +4 -3
  23. package/dist/lib/auth/auth.js +220 -28
  24. package/dist/lib/auth/browser.d.ts +0 -1
  25. package/dist/lib/auth/callback-guidance.d.ts +0 -1
  26. package/dist/lib/auth/device-auth.d.ts +0 -1
  27. package/dist/lib/auth/index.d.ts +0 -1
  28. package/dist/lib/auth/org-override.d.ts +0 -1
  29. package/dist/lib/auth/server.d.ts +1 -2
  30. package/dist/lib/auth/server.js +100 -53
  31. package/dist/lib/auth/token-utils.d.ts +0 -1
  32. package/dist/lib/auth-rate-limit.d.ts +0 -1
  33. package/dist/lib/budget-guard.d.ts +16 -2
  34. package/dist/lib/budget-guard.js +123 -43
  35. package/dist/lib/capability-policy.d.ts +0 -1
  36. package/dist/lib/circuit-breaker.d.ts +20 -1
  37. package/dist/lib/circuit-breaker.js +24 -5
  38. package/dist/lib/cli.d.ts +0 -1
  39. package/dist/lib/codex-cli/index.d.ts +0 -1
  40. package/dist/lib/codex-cli/observability.d.ts +0 -1
  41. package/dist/lib/codex-cli/state.d.ts +0 -1
  42. package/dist/lib/codex-cli/sync.d.ts +0 -1
  43. package/dist/lib/codex-cli/writer.d.ts +0 -1
  44. package/dist/lib/codex-manager/account-credentials.d.ts +0 -1
  45. package/dist/lib/codex-manager/account-manager-commands.d.ts +0 -1
  46. package/dist/lib/codex-manager/account-pool-write.d.ts +0 -1
  47. package/dist/lib/codex-manager/active-account-sync.d.ts +6 -0
  48. package/dist/lib/codex-manager/active-account-sync.js +336 -0
  49. package/dist/lib/codex-manager/api-login-menu.d.ts +0 -1
  50. package/dist/lib/codex-manager/backend-category-entry.d.ts +0 -1
  51. package/dist/lib/codex-manager/backend-category-helpers.d.ts +0 -1
  52. package/dist/lib/codex-manager/backend-category-prompt.d.ts +0 -1
  53. package/dist/lib/codex-manager/backend-settings-controller.d.ts +0 -1
  54. package/dist/lib/codex-manager/backend-settings-entry.d.ts +0 -1
  55. package/dist/lib/codex-manager/backend-settings-helpers.d.ts +0 -1
  56. package/dist/lib/codex-manager/backend-settings-prompt.d.ts +0 -1
  57. package/dist/lib/codex-manager/backend-settings-schema.d.ts +0 -1
  58. package/dist/lib/codex-manager/behavior-settings-panel.d.ts +0 -1
  59. package/dist/lib/codex-manager/commands/account.d.ts +8 -3
  60. package/dist/lib/codex-manager/commands/account.js +46 -34
  61. package/dist/lib/codex-manager/commands/best.d.ts +0 -1
  62. package/dist/lib/codex-manager/commands/bridge.d.ts +0 -1
  63. package/dist/lib/codex-manager/commands/budget.d.ts +8 -3
  64. package/dist/lib/codex-manager/commands/budget.js +6 -4
  65. package/dist/lib/codex-manager/commands/check.d.ts +0 -1
  66. package/dist/lib/codex-manager/commands/config-explain.d.ts +0 -1
  67. package/dist/lib/codex-manager/commands/debug-bundle.d.ts +0 -1
  68. package/dist/lib/codex-manager/commands/forecast.d.ts +1 -2
  69. package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
  70. package/dist/lib/codex-manager/commands/forecast.js +2 -2
  71. package/dist/lib/codex-manager/commands/history.d.ts +0 -1
  72. package/dist/lib/codex-manager/commands/init-config.d.ts +0 -1
  73. package/dist/lib/codex-manager/commands/integrations.d.ts +0 -1
  74. package/dist/lib/codex-manager/commands/limits.d.ts +0 -1
  75. package/dist/lib/codex-manager/commands/models.d.ts +0 -1
  76. package/dist/lib/codex-manager/commands/monitor.d.ts +0 -1
  77. package/dist/lib/codex-manager/commands/report.d.ts +0 -1
  78. package/dist/lib/codex-manager/commands/resets.d.ts +0 -1
  79. package/dist/lib/codex-manager/commands/resets.js +9 -1
  80. package/dist/lib/codex-manager/commands/rotation.d.ts +0 -1
  81. package/dist/lib/codex-manager/commands/status.d.ts +0 -1
  82. package/dist/lib/codex-manager/commands/switch.d.ts +0 -1
  83. package/dist/lib/codex-manager/commands/uninstall.d.ts +0 -1
  84. package/dist/lib/codex-manager/commands/unpin.d.ts +0 -1
  85. package/dist/lib/codex-manager/commands/usage.d.ts +0 -1
  86. package/dist/lib/codex-manager/commands/verify.d.ts +0 -1
  87. package/dist/lib/codex-manager/commands/why-selected.d.ts +0 -1
  88. package/dist/lib/codex-manager/commands/workspace.d.ts +0 -1
  89. package/dist/lib/codex-manager/dashboard-display-panel.d.ts +0 -1
  90. package/dist/lib/codex-manager/dashboard-formatters.d.ts +0 -1
  91. package/dist/lib/codex-manager/dashboard-settings-controller.d.ts +0 -1
  92. package/dist/lib/codex-manager/dashboard-settings-data.d.ts +0 -1
  93. package/dist/lib/codex-manager/dashboard-settings-entry.d.ts +0 -1
  94. package/dist/lib/codex-manager/experimental-settings-entry.d.ts +0 -1
  95. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +0 -1
  96. package/dist/lib/codex-manager/experimental-settings-schema.d.ts +0 -1
  97. package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts +0 -1
  98. package/dist/lib/codex-manager/experimental-sync-target.d.ts +0 -1
  99. package/dist/lib/codex-manager/forecast-report-shared.d.ts +0 -1
  100. package/dist/lib/codex-manager/formatters/account-formatters.d.ts +0 -1
  101. package/dist/lib/codex-manager/formatters/index.d.ts +0 -1
  102. package/dist/lib/codex-manager/formatters/model-formatters.d.ts +0 -1
  103. package/dist/lib/codex-manager/formatters/quota-formatters.d.ts +0 -1
  104. package/dist/lib/codex-manager/formatters/text-style.d.ts +0 -1
  105. package/dist/lib/codex-manager/health-check.d.ts +0 -1
  106. package/dist/lib/codex-manager/health-check.js +1 -1
  107. package/dist/lib/codex-manager/help.d.ts +0 -1
  108. package/dist/lib/codex-manager/login-action-panel.d.ts +0 -1
  109. package/dist/lib/codex-manager/login-flow.d.ts +0 -1
  110. package/dist/lib/codex-manager/login-menu-actions.d.ts +0 -1
  111. package/dist/lib/codex-manager/login-menu-data.d.ts +0 -1
  112. package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
  113. package/dist/lib/codex-manager/login-menu-data.js +7 -3
  114. package/dist/lib/codex-manager/login-oauth.d.ts +0 -1
  115. package/dist/lib/codex-manager/login-workspace-choice.d.ts +0 -1
  116. package/dist/lib/codex-manager/manual-callback.d.ts +0 -1
  117. package/dist/lib/codex-manager/persist-selected-account.d.ts +0 -1
  118. package/dist/lib/codex-manager/quota-cache-helpers.d.ts +7 -2
  119. package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -1
  120. package/dist/lib/codex-manager/quota-cache-helpers.js +34 -19
  121. package/dist/lib/codex-manager/rate-limit-markers.d.ts +0 -1
  122. package/dist/lib/codex-manager/repair-commands.d.ts +0 -1
  123. package/dist/lib/codex-manager/repair-commands.js +1 -1
  124. package/dist/lib/codex-manager/settings-hub/backend.d.ts +0 -1
  125. package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +0 -1
  126. package/dist/lib/codex-manager/settings-hub/experimental.d.ts +0 -1
  127. package/dist/lib/codex-manager/settings-hub/index.d.ts +0 -1
  128. package/dist/lib/codex-manager/settings-hub/shared.d.ts +0 -1
  129. package/dist/lib/codex-manager/settings-hub-entry.d.ts +0 -1
  130. package/dist/lib/codex-manager/settings-hub-menu.d.ts +0 -1
  131. package/dist/lib/codex-manager/settings-hub-prompt.d.ts +0 -1
  132. package/dist/lib/codex-manager/settings-hub.d.ts +0 -1
  133. package/dist/lib/codex-manager/settings-panels.d.ts +0 -1
  134. package/dist/lib/codex-manager/settings-persist-utils.d.ts +0 -1
  135. package/dist/lib/codex-manager/settings-preview.d.ts +0 -1
  136. package/dist/lib/codex-manager/settings-write-queue.d.ts +0 -1
  137. package/dist/lib/codex-manager/statusline-settings-panel.d.ts +0 -1
  138. package/dist/lib/codex-manager/theme-settings-panel.d.ts +0 -1
  139. package/dist/lib/codex-manager/unified-settings-controller.d.ts +0 -1
  140. package/dist/lib/codex-manager/unified-settings-entry.d.ts +0 -1
  141. package/dist/lib/codex-manager.d.ts +1 -2
  142. package/dist/lib/codex-manager.js +5 -95
  143. package/dist/lib/concurrency.d.ts +0 -1
  144. package/dist/lib/config-schema.d.ts +0 -1
  145. package/dist/lib/config.d.ts +0 -1
  146. package/dist/lib/config.js +46 -241
  147. package/dist/lib/constants.d.ts +0 -1
  148. package/dist/lib/context-budget/model-context-windows.d.ts +0 -1
  149. package/dist/lib/context-budget-guard.d.ts +0 -1
  150. package/dist/lib/context-budget-response.d.ts +0 -1
  151. package/dist/lib/context-budget-response.js +8 -8
  152. package/dist/lib/context-overflow.d.ts +0 -1
  153. package/dist/lib/context-overflow.js +10 -10
  154. package/dist/lib/dashboard-settings.d.ts +0 -1
  155. package/dist/lib/entitlement-cache.d.ts +0 -1
  156. package/dist/lib/env-parsing.d.ts +13 -1
  157. package/dist/lib/env-parsing.js +21 -0
  158. package/dist/lib/errors.d.ts +0 -1
  159. package/dist/lib/forecast.d.ts +0 -1
  160. package/dist/lib/fs-retry.d.ts +0 -1
  161. package/dist/lib/health.d.ts +0 -1
  162. package/dist/lib/index.d.ts +0 -1
  163. package/dist/lib/integration-generators.d.ts +0 -1
  164. package/dist/lib/live-account-sync.d.ts +0 -1
  165. package/dist/lib/local-bridge.d.ts +0 -1
  166. package/dist/lib/local-bridge.js +4 -1
  167. package/dist/lib/local-client-tokens.d.ts +0 -1
  168. package/dist/lib/local-client-tokens.js +125 -30
  169. package/dist/lib/logger.d.ts +0 -1
  170. package/dist/lib/logger.js +11 -1
  171. package/dist/lib/model-capability-matrix.d.ts +0 -1
  172. package/dist/lib/model-route-policy.d.ts +1 -2
  173. package/dist/lib/named-backup-export.d.ts +0 -1
  174. package/dist/lib/oauth-success.html +125 -125
  175. package/dist/lib/oc-chatgpt-import-adapter.d.ts +0 -1
  176. package/dist/lib/oc-chatgpt-orchestrator.d.ts +0 -1
  177. package/dist/lib/oc-chatgpt-target-detection.d.ts +0 -1
  178. package/dist/lib/parallel-probe.d.ts +0 -1
  179. package/dist/lib/policy/runtime-policy-cache.d.ts +80 -0
  180. package/dist/lib/policy/runtime-policy-cache.js +310 -0
  181. package/dist/lib/policy/runtime-policy.d.ts +1 -2
  182. package/dist/lib/policy/runtime-policy.js +46 -19
  183. package/dist/lib/preemptive-quota-scheduler.d.ts +0 -1
  184. package/dist/lib/proactive-refresh.d.ts +0 -1
  185. package/dist/lib/prompts/codex-host-bridge.d.ts +0 -1
  186. package/dist/lib/prompts/codex-host-bridge.js +138 -138
  187. package/dist/lib/prompts/codex.d.ts +0 -1
  188. package/dist/lib/prompts/codex.js +79 -79
  189. package/dist/lib/prompts/fetch-utils.d.ts +0 -1
  190. package/dist/lib/prompts/host-codex-prompt.d.ts +0 -1
  191. package/dist/lib/quota-cache.d.ts +7 -4
  192. package/dist/lib/quota-cache.d.ts.map +1 -1
  193. package/dist/lib/quota-cache.js +117 -61
  194. package/dist/lib/quota-probe.d.ts +0 -1
  195. package/dist/lib/quota-probe.js +5 -2
  196. package/dist/lib/quota-readiness.d.ts +7 -3
  197. package/dist/lib/quota-readiness.d.ts.map +1 -1
  198. package/dist/lib/quota-readiness.js +25 -4
  199. package/dist/lib/recovery/constants.d.ts +0 -1
  200. package/dist/lib/recovery/storage.d.ts +0 -1
  201. package/dist/lib/recovery/types.d.ts +0 -1
  202. package/dist/lib/recovery.d.ts +0 -1
  203. package/dist/lib/redaction.d.ts +0 -1
  204. package/dist/lib/refresh-guardian.d.ts +0 -1
  205. package/dist/lib/refresh-lease.d.ts +0 -1
  206. package/dist/lib/refresh-queue.d.ts +0 -1
  207. package/dist/lib/request/client-cancellation.d.ts +0 -1
  208. package/dist/lib/request/error-classification.d.ts +0 -1
  209. package/dist/lib/request/failover-config.d.ts +0 -1
  210. package/dist/lib/request/failure-policy.d.ts +0 -1
  211. package/dist/lib/request/fetch-helpers.d.ts +0 -1
  212. package/dist/lib/request/headers.d.ts +0 -1
  213. package/dist/lib/request/helpers/input-utils.d.ts +0 -1
  214. package/dist/lib/request/helpers/input-utils.js +88 -34
  215. package/dist/lib/request/helpers/model-map.d.ts +0 -1
  216. package/dist/lib/request/helpers/tool-utils.d.ts +0 -1
  217. package/dist/lib/request/helpers/tool-utils.js +421 -4
  218. package/dist/lib/request/index.d.ts +0 -1
  219. package/dist/lib/request/rate-limit-backoff.d.ts +0 -1
  220. package/dist/lib/request/rate-limit-decision.d.ts +0 -1
  221. package/dist/lib/request/request-attempt-budget.d.ts +0 -1
  222. package/dist/lib/request/request-init.d.ts +0 -1
  223. package/dist/lib/request/request-resilience.d.ts +0 -1
  224. package/dist/lib/request/request-transformer.d.ts +0 -1
  225. package/dist/lib/request/request-transformer.js +50 -25
  226. package/dist/lib/request/response-compaction.d.ts +0 -1
  227. package/dist/lib/request/response-handler.d.ts +0 -1
  228. package/dist/lib/request/response-metadata.d.ts +0 -1
  229. package/dist/lib/request/response-outcome.d.ts +0 -1
  230. package/dist/lib/request/stream-failover-runtime.d.ts +0 -1
  231. package/dist/lib/request/stream-failover.d.ts +0 -1
  232. package/dist/lib/request/stream-failover.js +28 -4
  233. package/dist/lib/request/token-refresh.d.ts +0 -1
  234. package/dist/lib/request/url-rewriting.d.ts +0 -1
  235. package/dist/lib/request/wait-utils.d.ts +0 -1
  236. package/dist/lib/rotation.d.ts +0 -1
  237. package/dist/lib/routing-mutex.d.ts +0 -1
  238. package/dist/lib/routing-profiles.d.ts +16 -2
  239. package/dist/lib/routing-profiles.js +119 -44
  240. package/dist/lib/runtime/account-check-helpers.d.ts +0 -1
  241. package/dist/lib/runtime/account-check-types.d.ts +0 -1
  242. package/dist/lib/runtime/account-check.d.ts +0 -1
  243. package/dist/lib/runtime/account-manager-cache-entry.d.ts +0 -1
  244. package/dist/lib/runtime/account-manager-cache.d.ts +0 -1
  245. package/dist/lib/runtime/account-model-catalog.d.ts +1 -2
  246. package/dist/lib/runtime/account-pool.d.ts +0 -1
  247. package/dist/lib/runtime/account-reset-credits.d.ts +0 -1
  248. package/dist/lib/runtime/account-reset-credits.js +8 -2
  249. package/dist/lib/runtime/account-scope.d.ts +0 -1
  250. package/dist/lib/runtime/account-select-event.d.ts +0 -1
  251. package/dist/lib/runtime/account-selection.d.ts +0 -1
  252. package/dist/lib/runtime/account-state.d.ts +0 -1
  253. package/dist/lib/runtime/account-status.d.ts +0 -1
  254. package/dist/lib/runtime/account-storage-scope-entry.d.ts +0 -1
  255. package/dist/lib/runtime/api-model-capabilities.d.ts +0 -1
  256. package/dist/lib/runtime/api-model-runtime.d.ts +0 -1
  257. package/dist/lib/runtime/app-bind.d.ts +0 -1
  258. package/dist/lib/runtime/app-bind.d.ts.map +1 -1
  259. package/dist/lib/runtime/app-bind.js +10 -2
  260. package/dist/lib/runtime/app-helper-selection.d.ts +0 -1
  261. package/dist/lib/runtime/auth-facade.d.ts +0 -1
  262. package/dist/lib/runtime/automatic-account-checks.d.ts +5 -2
  263. package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -1
  264. package/dist/lib/runtime/automatic-account-checks.js +29 -2
  265. package/dist/lib/runtime/automatic-subscription-checks.d.ts +1 -2
  266. package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +1 -1
  267. package/dist/lib/runtime/automatic-subscription-checks.js +13 -16
  268. package/dist/lib/runtime/browser-oauth-flow.d.ts +0 -1
  269. package/dist/lib/runtime/capability-boost.d.ts +0 -1
  270. package/dist/lib/runtime/catalog-capabilities.d.ts +0 -1
  271. package/dist/lib/runtime/config-toml.d.ts +0 -1
  272. package/dist/lib/runtime/context-budget-settings.d.ts +0 -1
  273. package/dist/lib/runtime/event-handler.d.ts +0 -1
  274. package/dist/lib/runtime/first-run.d.ts +0 -1
  275. package/dist/lib/runtime/flagged-verify-types.d.ts +0 -1
  276. package/dist/lib/runtime/hydrate-emails.d.ts +0 -1
  277. package/dist/lib/runtime/inference-activity.d.ts +0 -1
  278. package/dist/lib/runtime/live-sync-entry.d.ts +0 -1
  279. package/dist/lib/runtime/live-sync.d.ts +0 -1
  280. package/dist/lib/runtime/loader-setup.d.ts +0 -1
  281. package/dist/lib/runtime/login-menu-accounts.d.ts +0 -1
  282. package/dist/lib/runtime/manual-oauth-flow.d.ts +0 -1
  283. package/dist/lib/runtime/model-discovery-status.d.ts +2 -3
  284. package/dist/lib/runtime/native-account-storage.d.ts +0 -1
  285. package/dist/lib/runtime/native-account-sync.d.ts +0 -1
  286. package/dist/lib/runtime/native-binding-lock.d.ts +0 -1
  287. package/dist/lib/runtime/native-client-auth.d.ts +0 -1
  288. package/dist/lib/runtime/native-provider-config.d.ts +0 -1
  289. package/dist/lib/runtime/native-rate-limits.d.ts +2 -1
  290. package/dist/lib/runtime/native-rate-limits.js +23 -6
  291. package/dist/lib/runtime/preemptive-quota.d.ts +0 -1
  292. package/dist/lib/runtime/quota-headers.d.ts +0 -1
  293. package/dist/lib/runtime/quota-probe.d.ts +0 -1
  294. package/dist/lib/runtime/quota-settings.d.ts +0 -1
  295. package/dist/lib/runtime/refresh-guardian-entry.d.ts +0 -1
  296. package/dist/lib/runtime/refresh-guardian.d.ts +0 -1
  297. package/dist/lib/runtime/request-init.d.ts +0 -1
  298. package/dist/lib/runtime/reset-credit-routing.d.ts +0 -1
  299. package/dist/lib/runtime/reset-credits.d.ts +0 -1
  300. package/dist/lib/runtime/response-output-history.d.ts +0 -1
  301. package/dist/lib/runtime/responses-websocket.d.ts +0 -1
  302. package/dist/lib/runtime/resume-picker.d.ts +0 -1
  303. package/dist/lib/runtime/rotation-account-selection.d.ts +0 -1
  304. package/dist/lib/runtime/rotation-proxy-state.d.ts +0 -1
  305. package/dist/lib/runtime/rotation-server-types.d.ts +0 -1
  306. package/dist/lib/runtime/rotation-storage-meta.d.ts +0 -1
  307. package/dist/lib/runtime/rotation-token-refresh.d.ts +0 -1
  308. package/dist/lib/runtime/runtime-capability-failures.d.ts +0 -1
  309. package/dist/lib/runtime/runtime-current-account.d.ts +0 -1
  310. package/dist/lib/runtime/runtime-observability.d.ts +0 -1
  311. package/dist/lib/runtime/runtime-services.d.ts +0 -1
  312. package/dist/lib/runtime/session-affinity-entry.d.ts +0 -1
  313. package/dist/lib/runtime/session-recovery.d.ts +0 -1
  314. package/dist/lib/runtime/status-marker.d.ts +0 -1
  315. package/dist/lib/runtime/storage-scope.d.ts +0 -1
  316. package/dist/lib/runtime/subscription-first-use.d.ts +0 -1
  317. package/dist/lib/runtime/subscription-quota-event.d.ts +0 -1
  318. package/dist/lib/runtime/subscription-quota-order.d.ts +0 -1
  319. package/dist/lib/runtime/toast.d.ts +0 -1
  320. package/dist/lib/runtime/ui-runtime-entry.d.ts +0 -1
  321. package/dist/lib/runtime/ui-runtime.d.ts +0 -1
  322. package/dist/lib/runtime/verify-flagged.d.ts +0 -1
  323. package/dist/lib/runtime/workspace-model-scopes.d.ts +0 -1
  324. package/dist/lib/runtime-constants.d.ts +0 -1
  325. package/dist/lib/runtime-paths.d.ts +0 -1
  326. package/dist/lib/runtime-rotation-proxy.d.ts +1 -1
  327. package/dist/lib/runtime-rotation-proxy.js +136 -3
  328. package/dist/lib/schemas.d.ts +35 -13
  329. package/dist/lib/schemas.js +19 -2
  330. package/dist/lib/session-affinity.d.ts +0 -1
  331. package/dist/lib/shutdown.d.ts +0 -1
  332. package/dist/lib/storage/account-clear-entry.d.ts +0 -1
  333. package/dist/lib/storage/account-clear.d.ts +0 -1
  334. package/dist/lib/storage/account-match-utils.d.ts +0 -1
  335. package/dist/lib/storage/account-persistence.d.ts +0 -1
  336. package/dist/lib/storage/account-port.d.ts +0 -1
  337. package/dist/lib/storage/account-save-entry.d.ts +0 -1
  338. package/dist/lib/storage/account-save.d.ts +9 -2
  339. package/dist/lib/storage/account-save.js +4 -1
  340. package/dist/lib/storage/account-snapshot.d.ts +0 -1
  341. package/dist/lib/storage/backup-metadata-builder.d.ts +0 -1
  342. package/dist/lib/storage/backup-metadata.d.ts +0 -1
  343. package/dist/lib/storage/backup-paths.d.ts +0 -1
  344. package/dist/lib/storage/backup-restore.d.ts +0 -1
  345. package/dist/lib/storage/cache-artifacts.d.ts +0 -1
  346. package/dist/lib/storage/credential-sidecars.d.ts +0 -1
  347. package/dist/lib/storage/error-hints.d.ts +0 -1
  348. package/dist/lib/storage/file-lock.d.ts +0 -1
  349. package/dist/lib/storage/file-lock.js +33 -1
  350. package/dist/lib/storage/file-paths.d.ts +0 -1
  351. package/dist/lib/storage/fixture-guards.d.ts +0 -1
  352. package/dist/lib/storage/flagged-entry.d.ts +0 -1
  353. package/dist/lib/storage/flagged-load-entry.d.ts +0 -1
  354. package/dist/lib/storage/flagged-save-entry.d.ts +0 -1
  355. package/dist/lib/storage/flagged-storage-file.d.ts +0 -1
  356. package/dist/lib/storage/flagged-storage-io.d.ts +0 -1
  357. package/dist/lib/storage/flagged-storage.d.ts +0 -1
  358. package/dist/lib/storage/gitignore.d.ts +0 -1
  359. package/dist/lib/storage/hash.d.ts +0 -1
  360. package/dist/lib/storage/health.d.ts +0 -1
  361. package/dist/lib/storage/identity.d.ts +0 -1
  362. package/dist/lib/storage/import-export.d.ts +0 -1
  363. package/dist/lib/storage/json-store-lock.d.ts +105 -0
  364. package/dist/lib/storage/json-store-lock.js +259 -0
  365. package/dist/lib/storage/metadata-section.d.ts +0 -1
  366. package/dist/lib/storage/migrations.d.ts +0 -1
  367. package/dist/lib/storage/migrations.js +31 -18
  368. package/dist/lib/storage/named-backup-entry.d.ts +0 -1
  369. package/dist/lib/storage/named-backups-entry.d.ts +0 -1
  370. package/dist/lib/storage/named-backups.d.ts +0 -1
  371. package/dist/lib/storage/path-state.d.ts +0 -1
  372. package/dist/lib/storage/paths.d.ts +0 -1
  373. package/dist/lib/storage/pending-auth.d.ts +10 -3
  374. package/dist/lib/storage/pending-auth.d.ts.map +1 -1
  375. package/dist/lib/storage/pending-auth.js +33 -9
  376. package/dist/lib/storage/project-migration.d.ts +0 -1
  377. package/dist/lib/storage/public-types.d.ts +0 -1
  378. package/dist/lib/storage/record-identity.d.ts +15 -0
  379. package/dist/lib/storage/record-identity.d.ts.map +1 -0
  380. package/dist/lib/storage/record-identity.js +16 -0
  381. package/dist/lib/storage/record-utils.d.ts +0 -1
  382. package/dist/lib/storage/restore-assessment.d.ts +0 -1
  383. package/dist/lib/storage/restore-backup-entry.d.ts +0 -1
  384. package/dist/lib/storage/restore-metadata.d.ts +0 -1
  385. package/dist/lib/storage/save-retry.d.ts +0 -1
  386. package/dist/lib/storage/snapshot-inspectors.d.ts +0 -1
  387. package/dist/lib/storage/snapshot-merge.d.ts +0 -1
  388. package/dist/lib/storage/storage-parser.d.ts +2 -1
  389. package/dist/lib/storage/storage-parser.js +10 -2
  390. package/dist/lib/storage/transactions.d.ts +0 -1
  391. package/dist/lib/storage.d.ts +15 -2
  392. package/dist/lib/storage.js +612 -25
  393. package/dist/lib/synthetic-response.d.ts +0 -1
  394. package/dist/lib/table-formatter.d.ts +0 -1
  395. package/dist/lib/temp-path.d.ts +0 -1
  396. package/dist/lib/tools/hashline-tools.d.ts +0 -1
  397. package/dist/lib/types.d.ts +0 -1
  398. package/dist/lib/ui/ansi.d.ts +0 -1
  399. package/dist/lib/ui/auth-menu-builder.d.ts +0 -1
  400. package/dist/lib/ui/auth-menu.d.ts +0 -1
  401. package/dist/lib/ui/check-progress.d.ts +0 -1
  402. package/dist/lib/ui/confirm.d.ts +0 -1
  403. package/dist/lib/ui/display-width.d.ts +0 -1
  404. package/dist/lib/ui/format.d.ts +0 -1
  405. package/dist/lib/ui/index.d.ts +0 -1
  406. package/dist/lib/ui/runtime.d.ts +0 -1
  407. package/dist/lib/ui/select.d.ts +0 -1
  408. package/dist/lib/ui/theme.d.ts +0 -1
  409. package/dist/lib/ui/ui-copy.d.ts +0 -1
  410. package/dist/lib/unified-settings.d.ts +13 -11
  411. package/dist/lib/unified-settings.js +22 -14
  412. package/dist/lib/update-notice.d.ts +0 -1
  413. package/dist/lib/usage/index.d.ts +0 -1
  414. package/dist/lib/usage/ledger.d.ts +0 -1
  415. package/dist/lib/usage/pricing.d.ts +0 -1
  416. package/dist/lib/usage/redaction.d.ts +0 -1
  417. package/dist/lib/usage/stream-usage-deferral.d.ts +0 -1
  418. package/dist/lib/usage/types.d.ts +0 -1
  419. package/dist/lib/usage/usage-extraction.d.ts +0 -1
  420. package/dist/lib/utils.d.ts +21 -1
  421. package/dist/lib/utils.js +31 -0
  422. package/dist/lib/wsl.d.ts +0 -1
  423. package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
  424. package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
  425. package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
  426. package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
  427. package/node_modules/@codex-ai/plugin/package.json +9 -9
  428. package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
  429. package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
  430. package/node_modules/@codex-ai/sdk/package.json +8 -8
  431. package/package.json +206 -200
  432. package/scripts/codex-app-launcher.js +653 -653
  433. package/scripts/codex-app-router.js +373 -373
  434. package/scripts/codex-bin-resolver.js +332 -313
  435. package/scripts/codex-multi-auth.js +65 -59
  436. package/scripts/codex-routing.js +62 -62
  437. package/scripts/codex.js +6923 -6642
  438. package/scripts/install-codex-auth-utils.js +213 -213
  439. package/scripts/mcodex.js +367 -367
  440. package/scripts/postinstall.js +114 -114
  441. package/scripts/preuninstall.js +265 -265
  442. package/skills/codex-auth-setup/SKILL.md +73 -0
  443. package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
  444. package/vendor/codex-ai-plugin/dist/index.js +2 -2
  445. package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
  446. package/vendor/codex-ai-plugin/dist/tool.js +29 -29
  447. package/vendor/codex-ai-plugin/package.json +9 -9
  448. package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
  449. package/vendor/codex-ai-sdk/dist/index.js +2 -2
  450. package/vendor/codex-ai-sdk/package.json +8 -8
@@ -6,4 +6,3 @@ export declare function readFileWithRetry(path: string, deps: {
6
6
  maxAttempts: number;
7
7
  sleep: (ms: number) => Promise<void>;
8
8
  }): Promise<string>;
9
- //# sourceMappingURL=settings-persist-utils.d.ts.map
@@ -9,4 +9,3 @@ export declare function buildAccountListPreview(settings: DashboardDisplaySettin
9
9
  label: string;
10
10
  hint: string;
11
11
  };
12
- //# sourceMappingURL=settings-preview.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export declare function withQueuedRetry<T>(pathKey: string, task: () => Promise<T>, deps: {
2
2
  sleep: (ms: number) => Promise<void>;
3
3
  }): Promise<T>;
4
- //# sourceMappingURL=settings-write-queue.d.ts.map
@@ -22,4 +22,3 @@ export interface StatuslineSettingsPanelDeps {
22
22
  }
23
23
  export declare function promptStatuslineSettingsPanel(initial: DashboardDisplaySettings, deps: StatuslineSettingsPanelDeps): Promise<DashboardDisplaySettings | null>;
24
24
  export {};
25
- //# sourceMappingURL=statusline-settings-panel.d.ts.map
@@ -10,4 +10,3 @@ export interface ThemeSettingsPanelDeps {
10
10
  UI_COPY: typeof UI_COPY;
11
11
  }
12
12
  export declare function promptThemeSettingsPanel(initial: DashboardDisplaySettings, deps: ThemeSettingsPanelDeps): Promise<DashboardDisplaySettings | null>;
13
- //# sourceMappingURL=theme-settings-panel.d.ts.map
@@ -24,4 +24,3 @@ export type UnifiedSettingsControllerDeps = {
24
24
  THEME_PANEL_KEYS: readonly (keyof DashboardDisplaySettings)[];
25
25
  };
26
26
  export declare function configureUnifiedSettingsController(initialSettings: DashboardDisplaySettings | undefined, deps: UnifiedSettingsControllerDeps): Promise<DashboardDisplaySettings>;
27
- //# sourceMappingURL=unified-settings-controller.d.ts.map
@@ -3,4 +3,3 @@ import type { UnifiedSettingsControllerDeps } from "./unified-settings-controlle
3
3
  export declare function configureUnifiedSettingsEntry(initialSettings: DashboardDisplaySettings | undefined, deps: {
4
4
  configureUnifiedSettingsController: (initialSettings: DashboardDisplaySettings | undefined, deps: UnifiedSettingsControllerDeps) => Promise<DashboardDisplaySettings>;
5
5
  } & UnifiedSettingsControllerDeps): Promise<DashboardDisplaySettings>;
6
- //# sourceMappingURL=unified-settings-entry.d.ts.map
@@ -2,8 +2,7 @@ import { selectHybridAccountTraced } from "./rotation.js";
2
2
  import { formatBackupSavedAt, styleAccountDetailText } from "./codex-manager/formatters/index.js";
3
3
  import { type AccountStorageV3 } from "./storage.js";
4
4
  export { formatBackupSavedAt, styleAccountDetailText };
5
- export declare function autoSyncActiveAccountToCodex(): Promise<boolean>;
5
+ export { autoSyncActiveAccountToCodex } from "./codex-manager/active-account-sync.js";
6
6
  /** @internal Exposed for diagnostics regression tests; not part of the CLI API. */
7
7
  export declare function buildSelectAccountTraced(): (storage: AccountStorageV3) => Promise<ReturnType<typeof selectHybridAccountTraced>>;
8
8
  export declare function runCodexMultiAuthCli(rawArgs: string[]): Promise<number>;
9
- //# sourceMappingURL=codex-manager.d.ts.map
@@ -5,7 +5,6 @@ import { loadInferenceRequestTimes } from "./runtime/inference-activity.js";
5
5
  import { loadModelInventory, refreshAndPrintModelInventory } from "./runtime/model-discovery-status.js";
6
6
  import { AUTH_INVALIDATION_MARKER, AccountManager, extractAccountEmail, extractAccountId, formatAccountLabel, formatWaitTime, sanitizeEmail, } from "./accounts.js";
7
7
  import { reboundUnauthorizedAccountIdentity, refreshCodexCliMirror, } from "./auth/account-access.js";
8
- import { codexCliAccountIdFor } from "./auth/token-utils.js";
9
8
  import { loadCodexCliState } from "./codex-cli/state.js";
10
9
  import { setCodexCliActiveSelection } from "./codex-cli/writer.js";
11
10
  import { parseBestArgs, printBestUsage, runBestCommand, } from "./codex-manager/commands/best.js";
@@ -60,7 +59,7 @@ import { loadQuotaCache, saveQuotaCache } from "./quota-cache.js";
60
59
  import { readAppRuntimeHelperAccountSignal } from "./runtime/runtime-current-account.js";
61
60
  import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./quota-probe.js";
62
61
  import { queuedRefresh } from "./refresh-queue.js";
63
- import { clearAccounts, findMatchingAccountIndex, inspectStorageHealth, getLastAccountsSaveTimestamp, getStoragePath, loadAccounts, loadFlaggedAccounts, saveAccounts, setStoragePath, withAccountStorageTransaction, } from "./storage.js";
62
+ import { clearAccounts, inspectStorageHealth, getLastAccountsSaveTimestamp, getStoragePath, loadAccounts, loadFlaggedAccounts, saveAccounts, setStoragePath, } from "./storage.js";
64
63
  // Formatter implementations moved to lib/codex-manager/formatters/ (audit
65
64
  // roadmap §4.1.1 phase 1). Re-exported here so existing consumers importing
66
65
  // from lib/codex-manager.js keep working unchanged.
@@ -196,99 +195,10 @@ async function runBest(args) {
196
195
  setCodexCliActiveSelection,
197
196
  });
198
197
  }
199
- export async function autoSyncActiveAccountToCodex() {
200
- setStoragePath(null);
201
- const storage = await loadAccounts();
202
- if (!storage || storage.accounts.length === 0) {
203
- return false;
204
- }
205
- const activeIndex = resolveActiveIndex(storage, "codex");
206
- if (activeIndex < 0 || activeIndex >= storage.accounts.length) {
207
- return false;
208
- }
209
- const account = storage.accounts[activeIndex];
210
- if (!account) {
211
- return false;
212
- }
213
- const accountMatch = {
214
- accountId: account.accountId,
215
- email: account.email,
216
- refreshToken: account.refreshToken,
217
- };
218
- const now = Date.now();
219
- let syncAccessToken = account.accessToken;
220
- let syncRefreshToken = account.refreshToken;
221
- let syncExpiresAt = account.expiresAt;
222
- let syncIdToken;
223
- let syncEmail = account.email;
224
- let changed = false;
225
- let nextStoredAccount = null;
226
- if (!hasUsableAccessToken(account, now)) {
227
- const refreshResult = await queuedRefresh(account.refreshToken);
228
- if (refreshResult.type !== "success") {
229
- return false;
230
- }
231
- nextStoredAccount = structuredClone(account);
232
- const tokenAccountId = extractAccountId(refreshResult.access);
233
- const nextEmail = sanitizeEmail(extractAccountEmail(refreshResult.access, refreshResult.idToken));
234
- if (nextStoredAccount.refreshToken !== refreshResult.refresh) {
235
- nextStoredAccount.refreshToken = refreshResult.refresh;
236
- changed = true;
237
- }
238
- if (nextStoredAccount.accessToken !== refreshResult.access) {
239
- nextStoredAccount.accessToken = refreshResult.access;
240
- changed = true;
241
- }
242
- if (nextStoredAccount.expiresAt !== refreshResult.expires) {
243
- nextStoredAccount.expiresAt = refreshResult.expires;
244
- changed = true;
245
- }
246
- if (nextEmail && nextEmail !== nextStoredAccount.email) {
247
- nextStoredAccount.email = nextEmail;
248
- changed = true;
249
- }
250
- if (applyTokenAccountIdentity(nextStoredAccount, tokenAccountId)) {
251
- changed = true;
252
- }
253
- syncAccessToken = refreshResult.access;
254
- syncRefreshToken = refreshResult.refresh;
255
- syncExpiresAt = refreshResult.expires;
256
- syncIdToken = refreshResult.idToken;
257
- syncEmail = nextStoredAccount.email;
258
- }
259
- if (changed && nextStoredAccount) {
260
- let persisted = false;
261
- await withAccountStorageTransaction(async (loadedStorage, persist) => {
262
- if (!loadedStorage) {
263
- return;
264
- }
265
- const nextStorage = structuredClone(loadedStorage);
266
- const targetIndex = findMatchingAccountIndex(nextStorage.accounts, accountMatch, {
267
- allowUniqueAccountIdFallbackWithoutEmail: true,
268
- }) ??
269
- findMatchingAccountIndex(nextStorage.accounts, nextStoredAccount, {
270
- allowUniqueAccountIdFallbackWithoutEmail: true,
271
- });
272
- if (targetIndex === undefined) {
273
- return;
274
- }
275
- nextStorage.accounts[targetIndex] = structuredClone(nextStoredAccount);
276
- await persist(nextStorage);
277
- persisted = true;
278
- });
279
- if (!persisted) {
280
- return false;
281
- }
282
- }
283
- return setCodexCliActiveSelection({
284
- accountId: codexCliAccountIdFor(nextStoredAccount ?? account, syncAccessToken, syncIdToken),
285
- email: syncEmail,
286
- accessToken: syncAccessToken,
287
- refreshToken: syncRefreshToken,
288
- expiresAt: syncExpiresAt,
289
- ...(syncIdToken ? { idToken: syncIdToken } : {}),
290
- });
291
- }
198
+ // Moved to lib/codex-manager/active-account-sync.ts so the wrapper's forwarded
199
+ // path can import the sync without the whole manager/dispatch graph. Re-exported
200
+ // here to keep the codex-manager.js surface (and its tests) unchanged.
201
+ export { autoSyncActiveAccountToCodex } from "./codex-manager/active-account-sync.js";
292
202
  /** @internal Exposed for diagnostics regression tests; not part of the CLI API. */
293
203
  export function buildSelectAccountTraced() {
294
204
  return async (storage) => {
@@ -1,3 +1,2 @@
1
1
  /** Bounded independent work, refilling free slots immediately and preserving result order. */
2
2
  export declare function mapWithConcurrency<T, R>(items: readonly T[], limit: number, worker: (item: T, index: number) => Promise<R>): Promise<R[]>;
3
- //# sourceMappingURL=concurrency.d.ts.map
@@ -29,4 +29,3 @@ export declare function buildConfigJsonSchema(): JsonObject;
29
29
  */
30
30
  export declare function renderConfigJsonSchema(): string;
31
31
  export {};
32
- //# sourceMappingURL=config-schema.d.ts.map
@@ -385,4 +385,3 @@ export declare function getRoutingMutexMode(pluginConfig: PluginConfig): "enable
385
385
  export declare function getSchedulingStrategy(pluginConfig: PluginConfig): "hybrid" | "sequential";
386
386
  export declare function getPluginConfigExplainReport(): ConfigExplainReport;
387
387
  export {};
388
- //# sourceMappingURL=config.d.ts.map
@@ -1,6 +1,5 @@
1
1
  import { existsSync, promises as fs, readFileSync } from "node:fs";
2
- import { randomUUID } from "node:crypto";
3
- import { dirname, join } from "node:path";
2
+ import { join } from "node:path";
4
3
  import { parseBooleanEnv } from "./env-parsing.js";
5
4
  import { stripModelEffortSuffix } from "./constants.js";
6
5
  import { withRetry, withRetrySync } from "./fs-retry.js";
@@ -8,8 +7,8 @@ import { logWarn } from "./logger.js";
8
7
  import { StorageError } from "./errors.js";
9
8
  import { getCodexHomeDir, getCodexMultiAuthDir, getLegacyCodexDir, } from "./runtime-paths.js";
10
9
  import { getValidationErrors, PluginConfigSchema } from "./schemas.js";
10
+ import { getJsonStoreFileMtimeMs, withJsonStoreCasRetry, withJsonStoreFileLock, withJsonStoreWriteQueue, writeJsonStoreFileAtomicWithRetry, } from "./storage/json-store-lock.js";
11
11
  import { getUnifiedSettingsPath, loadUnifiedPluginConfigSync, saveUnifiedPluginConfig, } from "./unified-settings.js";
12
- import { tempPathFor } from "./temp-path.js";
13
12
  const CONFIG_DIR = getCodexMultiAuthDir();
14
13
  const CONFIG_PATH = join(CONFIG_DIR, "config.json");
15
14
  const CODEX_HOME_DIR = getCodexHomeDir();
@@ -23,8 +22,6 @@ const TUI_COLOR_PROFILES = new Set(["truecolor", "ansi16", "ansi256"]);
23
22
  const TUI_GLYPH_MODES = new Set(["ascii", "unicode", "auto"]);
24
23
  const UNSUPPORTED_CODEX_POLICIES = new Set(["strict", "fallback"]);
25
24
  const emittedConfigWarnings = new Set();
26
- const configSaveQueues = new Map();
27
- const RETRYABLE_FS_CODES = new Set(["EBUSY", "EPERM"]);
28
25
  const RETRYABLE_CONFIG_READ_CODES = new Set(["EBUSY", "EPERM", "EAGAIN"]);
29
26
  /**
30
27
  * Synchronous readFileSync with bounded retry on transient FS-lock codes.
@@ -330,212 +327,14 @@ function stripUtf8Bom(content) {
330
327
  function isRecord(value) {
331
328
  return value !== null && typeof value === "object" && !Array.isArray(value);
332
329
  }
333
- function sleep(ms) {
334
- return new Promise((resolve) => setTimeout(resolve, ms));
335
- }
336
- async function getConfigFileMtimeMs(filePath) {
337
- // config-08: the mtime CAS preflight (and savePluginConfig's env-path branch)
338
- // run on the Windows-sensitive save path, where a transient EBUSY/EPERM/EAGAIN
339
- // from an AV/indexer lock on a single fs.stat would abort the entire save.
340
- // Mirror readConfigRecordForSave's bounded transient-FS retry (same code set,
341
- // same backoff, 5 attempts). ENOENT still returns null immediately. On
342
- // exhaustion the last failure surfaces so the caller treats it as a real
343
- // save error rather than a phantom missing file.
344
- return withRetry(async () => {
345
- try {
346
- return (await fs.stat(filePath)).mtimeMs;
347
- }
348
- catch (error) {
349
- if (error?.code === "ENOENT") {
350
- return null;
351
- }
352
- throw error;
353
- }
354
- }, {
355
- maxAttempts: 5,
356
- backoffMs: (attempt) => 10 * 2 ** (attempt - 1),
357
- retryableCodes: RETRYABLE_CONFIG_READ_CODES,
358
- });
359
- }
360
- async function writeJsonFileAtomicWithRetry(filePath, payload, options) {
361
- const tempPath = tempPathFor(filePath);
362
- await fs.mkdir(dirname(filePath), { recursive: true });
363
- await fs.writeFile(tempPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
364
- let renamed = false;
365
- try {
366
- // Compare-and-swap guard: if a concurrent writer changed the target file
367
- // since the caller read it (mtime mismatch), abort with ESTALE so the
368
- // caller can re-read and merge instead of clobbering the other write.
369
- if (options && "expectedMtimeMs" in options) {
370
- const currentMtimeMs = await getConfigFileMtimeMs(filePath);
371
- if (currentMtimeMs !== options.expectedMtimeMs) {
372
- const staleError = new Error(`Config at ${filePath} changed on disk during save; retrying with latest state.`);
373
- staleError.code = "ESTALE";
374
- throw staleError;
375
- }
376
- }
377
- await withRetry(() => fs.rename(tempPath, filePath), {
378
- maxAttempts: 5,
379
- backoffMs: (attempt) => 10 * 2 ** (attempt - 1),
380
- retryableCodes: RETRYABLE_FS_CODES,
381
- });
382
- renamed = true;
383
- }
384
- finally {
385
- if (!renamed) {
386
- try {
387
- await fs.unlink(tempPath);
388
- }
389
- catch {
390
- // Best-effort temp cleanup.
391
- }
392
- }
393
- }
394
- }
395
- async function withConfigSaveLock(path, task) {
396
- const previous = configSaveQueues.get(path) ?? Promise.resolve();
397
- const queued = previous.catch(() => { }).then(task);
398
- configSaveQueues.set(path, queued);
399
- try {
400
- await queued;
401
- }
402
- finally {
403
- if (configSaveQueues.get(path) === queued) {
404
- configSaveQueues.delete(path);
405
- }
406
- }
407
- }
408
- // Cross-process config-save lock. withConfigSaveLock only serializes saves
409
- // within THIS process (a per-path promise queue); it does nothing against a
410
- // second process. The mtime CAS in writeJsonFileAtomicWithRetry narrows but does
411
- // not close the read→check→merge→rename TOCTOU window (another process can still
412
- // land a write between the CAS stat and the rename). This file lock provides the
413
- // cross-process mutual exclusion that closes that window. It deliberately mirrors
414
- // RefreshLeaseCoordinator (lib/refresh-lease.ts): exclusive `wx` lockfile create,
415
- // JSON payload carrying pid + expiry, stale-takeover via expiry/mtime, and a
416
- // best-effort retrying release in a finally. The mtime CAS stays as a second-line
417
- // guard for any non-participating writer.
418
- const CONFIG_LOCK_TTL_MS = 10_000;
419
- const CONFIG_LOCK_WAIT_TIMEOUT_MS = 10_000;
420
- const CONFIG_LOCK_POLL_MS = 50;
421
- async function unlinkConfigLockWithRetry(lockPath) {
422
- try {
423
- await withRetry(() => fs.unlink(lockPath), {
424
- maxAttempts: 5,
425
- backoffMs: (attempt) => 10 * 2 ** (attempt - 1),
426
- retryableCodes: RETRYABLE_FS_CODES,
427
- });
428
- }
429
- catch {
430
- // ENOENT (already released) or best-effort release failure: a leftover
431
- // lockfile is recovered as stale by the next acquirer via its
432
- // expiry/mtime, so never fail the save over this.
433
- }
434
- }
435
- // Owner-safe release: only unlink the lockfile if it still carries OUR owner
436
- // token. If a slow save was deemed stale and a second process stole the lock,
437
- // the lockfile now holds the new owner's token — deleting it would reopen
438
- // concurrent saves, so we leave it alone.
439
- async function releaseConfigLockIfOwner(lockPath, owner) {
440
- try {
441
- const content = await fs.readFile(lockPath, "utf-8");
442
- const parsed = JSON.parse(stripUtf8Bom(content));
443
- if (parsed?.owner && parsed.owner !== owner) {
444
- // Lock was taken over by another holder; do not delete their lock.
445
- return;
446
- }
447
- }
448
- catch (error) {
449
- const code = error?.code;
450
- if (code === "ENOENT")
451
- return;
452
- // Unreadable/malformed: fall through and attempt our best-effort unlink.
453
- }
454
- await unlinkConfigLockWithRetry(lockPath);
455
- }
456
- async function isConfigLockStale(lockPath) {
457
- try {
458
- const content = await fs.readFile(lockPath, "utf-8");
459
- const parsed = JSON.parse(stripUtf8Bom(content));
460
- if (typeof parsed?.expiresAt === "number" &&
461
- Number.isFinite(parsed.expiresAt)) {
462
- return parsed.expiresAt <= Date.now();
463
- }
464
- }
465
- catch (error) {
466
- const code = error?.code;
467
- if (code === "ENOENT")
468
- return true;
469
- // Unreadable/malformed payload: fall through to the mtime heuristic.
470
- }
471
- try {
472
- const stat = await fs.stat(lockPath);
473
- return Date.now() - stat.mtimeMs > CONFIG_LOCK_TTL_MS;
474
- }
475
- catch (error) {
476
- const code = error?.code;
477
- if (code === "ENOENT")
478
- return true;
479
- return false;
480
- }
481
- }
482
- async function withConfigFileLock(targetPath, task) {
483
- const lockPath = `${targetPath}.lock`;
484
- const owner = randomUUID();
485
- await fs.mkdir(dirname(lockPath), { recursive: true });
486
- const deadline = Date.now() + CONFIG_LOCK_WAIT_TIMEOUT_MS;
487
- let acquired = false;
488
- while (!acquired) {
489
- try {
490
- const now = Date.now();
491
- const payload = {
492
- pid: process.pid,
493
- owner,
494
- acquiredAt: now,
495
- expiresAt: now + CONFIG_LOCK_TTL_MS,
496
- };
497
- const handle = await fs.open(lockPath, "wx", 0o600);
498
- try {
499
- await handle.writeFile(`${JSON.stringify(payload)}\n`, "utf8");
500
- }
501
- finally {
502
- await handle.close();
503
- }
504
- acquired = true;
505
- }
506
- catch (error) {
507
- const code = error?.code;
508
- if (code !== "EEXIST") {
509
- // A transient FS lock on the lockfile itself: retry until the deadline,
510
- // matching the bounded backoff used elsewhere on the Windows save path.
511
- if (typeof code === "string" &&
512
- RETRYABLE_FS_CODES.has(code) &&
513
- Date.now() < deadline) {
514
- await sleep(CONFIG_LOCK_POLL_MS);
515
- continue;
516
- }
517
- throw error;
518
- }
519
- // Lock is held. Take it over if the holder expired/crashed; otherwise wait.
520
- if (await isConfigLockStale(lockPath)) {
521
- await unlinkConfigLockWithRetry(lockPath);
522
- continue;
523
- }
524
- if (Date.now() >= deadline) {
525
- const timeoutError = new Error(`Timed out acquiring config save lock at ${lockPath}.`);
526
- timeoutError.code = "ELOCKTIMEOUT";
527
- throw timeoutError;
528
- }
529
- await sleep(CONFIG_LOCK_POLL_MS);
530
- }
531
- }
532
- try {
533
- return await task();
534
- }
535
- finally {
536
- await releaseConfigLockIfOwner(lockPath, owner);
537
- }
538
- }
330
+ // Cross-process save safety lives in lib/storage/json-store-lock.ts:
331
+ // withJsonStoreWriteQueue (per-path in-process queue), withJsonStoreFileLock
332
+ // (candidate-directory lock + dead-owner recovery), and the mtime CAS
333
+ // trio (getJsonStoreFileMtimeMs / writeJsonStoreFileAtomicWithRetry /
334
+ // withJsonStoreCasRetry). The file lock provides the cross-process mutual
335
+ // exclusion that closes the read→check→merge→rename TOCTOU window against
336
+ // OTHER processes; the mtime CAS stays on as a second-line guard for any
337
+ // non-participating writer.
539
338
  /**
540
339
  * Read and parse a JSON configuration file and return its top-level object when present and valid.
541
340
  *
@@ -718,19 +517,19 @@ export async function savePluginConfig(configPatch) {
718
517
  }
719
518
  const envPath = (process.env.CODEX_MULTI_AUTH_CONFIG_PATH ?? "").trim();
720
519
  if (envPath.length > 0) {
721
- await withConfigSaveLock(envPath, async () => {
520
+ await withJsonStoreWriteQueue(envPath, async () => {
722
521
  // In-process queue (above) is the cheap fast path; the cross-process file
723
522
  // lock (below) closes the read→merge→rename TOCTOU window against OTHER
724
523
  // processes. Acquire the file lock for the full critical section, then run
725
524
  // the same mtime CAS retry as a second-line guard for any non-participating
726
525
  // writer. Mirrors the unified-settings save path (writeSettingsRecordAsync
727
526
  // CAS).
728
- await withConfigFileLock(envPath, async () => {
527
+ await withJsonStoreFileLock(envPath, async () => {
729
528
  // CAS retry: ESTALE means the file's mtime moved between our stat and
730
529
  // the write, so each attempt re-stats, re-reads, and re-merges against
731
530
  // the latest on-disk state before writing again.
732
- await withRetry(async () => {
733
- const expectedMtimeMs = await getConfigFileMtimeMs(envPath);
531
+ await withJsonStoreCasRetry(async () => {
532
+ const expectedMtimeMs = await getJsonStoreFileMtimeMs(envPath);
734
533
  const envConfigState = await readConfigRecordForSave(envPath);
735
534
  if (envConfigState.status === "unreadable") {
736
535
  throw unreadableConfigSaveError(envPath, envConfigState.errorMessage);
@@ -742,39 +541,45 @@ export async function savePluginConfig(configPatch) {
742
541
  ...(existingConfig ?? {}),
743
542
  ...sanitizedPatch,
744
543
  };
745
- await writeJsonFileAtomicWithRetry(envPath, merged, {
544
+ await writeJsonStoreFileAtomicWithRetry(envPath, merged, {
746
545
  expectedMtimeMs,
747
546
  });
748
- }, { maxAttempts: 3, backoffMs: 0, retryableCodes: ["ESTALE"] });
547
+ });
749
548
  });
750
549
  });
751
550
  return;
752
551
  }
753
552
  const unifiedPath = getUnifiedSettingsPath();
754
- await withConfigSaveLock(unifiedPath, async () => {
755
- const unifiedConfigState = await readConfigRecordForSave(unifiedPath);
756
- if (unifiedConfigState.status === "unreadable") {
757
- throw unreadableConfigSaveError(unifiedPath, unifiedConfigState.errorMessage);
758
- }
759
- const unifiedConfigRecord = unifiedConfigState.status === "ok"
760
- ? unifiedConfigState.record.pluginConfig
761
- : loadUnifiedPluginConfigSync();
762
- const unifiedConfig = sanitizeStoredPluginConfigRecord(unifiedConfigRecord);
763
- const legacyPath = unifiedConfig === null ? resolvePluginConfigPath() : null;
764
- const legacyConfigState = legacyPath
765
- ? await readConfigRecordForSave(legacyPath)
766
- : null;
767
- if (legacyConfigState?.status === "unreadable") {
768
- throw unreadableConfigSaveError(legacyPath, legacyConfigState.errorMessage);
769
- }
770
- const legacyConfig = legacyConfigState?.status === "ok"
771
- ? sanitizeStoredPluginConfigRecord(legacyConfigState.record)
772
- : null;
773
- const merged = {
774
- ...(unifiedConfig ?? legacyConfig ?? {}),
775
- ...sanitizedPatch,
776
- };
777
- await saveUnifiedPluginConfig(merged);
553
+ await withJsonStoreWriteQueue(unifiedPath, async () => {
554
+ // Hold the same cross-process lockfile for the read→merge portion, not
555
+ // just the write: saveUnifiedPluginConfig re-acquires both primitives
556
+ // re-entrantly inside this critical section, so the merged pluginConfig
557
+ // cannot interleave with another process's write to the same file.
558
+ await withJsonStoreFileLock(unifiedPath, async () => {
559
+ const unifiedConfigState = await readConfigRecordForSave(unifiedPath);
560
+ if (unifiedConfigState.status === "unreadable") {
561
+ throw unreadableConfigSaveError(unifiedPath, unifiedConfigState.errorMessage);
562
+ }
563
+ const unifiedConfigRecord = unifiedConfigState.status === "ok"
564
+ ? unifiedConfigState.record.pluginConfig
565
+ : loadUnifiedPluginConfigSync();
566
+ const unifiedConfig = sanitizeStoredPluginConfigRecord(unifiedConfigRecord);
567
+ const legacyPath = unifiedConfig === null ? resolvePluginConfigPath() : null;
568
+ const legacyConfigState = legacyPath
569
+ ? await readConfigRecordForSave(legacyPath)
570
+ : null;
571
+ if (legacyConfigState?.status === "unreadable") {
572
+ throw unreadableConfigSaveError(legacyPath, legacyConfigState.errorMessage);
573
+ }
574
+ const legacyConfig = legacyConfigState?.status === "ok"
575
+ ? sanitizeStoredPluginConfigRecord(legacyConfigState.record)
576
+ : null;
577
+ const merged = {
578
+ ...(unifiedConfig ?? legacyConfig ?? {}),
579
+ ...sanitizedPatch,
580
+ };
581
+ await saveUnifiedPluginConfig(merged);
582
+ });
778
583
  });
779
584
  }
780
585
  function parseNumberEnv(value) {
@@ -113,4 +113,3 @@ export type WireReasoningEffort = Exclude<ModelReasoningEffort, "ultra">;
113
113
  * untouched.
114
114
  */
115
115
  export declare function stripModelEffortSuffix(modelId: string): string;
116
- //# sourceMappingURL=constants.d.ts.map
@@ -22,4 +22,3 @@ export interface EffectiveContextWindow {
22
22
  */
23
23
  export declare function getEffectiveContextWindow(model: string | null | undefined, overrides: Record<string, number> | undefined): EffectiveContextWindow | null;
24
24
  export declare function listEstimatedModelContextWindows(): Record<string, number>;
25
- //# sourceMappingURL=model-context-windows.d.ts.map
@@ -97,4 +97,3 @@ export declare class ContextBudgetGuard {
97
97
  noteHardPauseEmitted(key: string): void;
98
98
  }
99
99
  export {};
100
- //# sourceMappingURL=context-budget-guard.d.ts.map
@@ -22,4 +22,3 @@ export declare function createContextBudgetPauseResponse(advisory: Extract<Conte
22
22
  export declare function buildContextBudgetHeaders(advisory: Extract<ContextBudgetAdvisory, {
23
23
  level: "soft" | "hard";
24
24
  }>): Record<string, string>;
25
- //# sourceMappingURL=context-budget-response.d.ts.map
@@ -17,14 +17,14 @@ function buildPauseMessage(advisory) {
17
17
  const windowNote = advisory.windowSource === "override"
18
18
  ? "your configured window size"
19
19
  : "an estimated window size (unverified — set `contextBudgetGuardModelWindowOverrides` if you know the real limit)";
20
- return `[Plugin Notice] Context budget guard paused this session at ${formatPercent(advisory.percent)}% of ${windowNote} for \`${advisory.model}\`, before hitting the model's actual limit.
21
-
22
- Please use one of these commands to reduce context size:
23
-
24
- • **/compact** - Compress conversation history (recommended)
25
- • **/clear** - Start fresh with empty context
26
- • **/undo** - Remove recent messages
27
-
20
+ return `[Plugin Notice] Context budget guard paused this session at ${formatPercent(advisory.percent)}% of ${windowNote} for \`${advisory.model}\`, before hitting the model's actual limit.
21
+
22
+ Please use one of these commands to reduce context size:
23
+
24
+ • **/compact** - Compress conversation history (recommended)
25
+ • **/clear** - Start fresh with empty context
26
+ • **/undo** - Remove recent messages
27
+
28
28
  Then retry your request. This pause clears itself automatically once your context usage drops back below the threshold.`;
29
29
  }
30
30
  /**
@@ -29,4 +29,3 @@ export declare function handleContextOverflow(response: Response, model?: string
29
29
  } | {
30
30
  handled: false;
31
31
  }>;
32
- //# sourceMappingURL=context-overflow.d.ts.map
@@ -33,16 +33,16 @@ export function isContextOverflowError(status, bodyText) {
33
33
  /**
34
34
  * The message shown to users when context overflow occurs
35
35
  */
36
- const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
37
-
38
- Please use one of these commands to reduce context size:
39
-
40
- • **/compact** - Compress conversation history (recommended)
41
- • **/clear** - Start fresh with empty context
42
- • **/undo** - Remove recent messages
43
-
44
- Then retry your request.
45
-
36
+ const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
37
+
38
+ Please use one of these commands to reduce context size:
39
+
40
+ • **/compact** - Compress conversation history (recommended)
41
+ • **/clear** - Start fresh with empty context
42
+ • **/undo** - Remove recent messages
43
+
44
+ Then retry your request.
45
+
46
46
  Alternatively, you can switch to a model with a larger context window.`;
47
47
  /**
48
48
  * Creates a synthetic SSE response for context overflow errors.
@@ -87,4 +87,3 @@ export declare function loadDashboardDisplaySettings(): Promise<DashboardDisplay
87
87
  */
88
88
  export declare function saveDashboardDisplaySettings(settings: DashboardDisplaySettings): Promise<void>;
89
89
  export {};
90
- //# sourceMappingURL=dashboard-settings.d.ts.map
@@ -41,4 +41,3 @@ export declare class EntitlementCache {
41
41
  prune(now?: number): number;
42
42
  snapshot(now?: number): EntitlementCacheSnapshot;
43
43
  }
44
- //# sourceMappingURL=entitlement-cache.d.ts.map