codex-multi-auth 2.18.0 → 2.19.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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/lib/account-policy.d.ts +3 -1
- package/dist/lib/account-policy.js +21 -5
- package/dist/lib/codex-manager/commands/history.js +3 -1
- package/dist/lib/codex-manager/commands/status.js +8 -3
- package/dist/lib/codex-manager/formatters/subscription-status.d.ts +16 -0
- package/dist/lib/codex-manager/formatters/subscription-status.js +69 -0
- package/dist/lib/codex-manager/health-check.js +17 -12
- package/dist/lib/codex-manager/quota-cache-helpers.js +8 -4
- package/dist/lib/model-route-policy.d.ts +1 -1
- package/dist/lib/quota-cache.d.ts +6 -0
- package/dist/lib/quota-cache.js +33 -16
- package/dist/lib/quota-probe.d.ts +3 -0
- package/dist/lib/quota-probe.js +5 -4
- package/dist/lib/quota-readiness.d.ts +1 -1
- package/dist/lib/quota-readiness.js +6 -2
- package/dist/lib/runtime/account-model-catalog.d.ts +1 -1
- package/dist/lib/runtime/subscription-first-use.js +1 -1
- package/package.json +2 -2
- package/scripts/codex.js +70 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/account-policy.d.ts.map +0 -1
- package/dist/lib/accounts/rate-limits.d.ts.map +0 -1
- package/dist/lib/accounts.d.ts.map +0 -1
- package/dist/lib/api-route-store.d.ts.map +0 -1
- package/dist/lib/audit.d.ts.map +0 -1
- package/dist/lib/auth/account-access.d.ts.map +0 -1
- package/dist/lib/auth/auth.d.ts.map +0 -1
- package/dist/lib/auth/browser.d.ts.map +0 -1
- package/dist/lib/auth/callback-guidance.d.ts.map +0 -1
- package/dist/lib/auth/device-auth.d.ts.map +0 -1
- package/dist/lib/auth/index.d.ts.map +0 -1
- package/dist/lib/auth/org-override.d.ts.map +0 -1
- package/dist/lib/auth/server.d.ts.map +0 -1
- package/dist/lib/auth/token-utils.d.ts.map +0 -1
- package/dist/lib/auth-rate-limit.d.ts.map +0 -1
- package/dist/lib/budget-guard.d.ts.map +0 -1
- package/dist/lib/capability-policy.d.ts.map +0 -1
- package/dist/lib/circuit-breaker.d.ts.map +0 -1
- package/dist/lib/cli.d.ts.map +0 -1
- package/dist/lib/codex-cli/index.d.ts.map +0 -1
- package/dist/lib/codex-cli/observability.d.ts.map +0 -1
- package/dist/lib/codex-cli/state.d.ts.map +0 -1
- package/dist/lib/codex-cli/sync.d.ts.map +0 -1
- package/dist/lib/codex-cli/writer.d.ts.map +0 -1
- package/dist/lib/codex-manager/account-credentials.d.ts.map +0 -1
- package/dist/lib/codex-manager/account-manager-commands.d.ts.map +0 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts.map +0 -1
- package/dist/lib/codex-manager/api-login-menu.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-category-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-category-helpers.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-category-prompt.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-settings-controller.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-settings-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-settings-prompt.d.ts.map +0 -1
- package/dist/lib/codex-manager/backend-settings-schema.d.ts.map +0 -1
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/account.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/best.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/bridge.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/budget.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/check.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/config-explain.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/debug-bundle.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/history.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/init-config.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/integrations.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/limits.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/models.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/monitor.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/report.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/resets.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/status.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/switch.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/uninstall.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/unpin.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/usage.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/verify.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/why-selected.d.ts.map +0 -1
- package/dist/lib/codex-manager/commands/workspace.d.ts.map +0 -1
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts.map +0 -1
- package/dist/lib/codex-manager/dashboard-formatters.d.ts.map +0 -1
- package/dist/lib/codex-manager/dashboard-settings-controller.d.ts.map +0 -1
- package/dist/lib/codex-manager/dashboard-settings-data.d.ts.map +0 -1
- package/dist/lib/codex-manager/dashboard-settings-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/experimental-settings-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +0 -1
- package/dist/lib/codex-manager/experimental-settings-schema.d.ts.map +0 -1
- package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/experimental-sync-target.d.ts.map +0 -1
- package/dist/lib/codex-manager/forecast-report-shared.d.ts.map +0 -1
- package/dist/lib/codex-manager/formatters/account-formatters.d.ts.map +0 -1
- package/dist/lib/codex-manager/formatters/index.d.ts.map +0 -1
- package/dist/lib/codex-manager/formatters/model-formatters.d.ts.map +0 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +0 -1
- package/dist/lib/codex-manager/formatters/text-style.d.ts.map +0 -1
- package/dist/lib/codex-manager/health-check.d.ts.map +0 -1
- package/dist/lib/codex-manager/help.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-action-panel.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-flow.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-menu-actions.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-oauth.d.ts.map +0 -1
- package/dist/lib/codex-manager/login-workspace-choice.d.ts.map +0 -1
- package/dist/lib/codex-manager/manual-callback.d.ts.map +0 -1
- package/dist/lib/codex-manager/persist-selected-account.d.ts.map +0 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +0 -1
- package/dist/lib/codex-manager/rate-limit-markers.d.ts.map +0 -1
- package/dist/lib/codex-manager/repair-commands.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub/backend.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub/dashboard.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub/experimental.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub/index.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub/shared.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub-menu.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub-prompt.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-hub.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-panels.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-persist-utils.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-preview.d.ts.map +0 -1
- package/dist/lib/codex-manager/settings-write-queue.d.ts.map +0 -1
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts.map +0 -1
- package/dist/lib/codex-manager/theme-settings-panel.d.ts.map +0 -1
- package/dist/lib/codex-manager/unified-settings-controller.d.ts.map +0 -1
- package/dist/lib/codex-manager/unified-settings-entry.d.ts.map +0 -1
- package/dist/lib/codex-manager.d.ts.map +0 -1
- package/dist/lib/concurrency.d.ts.map +0 -1
- package/dist/lib/config-schema.d.ts.map +0 -1
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/constants.d.ts.map +0 -1
- package/dist/lib/context-budget/model-context-windows.d.ts.map +0 -1
- package/dist/lib/context-budget-guard.d.ts.map +0 -1
- package/dist/lib/context-budget-response.d.ts.map +0 -1
- package/dist/lib/context-overflow.d.ts.map +0 -1
- package/dist/lib/dashboard-settings.d.ts.map +0 -1
- package/dist/lib/entitlement-cache.d.ts.map +0 -1
- package/dist/lib/env-parsing.d.ts.map +0 -1
- package/dist/lib/errors.d.ts.map +0 -1
- package/dist/lib/forecast.d.ts.map +0 -1
- package/dist/lib/fs-retry.d.ts.map +0 -1
- package/dist/lib/health.d.ts.map +0 -1
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/integration-generators.d.ts.map +0 -1
- package/dist/lib/live-account-sync.d.ts.map +0 -1
- package/dist/lib/local-bridge.d.ts.map +0 -1
- package/dist/lib/local-client-tokens.d.ts.map +0 -1
- package/dist/lib/logger.d.ts.map +0 -1
- package/dist/lib/model-capability-matrix.d.ts.map +0 -1
- package/dist/lib/model-route-policy.d.ts.map +0 -1
- package/dist/lib/named-backup-export.d.ts.map +0 -1
- package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +0 -1
- package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +0 -1
- package/dist/lib/oc-chatgpt-target-detection.d.ts.map +0 -1
- package/dist/lib/parallel-probe.d.ts.map +0 -1
- package/dist/lib/policy/runtime-policy.d.ts.map +0 -1
- package/dist/lib/preemptive-quota-scheduler.d.ts.map +0 -1
- package/dist/lib/proactive-refresh.d.ts.map +0 -1
- package/dist/lib/prompts/codex-host-bridge.d.ts.map +0 -1
- package/dist/lib/prompts/codex.d.ts.map +0 -1
- package/dist/lib/prompts/fetch-utils.d.ts.map +0 -1
- package/dist/lib/prompts/host-codex-prompt.d.ts.map +0 -1
- package/dist/lib/quota-cache.d.ts.map +0 -1
- package/dist/lib/quota-probe.d.ts.map +0 -1
- package/dist/lib/quota-readiness.d.ts.map +0 -1
- package/dist/lib/recovery/constants.d.ts.map +0 -1
- package/dist/lib/recovery/storage.d.ts.map +0 -1
- package/dist/lib/recovery/types.d.ts.map +0 -1
- package/dist/lib/recovery.d.ts.map +0 -1
- package/dist/lib/redaction.d.ts.map +0 -1
- package/dist/lib/refresh-guardian.d.ts.map +0 -1
- package/dist/lib/refresh-lease.d.ts.map +0 -1
- package/dist/lib/refresh-queue.d.ts.map +0 -1
- package/dist/lib/request/client-cancellation.d.ts.map +0 -1
- package/dist/lib/request/error-classification.d.ts.map +0 -1
- package/dist/lib/request/failover-config.d.ts.map +0 -1
- package/dist/lib/request/failure-policy.d.ts.map +0 -1
- package/dist/lib/request/fetch-helpers.d.ts.map +0 -1
- package/dist/lib/request/headers.d.ts.map +0 -1
- package/dist/lib/request/helpers/input-utils.d.ts.map +0 -1
- package/dist/lib/request/helpers/model-map.d.ts.map +0 -1
- package/dist/lib/request/helpers/tool-utils.d.ts.map +0 -1
- package/dist/lib/request/index.d.ts.map +0 -1
- package/dist/lib/request/rate-limit-backoff.d.ts.map +0 -1
- package/dist/lib/request/rate-limit-decision.d.ts.map +0 -1
- package/dist/lib/request/request-attempt-budget.d.ts.map +0 -1
- package/dist/lib/request/request-init.d.ts.map +0 -1
- package/dist/lib/request/request-resilience.d.ts.map +0 -1
- package/dist/lib/request/request-transformer.d.ts.map +0 -1
- package/dist/lib/request/response-compaction.d.ts.map +0 -1
- package/dist/lib/request/response-handler.d.ts.map +0 -1
- package/dist/lib/request/response-metadata.d.ts.map +0 -1
- package/dist/lib/request/response-outcome.d.ts.map +0 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +0 -1
- package/dist/lib/request/stream-failover.d.ts.map +0 -1
- package/dist/lib/request/token-refresh.d.ts.map +0 -1
- package/dist/lib/request/url-rewriting.d.ts.map +0 -1
- package/dist/lib/request/wait-utils.d.ts.map +0 -1
- package/dist/lib/rotation.d.ts.map +0 -1
- package/dist/lib/routing-mutex.d.ts.map +0 -1
- package/dist/lib/routing-profiles.d.ts.map +0 -1
- package/dist/lib/runtime/account-check-helpers.d.ts.map +0 -1
- package/dist/lib/runtime/account-check-types.d.ts.map +0 -1
- package/dist/lib/runtime/account-check.d.ts.map +0 -1
- package/dist/lib/runtime/account-manager-cache-entry.d.ts.map +0 -1
- package/dist/lib/runtime/account-manager-cache.d.ts.map +0 -1
- package/dist/lib/runtime/account-model-catalog.d.ts.map +0 -1
- package/dist/lib/runtime/account-pool.d.ts.map +0 -1
- package/dist/lib/runtime/account-reset-credits.d.ts.map +0 -1
- package/dist/lib/runtime/account-scope.d.ts.map +0 -1
- package/dist/lib/runtime/account-select-event.d.ts.map +0 -1
- package/dist/lib/runtime/account-selection.d.ts.map +0 -1
- package/dist/lib/runtime/account-state.d.ts.map +0 -1
- package/dist/lib/runtime/account-status.d.ts.map +0 -1
- package/dist/lib/runtime/account-storage-scope-entry.d.ts.map +0 -1
- package/dist/lib/runtime/api-model-capabilities.d.ts.map +0 -1
- package/dist/lib/runtime/api-model-runtime.d.ts.map +0 -1
- package/dist/lib/runtime/app-bind.d.ts.map +0 -1
- package/dist/lib/runtime/app-helper-selection.d.ts.map +0 -1
- package/dist/lib/runtime/auth-facade.d.ts.map +0 -1
- package/dist/lib/runtime/automatic-account-checks.d.ts.map +0 -1
- package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +0 -1
- package/dist/lib/runtime/browser-oauth-flow.d.ts.map +0 -1
- package/dist/lib/runtime/capability-boost.d.ts.map +0 -1
- package/dist/lib/runtime/catalog-capabilities.d.ts.map +0 -1
- package/dist/lib/runtime/config-toml.d.ts.map +0 -1
- package/dist/lib/runtime/context-budget-settings.d.ts.map +0 -1
- package/dist/lib/runtime/event-handler.d.ts.map +0 -1
- package/dist/lib/runtime/first-run.d.ts.map +0 -1
- package/dist/lib/runtime/flagged-verify-types.d.ts.map +0 -1
- package/dist/lib/runtime/hydrate-emails.d.ts.map +0 -1
- package/dist/lib/runtime/inference-activity.d.ts.map +0 -1
- package/dist/lib/runtime/live-sync-entry.d.ts.map +0 -1
- package/dist/lib/runtime/live-sync.d.ts.map +0 -1
- package/dist/lib/runtime/loader-setup.d.ts.map +0 -1
- package/dist/lib/runtime/login-menu-accounts.d.ts.map +0 -1
- package/dist/lib/runtime/manual-oauth-flow.d.ts.map +0 -1
- package/dist/lib/runtime/model-discovery-status.d.ts.map +0 -1
- package/dist/lib/runtime/native-account-storage.d.ts.map +0 -1
- package/dist/lib/runtime/native-account-sync.d.ts.map +0 -1
- package/dist/lib/runtime/native-binding-lock.d.ts.map +0 -1
- package/dist/lib/runtime/native-client-auth.d.ts.map +0 -1
- package/dist/lib/runtime/native-provider-config.d.ts.map +0 -1
- package/dist/lib/runtime/native-rate-limits.d.ts.map +0 -1
- package/dist/lib/runtime/preemptive-quota.d.ts.map +0 -1
- package/dist/lib/runtime/quota-headers.d.ts.map +0 -1
- package/dist/lib/runtime/quota-probe.d.ts.map +0 -1
- package/dist/lib/runtime/quota-settings.d.ts.map +0 -1
- package/dist/lib/runtime/refresh-guardian-entry.d.ts.map +0 -1
- package/dist/lib/runtime/refresh-guardian.d.ts.map +0 -1
- package/dist/lib/runtime/request-init.d.ts.map +0 -1
- package/dist/lib/runtime/reset-credit-routing.d.ts.map +0 -1
- package/dist/lib/runtime/reset-credits.d.ts.map +0 -1
- package/dist/lib/runtime/response-output-history.d.ts.map +0 -1
- package/dist/lib/runtime/responses-websocket.d.ts.map +0 -1
- package/dist/lib/runtime/resume-picker.d.ts.map +0 -1
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +0 -1
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +0 -1
- package/dist/lib/runtime/rotation-server-types.d.ts.map +0 -1
- package/dist/lib/runtime/rotation-storage-meta.d.ts.map +0 -1
- package/dist/lib/runtime/rotation-token-refresh.d.ts.map +0 -1
- package/dist/lib/runtime/runtime-capability-failures.d.ts.map +0 -1
- package/dist/lib/runtime/runtime-current-account.d.ts.map +0 -1
- package/dist/lib/runtime/runtime-observability.d.ts.map +0 -1
- package/dist/lib/runtime/runtime-services.d.ts.map +0 -1
- package/dist/lib/runtime/session-affinity-entry.d.ts.map +0 -1
- package/dist/lib/runtime/session-recovery.d.ts.map +0 -1
- package/dist/lib/runtime/status-marker.d.ts.map +0 -1
- package/dist/lib/runtime/storage-scope.d.ts.map +0 -1
- package/dist/lib/runtime/subscription-first-use.d.ts.map +0 -1
- package/dist/lib/runtime/subscription-quota-event.d.ts.map +0 -1
- package/dist/lib/runtime/subscription-quota-order.d.ts.map +0 -1
- package/dist/lib/runtime/toast.d.ts.map +0 -1
- package/dist/lib/runtime/ui-runtime-entry.d.ts.map +0 -1
- package/dist/lib/runtime/ui-runtime.d.ts.map +0 -1
- package/dist/lib/runtime/verify-flagged.d.ts.map +0 -1
- package/dist/lib/runtime/workspace-model-scopes.d.ts.map +0 -1
- package/dist/lib/runtime-constants.d.ts.map +0 -1
- package/dist/lib/runtime-paths.d.ts.map +0 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +0 -1
- package/dist/lib/schemas.d.ts.map +0 -1
- package/dist/lib/session-affinity.d.ts.map +0 -1
- package/dist/lib/shutdown.d.ts.map +0 -1
- package/dist/lib/storage/account-clear-entry.d.ts.map +0 -1
- package/dist/lib/storage/account-clear.d.ts.map +0 -1
- package/dist/lib/storage/account-match-utils.d.ts.map +0 -1
- package/dist/lib/storage/account-persistence.d.ts.map +0 -1
- package/dist/lib/storage/account-port.d.ts.map +0 -1
- package/dist/lib/storage/account-save-entry.d.ts.map +0 -1
- package/dist/lib/storage/account-save.d.ts.map +0 -1
- package/dist/lib/storage/account-snapshot.d.ts.map +0 -1
- package/dist/lib/storage/backup-metadata-builder.d.ts.map +0 -1
- package/dist/lib/storage/backup-metadata.d.ts.map +0 -1
- package/dist/lib/storage/backup-paths.d.ts.map +0 -1
- package/dist/lib/storage/backup-restore.d.ts.map +0 -1
- package/dist/lib/storage/cache-artifacts.d.ts.map +0 -1
- package/dist/lib/storage/credential-sidecars.d.ts.map +0 -1
- package/dist/lib/storage/error-hints.d.ts.map +0 -1
- package/dist/lib/storage/file-lock.d.ts.map +0 -1
- package/dist/lib/storage/file-paths.d.ts.map +0 -1
- package/dist/lib/storage/fixture-guards.d.ts.map +0 -1
- package/dist/lib/storage/flagged-entry.d.ts.map +0 -1
- package/dist/lib/storage/flagged-load-entry.d.ts.map +0 -1
- package/dist/lib/storage/flagged-save-entry.d.ts.map +0 -1
- package/dist/lib/storage/flagged-storage-file.d.ts.map +0 -1
- package/dist/lib/storage/flagged-storage-io.d.ts.map +0 -1
- package/dist/lib/storage/flagged-storage.d.ts.map +0 -1
- package/dist/lib/storage/gitignore.d.ts.map +0 -1
- package/dist/lib/storage/hash.d.ts.map +0 -1
- package/dist/lib/storage/health.d.ts.map +0 -1
- package/dist/lib/storage/identity.d.ts.map +0 -1
- package/dist/lib/storage/import-export.d.ts.map +0 -1
- package/dist/lib/storage/metadata-section.d.ts.map +0 -1
- package/dist/lib/storage/migrations.d.ts.map +0 -1
- package/dist/lib/storage/named-backup-entry.d.ts.map +0 -1
- package/dist/lib/storage/named-backups-entry.d.ts.map +0 -1
- package/dist/lib/storage/named-backups.d.ts.map +0 -1
- package/dist/lib/storage/path-state.d.ts.map +0 -1
- package/dist/lib/storage/paths.d.ts.map +0 -1
- package/dist/lib/storage/pending-auth.d.ts.map +0 -1
- package/dist/lib/storage/project-migration.d.ts.map +0 -1
- package/dist/lib/storage/public-types.d.ts.map +0 -1
- package/dist/lib/storage/record-identity.d.ts.map +0 -1
- package/dist/lib/storage/record-utils.d.ts.map +0 -1
- package/dist/lib/storage/restore-assessment.d.ts.map +0 -1
- package/dist/lib/storage/restore-backup-entry.d.ts.map +0 -1
- package/dist/lib/storage/restore-metadata.d.ts.map +0 -1
- package/dist/lib/storage/save-retry.d.ts.map +0 -1
- package/dist/lib/storage/snapshot-inspectors.d.ts.map +0 -1
- package/dist/lib/storage/snapshot-merge.d.ts.map +0 -1
- package/dist/lib/storage/storage-parser.d.ts.map +0 -1
- package/dist/lib/storage/transactions.d.ts.map +0 -1
- package/dist/lib/storage.d.ts.map +0 -1
- package/dist/lib/synthetic-response.d.ts.map +0 -1
- package/dist/lib/table-formatter.d.ts.map +0 -1
- package/dist/lib/temp-path.d.ts.map +0 -1
- package/dist/lib/tools/hashline-tools.d.ts.map +0 -1
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/ui/ansi.d.ts.map +0 -1
- package/dist/lib/ui/auth-menu-builder.d.ts.map +0 -1
- package/dist/lib/ui/auth-menu.d.ts.map +0 -1
- package/dist/lib/ui/check-progress.d.ts.map +0 -1
- package/dist/lib/ui/confirm.d.ts.map +0 -1
- package/dist/lib/ui/display-width.d.ts.map +0 -1
- package/dist/lib/ui/format.d.ts.map +0 -1
- package/dist/lib/ui/index.d.ts.map +0 -1
- package/dist/lib/ui/runtime.d.ts.map +0 -1
- package/dist/lib/ui/select.d.ts.map +0 -1
- package/dist/lib/ui/theme.d.ts.map +0 -1
- package/dist/lib/ui/ui-copy.d.ts.map +0 -1
- package/dist/lib/unified-settings.d.ts.map +0 -1
- package/dist/lib/update-notice.d.ts.map +0 -1
- package/dist/lib/usage/index.d.ts.map +0 -1
- package/dist/lib/usage/ledger.d.ts.map +0 -1
- package/dist/lib/usage/pricing.d.ts.map +0 -1
- package/dist/lib/usage/redaction.d.ts.map +0 -1
- package/dist/lib/usage/stream-usage-deferral.d.ts.map +0 -1
- package/dist/lib/usage/types.d.ts.map +0 -1
- package/dist/lib/usage/usage-extraction.d.ts.map +0 -1
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/wsl.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
4
4
|
"description": "Install and operate codex-multi-auth for the official @openai/codex CLI with multi-account OAuth rotation, switching, health checks, and recovery tools.",
|
|
5
5
|
"interface": {
|
|
6
6
|
"composerIcon": "./assets/codex-multi-auth-icon.svg"
|
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ Common symptoms — wrong active account, OAuth callback port `1455` already bou
|
|
|
137
137
|
|
|
138
138
|
## Release notes
|
|
139
139
|
|
|
140
|
-
- Current stable: [v2.
|
|
140
|
+
- Current stable: [v2.19.0](docs/releases/v2.19.0.md) — `npm i -g codex-multi-auth`
|
|
141
141
|
- Earlier stable lines: [v2.6.0](docs/releases/v2.6.0.md), [v2.5.0](docs/releases/v2.5.0.md)
|
|
142
142
|
- Full release archive: [docs/README.md#release-history](docs/README.md#release-history)
|
|
143
143
|
|
|
@@ -20,7 +20,9 @@ export declare function getAccountPolicyPath(): string;
|
|
|
20
20
|
export declare function getAccountPolicyKey(account: Pick<AccountMetadataV3, "accountId" | "email"> & {
|
|
21
21
|
refreshToken?: string | null;
|
|
22
22
|
}, _index?: number): string;
|
|
23
|
-
export declare function loadAccountPolicyStore(
|
|
23
|
+
export declare function loadAccountPolicyStore(options?: {
|
|
24
|
+
strict?: boolean;
|
|
25
|
+
}): Promise<AccountPolicyStore>;
|
|
24
26
|
export declare function saveAccountPolicyStore(store: AccountPolicyStore, baseline?: AccountPolicyStore): Promise<void>;
|
|
25
27
|
/**
|
|
26
28
|
* Run a policy-store read→mutate→write inside the write queue (in-process
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
3
|
import { basename, join } from "node:path";
|
|
4
4
|
import { logWarn } from "./logger.js";
|
|
5
5
|
import { getCodexMultiAuthDir } from "./runtime-paths.js";
|
|
@@ -100,14 +100,30 @@ export function getAccountPolicyKey(account, _index) {
|
|
|
100
100
|
(refreshFallback ? `refresh:${refreshFallback}` : "unknown");
|
|
101
101
|
return `sha256:${createHash("sha256").update(identity).digest("hex")}`;
|
|
102
102
|
}
|
|
103
|
-
export async function loadAccountPolicyStore() {
|
|
103
|
+
export async function loadAccountPolicyStore(options = {}) {
|
|
104
104
|
const path = getAccountPolicyPath();
|
|
105
|
-
if (!existsSync(path))
|
|
106
|
-
return emptyStore();
|
|
107
105
|
try {
|
|
108
|
-
|
|
106
|
+
const parsed = JSON.parse(await readFileWithRetry(path));
|
|
107
|
+
if (options.strict) {
|
|
108
|
+
if (!isRecord(parsed) || parsed.version !== 1 || !isRecord(parsed.accounts)) {
|
|
109
|
+
throw new Error("Invalid account policy store");
|
|
110
|
+
}
|
|
111
|
+
for (const [key, row] of Object.entries(parsed.accounts)) {
|
|
112
|
+
if (!key.startsWith("sha256:"))
|
|
113
|
+
continue;
|
|
114
|
+
// Legacy rows may omit flags; explicit malformed values are not OFF.
|
|
115
|
+
if (!isRecord(row) || ["autoPrime", "paused", "drained"].some(flag => flag in row && typeof row[flag] !== "boolean")) {
|
|
116
|
+
throw new Error("Invalid account policy row");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return normalizeStore(parsed);
|
|
109
121
|
}
|
|
110
122
|
catch (error) {
|
|
123
|
+
if (error.code === "ENOENT")
|
|
124
|
+
return emptyStore();
|
|
125
|
+
if (options.strict)
|
|
126
|
+
throw error;
|
|
111
127
|
logWarn(`Failed to load account policies from ${basename(path)}: ${error instanceof Error ? error.message : String(error)}`);
|
|
112
128
|
return emptyStore();
|
|
113
129
|
}
|
|
@@ -107,7 +107,9 @@ function parseRollout(rolloutPath, deps, previewLimit) {
|
|
|
107
107
|
if (typeof record.timestamp === "string") {
|
|
108
108
|
updatedAt = record.timestamp;
|
|
109
109
|
}
|
|
110
|
-
|
|
110
|
+
// Forked rollouts append the parent's session_meta after their own, so
|
|
111
|
+
// only the first one describes this rollout.
|
|
112
|
+
if (record.type === "session_meta" && !hasSessionMeta) {
|
|
111
113
|
const payload = record.payload;
|
|
112
114
|
const metaId = readStringField(payload, "id");
|
|
113
115
|
if (metaId)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { subscriptionStatus, formatSubscriptionStatus } from "../formatters/subscription-status.js";
|
|
1
2
|
import { resetSnapshotQuota } from "../../runtime/reset-credits.js";
|
|
2
3
|
import { resetTargetForStoredAccount } from "../../runtime/account-reset-credits.js";
|
|
3
4
|
import { subscriptionQuotaPreference, compareSubscriptionQuota, usesSubscriptionReserve, SUBSCRIPTION_RESERVE_PERCENT } from "../../runtime/subscription-quota-order.js";
|
|
@@ -87,7 +88,8 @@ export async function runStatusCommand(deps) {
|
|
|
87
88
|
const modelInventory = await deps.loadModelInventory?.();
|
|
88
89
|
const resetCredits = await deps.loadResetCreditState?.().catch(() => null);
|
|
89
90
|
const resetSnapshot = (account) => { const target = resetTargetForStoredAccount(account); return target ? resetCredits?.snapshots[target.key] : undefined; };
|
|
90
|
-
|
|
91
|
+
let policiesUnavailable = false;
|
|
92
|
+
const accountPolicies = await (deps.loadAccountPolicies ?? loadAccountPolicyStore)({ strict: true }).catch(() => { policiesUnavailable = true; return { version: 1, accounts: {} }; });
|
|
91
93
|
if (!deps.json && deps.loadModelInventory)
|
|
92
94
|
for (const line of formatModelInventory(modelInventory ?? null))
|
|
93
95
|
logInfo(line);
|
|
@@ -136,6 +138,7 @@ export async function runStatusCommand(deps) {
|
|
|
136
138
|
const now = deps.getNow?.() ?? Date.now();
|
|
137
139
|
const activeIndex = storage.accounts.length ? deps.resolveActiveIndex(storage, "codex") : -1;
|
|
138
140
|
const quotaCache = await deps.loadQuotaCache?.() ?? null;
|
|
141
|
+
const subscriptionStatuses = storage.accounts.map(account => subscriptionStatus(account, findQuotaCacheEntryForAccount(quotaCache, account, storage.accounts), policiesUnavailable ? undefined : accountPolicies.accounts[getAccountPolicyKey(account)] ?? {}, now));
|
|
139
142
|
const forecastQuotas = storage.accounts.map(account => {
|
|
140
143
|
const cached = findQuotaCacheEntryForAccount(quotaCache, account, storage.accounts);
|
|
141
144
|
const reset = resetSnapshot(account);
|
|
@@ -217,6 +220,7 @@ export async function runStatusCommand(deps) {
|
|
|
217
220
|
const markers = buildAccountMarkers(account, i, activeIndex, runtimeCurrent, now, quotaCache, storage.accounts, deps.formatRateLimitEntry);
|
|
218
221
|
return {
|
|
219
222
|
index: i,
|
|
223
|
+
subscription: subscriptionStatuses[i],
|
|
220
224
|
resetCreditsAvailable: resetSnapshot(account)?.availableCount ?? null,
|
|
221
225
|
resetCreditsCheckedAt: resetSnapshot(account)?.updatedAt ?? null,
|
|
222
226
|
label: formatAccountLabel(account, i),
|
|
@@ -335,8 +339,9 @@ export async function runStatusCommand(deps) {
|
|
|
335
339
|
: `inference not yet recorded; ${activity}`;
|
|
336
340
|
logInfo(`${paint(`${i + 1}. ${label}`, "heading")}${paint(markerLabel, markers.some(m => /disabled|cooldown|exhausted|limited|invalid/.test(m)) ? "warning" : "success")} ${paint(lastUsed, "muted")}`);
|
|
337
341
|
logInfo(` ${paint(`priority tier: ${accountPolicies.accounts[getAccountPolicyKey(account, i)]?.priority ?? 1}`, "accent")}`);
|
|
338
|
-
|
|
339
|
-
|
|
342
|
+
const subscription = subscriptionStatuses[i];
|
|
343
|
+
if (subscription)
|
|
344
|
+
logInfo(` ${formatSubscriptionStatus(subscription)}`);
|
|
340
345
|
if (appBindStatus?.nativeOpenai) {
|
|
341
346
|
const preference = quotaPreferences[i];
|
|
342
347
|
const order = automaticOrder.get(i);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AccountPolicy } from "../../account-policy.js";
|
|
2
|
+
import type { QuotaCacheEntry } from "../../quota-cache.js";
|
|
3
|
+
import type { AccountMetadataV3 } from "../../storage.js";
|
|
4
|
+
/** Display only observed evidence; never age a placeholder into a running timer. */
|
|
5
|
+
export declare function subscriptionStatus(account: AccountMetadataV3, entry: QuotaCacheEntry | null, policy: Partial<AccountPolicy> | undefined, now: number): {
|
|
6
|
+
planType: string | null;
|
|
7
|
+
planLabel: string;
|
|
8
|
+
selectedWorkspace: string;
|
|
9
|
+
autoPrime: boolean | null;
|
|
10
|
+
primingState: "failed" | "unknown" | "awaiting-first-use" | "timer-running" | "used" | "completed" | "not-applicable";
|
|
11
|
+
primingFailure: "timed out" | "stream ended early" | "upstream failed" | "response too large" | "network error" | null;
|
|
12
|
+
automaticBlock: string | null;
|
|
13
|
+
freshness: string;
|
|
14
|
+
observedAt: number | null;
|
|
15
|
+
};
|
|
16
|
+
export declare function formatSubscriptionStatus(value: ReturnType<typeof subscriptionStatus>): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { needsSubscriptionFirstUse } from "../../runtime/subscription-first-use.js";
|
|
2
|
+
const PLAN_LABELS = new Map([
|
|
3
|
+
["free", "Free"], ["plus", "Plus"], ["pro", "Pro 200"],
|
|
4
|
+
["prolite", "Pro 100"], ["promax", "Pro 500"], ["team", "Business"],
|
|
5
|
+
["business", "Business"], ["enterprise", "Enterprise"], ["edu", "Edu"],
|
|
6
|
+
]);
|
|
7
|
+
const STATE_LABELS = {
|
|
8
|
+
unknown: "Priming status unknown",
|
|
9
|
+
"awaiting-first-use": "Awaiting first use",
|
|
10
|
+
"timer-running": "Reset timer running",
|
|
11
|
+
used: "Usage recorded",
|
|
12
|
+
completed: "First-use completed; timer not yet verified",
|
|
13
|
+
failed: "Priming failed",
|
|
14
|
+
"not-applicable": "Priming not applicable",
|
|
15
|
+
};
|
|
16
|
+
/** Display only observed evidence; never age a placeholder into a running timer. */
|
|
17
|
+
export function subscriptionStatus(account, entry, policy, now) {
|
|
18
|
+
const workspace = account.workspaces?.[account.currentWorkspaceIndex ?? 0];
|
|
19
|
+
const selectedWorkspace = workspace
|
|
20
|
+
? workspace.name?.replace(/\s*\(role:.*$|\s*\[id:.*$/g, "").trim() || "Unnamed workspace"
|
|
21
|
+
: account.workspaces?.length ? "Invalid workspace selection" : "Stored binding (workspace unknown)";
|
|
22
|
+
const freshness = !entry ? "missing"
|
|
23
|
+
: entry.updatedAt > now || now - entry.updatedAt > 30 * 60000 ? "stale" : "fresh";
|
|
24
|
+
const planType = entry?.planType?.trim().toLowerCase() ?? null;
|
|
25
|
+
const planLabel = PLAN_LABELS.get(planType ?? "") ?? "Unknown plan";
|
|
26
|
+
let primingState = "unknown";
|
|
27
|
+
if (entry && freshness === "fresh" && entry.status === 200) {
|
|
28
|
+
const windows = [entry.primary, entry.secondary].filter(w => w.windowMinutes !== 0);
|
|
29
|
+
if (!planType || !PLAN_LABELS.has(planType))
|
|
30
|
+
primingState = "unknown";
|
|
31
|
+
else if (!["plus", "pro", "prolite", "promax"].includes(planType))
|
|
32
|
+
primingState = "not-applicable";
|
|
33
|
+
else if (entry.primingFailure)
|
|
34
|
+
primingState = "failed";
|
|
35
|
+
else if (entry.primingCompleted)
|
|
36
|
+
primingState = "completed";
|
|
37
|
+
else if (windows.some(w => typeof w.usedPercent === "number" && w.usedPercent > 0)) {
|
|
38
|
+
primingState = "used";
|
|
39
|
+
}
|
|
40
|
+
else if (windows.some(w => typeof w.windowMinutes === "number" && w.windowMinutes > 0 &&
|
|
41
|
+
typeof w.resetAtMs === "number" && w.resetAtMs > now &&
|
|
42
|
+
w.resetAtMs - entry.updatedAt < w.windowMinutes * 60000 - 2000)) {
|
|
43
|
+
primingState = "timer-running";
|
|
44
|
+
}
|
|
45
|
+
else if (needsSubscriptionFirstUse(entry, entry.updatedAt)) {
|
|
46
|
+
primingState = "awaiting-first-use";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const automaticBlock = account.enabled === false ? "account disabled"
|
|
50
|
+
: account.authInvalidatedAt ? "sign-in required"
|
|
51
|
+
: policy?.paused ? "paused"
|
|
52
|
+
: policy?.drained ? "drained"
|
|
53
|
+
: (account.coolingDownUntil ?? 0) > now ? "cooling down"
|
|
54
|
+
: account.workspaces?.length && (!workspace || workspace.enabled === false) ? "workspace unavailable"
|
|
55
|
+
: null;
|
|
56
|
+
return {
|
|
57
|
+
planType, planLabel, selectedWorkspace,
|
|
58
|
+
autoPrime: policy ? policy.autoPrime === true : null,
|
|
59
|
+
primingState, primingFailure: entry?.primingFailure ?? null,
|
|
60
|
+
automaticBlock, freshness, observedAt: entry?.updatedAt ?? null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function formatSubscriptionStatus(value) {
|
|
64
|
+
const freshness = value.freshness === "stale" ? " (stale; run check accounts)"
|
|
65
|
+
: value.freshness === "missing" ? " (not observed)" : "";
|
|
66
|
+
const autoPrime = value.autoPrime === null ? "unknown" : value.autoPrime ? "ON" : "OFF";
|
|
67
|
+
const block = value.automaticBlock ? `; blocked: ${value.automaticBlock}` : "";
|
|
68
|
+
return `${value.selectedWorkspace} · ${value.planLabel}${freshness} · Auto-prime ${autoPrime} · ${STATE_LABELS[value.primingState]}${block}`;
|
|
69
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { subscriptionStatus, formatSubscriptionStatus } from "./formatters/subscription-status.js";
|
|
2
|
+
import { getAccountPolicyKey, loadAccountPolicyStore } from "../account-policy.js";
|
|
3
|
+
import { automaticCheckWorkspaceId } from "../runtime/automatic-account-checks.js";
|
|
1
4
|
import { refreshAndPrintResetCredits } from "../runtime/account-reset-credits.js";
|
|
2
5
|
import { mapWithConcurrency } from "../concurrency.js";
|
|
3
6
|
import { withCheckProgress } from "../ui/check-progress.js";
|
|
@@ -16,7 +19,7 @@ import { loadAccounts, saveAccounts, setStoragePath } from "../storage.js";
|
|
|
16
19
|
import { applyTokenAccountIdentity, hasLikelyInvalidRefreshToken, hasUsableAccessToken, } from "./account-credentials.js";
|
|
17
20
|
import { saveAccountsWithRetry } from "./forecast-report-shared.js";
|
|
18
21
|
import { formatModelInspection, formatQuotaSnapshotForDashboard, formatResultSummary, inspectRequestedModel, normalizeFailureDetail, styleAccountDetailText, stylePromptText, } from "./formatters/index.js";
|
|
19
|
-
import { cloneQuotaCacheData, DEFAULT_LIVE_PROBE_MODEL, pruneUnsafeQuotaEmailCacheEntry,
|
|
22
|
+
import { cloneQuotaCacheData, DEFAULT_LIVE_PROBE_MODEL, pruneUnsafeQuotaEmailCacheEntry, updateQuotaCacheForWorkspace, } from "./quota-cache-helpers.js";
|
|
20
23
|
function appendAuthInvalidationMarker(account, detail) {
|
|
21
24
|
return typeof account.authInvalidatedAt === "number" &&
|
|
22
25
|
Number.isFinite(account.authInvalidatedAt)
|
|
@@ -44,6 +47,8 @@ export async function runHealthCheck(options = {}) {
|
|
|
44
47
|
let quotaEmailFallbackState = liveProbe && quotaCache
|
|
45
48
|
? buildQuotaEmailFallbackState(storage.accounts)
|
|
46
49
|
: null;
|
|
50
|
+
const policies = await loadAccountPolicyStore({ strict: true }).catch(() => null);
|
|
51
|
+
const subscriptionLine = (account, snapshot) => formatSubscriptionStatus(subscriptionStatus(account, { ...snapshot, updatedAt: snapshot.observedAt ?? Date.now() }, policies ? policies.accounts[getAccountPolicyKey(account)] ?? {} : undefined, Date.now()));
|
|
47
52
|
let changed = false;
|
|
48
53
|
let ok = 0;
|
|
49
54
|
let failed = 0;
|
|
@@ -62,7 +67,7 @@ export async function runHealthCheck(options = {}) {
|
|
|
62
67
|
const quickProbes = new Map();
|
|
63
68
|
if (liveProbe && !forceRefresh) {
|
|
64
69
|
const candidates = storage.accounts.flatMap((account, index) => {
|
|
65
|
-
const accountId =
|
|
70
|
+
const accountId = automaticCheckWorkspaceId(account);
|
|
66
71
|
return hasUsableAccessToken(account, now) && account.accessToken && accountId
|
|
67
72
|
? [{ index, accountId, accessToken: account.accessToken }] : [];
|
|
68
73
|
});
|
|
@@ -104,14 +109,14 @@ export async function runHealthCheck(options = {}) {
|
|
|
104
109
|
if (liveProbe) {
|
|
105
110
|
const currentAccessToken = account.accessToken;
|
|
106
111
|
const probeAccountId = currentAccessToken
|
|
107
|
-
? (account
|
|
112
|
+
? automaticCheckWorkspaceId(account)
|
|
108
113
|
: undefined;
|
|
109
114
|
if (!probeAccountId || !currentAccessToken) {
|
|
110
115
|
warnings += 1;
|
|
111
116
|
signedInOnly += 1;
|
|
112
117
|
healthTone = "warning";
|
|
113
118
|
healthDetail =
|
|
114
|
-
"signed in (live check skipped: missing account ID)";
|
|
119
|
+
"signed in (live check skipped: missing account ID or unavailable selected workspace)";
|
|
115
120
|
}
|
|
116
121
|
else {
|
|
117
122
|
try {
|
|
@@ -124,10 +129,10 @@ export async function runHealthCheck(options = {}) {
|
|
|
124
129
|
model: modelInspection.normalized,
|
|
125
130
|
}), console.log);
|
|
126
131
|
if (workingQuotaCache) {
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
updateQuotaCacheForWorkspace(workingQuotaCache, account, probeAccountId, snapshot, storage.accounts);
|
|
133
|
+
quotaCacheChanged = true;
|
|
129
134
|
}
|
|
130
|
-
healthDetail = formatQuotaSnapshotForDashboard(snapshot, display);
|
|
135
|
+
healthDetail = formatQuotaSnapshotForDashboard(snapshot, display) + " | " + subscriptionLine(account, snapshot);
|
|
131
136
|
if (snapshot.primingFailure) {
|
|
132
137
|
healthTone = "warning";
|
|
133
138
|
warnings += 1;
|
|
@@ -210,13 +215,13 @@ export async function runHealthCheck(options = {}) {
|
|
|
210
215
|
let healthyMessage = "working now";
|
|
211
216
|
let healthyTone = "success";
|
|
212
217
|
if (liveProbe) {
|
|
213
|
-
const probeAccountId = account
|
|
218
|
+
const probeAccountId = automaticCheckWorkspaceId(account);
|
|
214
219
|
if (!probeAccountId) {
|
|
215
220
|
warnings += 1;
|
|
216
221
|
signedInOnly += 1;
|
|
217
222
|
healthyTone = "warning";
|
|
218
223
|
healthyMessage =
|
|
219
|
-
"signed in (live check skipped: missing account ID)";
|
|
224
|
+
"signed in (live check skipped: missing account ID or unavailable selected workspace)";
|
|
220
225
|
}
|
|
221
226
|
else {
|
|
222
227
|
try {
|
|
@@ -226,10 +231,10 @@ export async function runHealthCheck(options = {}) {
|
|
|
226
231
|
model: modelInspection.normalized,
|
|
227
232
|
}), console.log);
|
|
228
233
|
if (workingQuotaCache) {
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
updateQuotaCacheForWorkspace(workingQuotaCache, account, probeAccountId, snapshot, storage.accounts);
|
|
235
|
+
quotaCacheChanged = true;
|
|
231
236
|
}
|
|
232
|
-
healthyMessage = formatQuotaSnapshotForDashboard(snapshot, display);
|
|
237
|
+
healthyMessage = formatQuotaSnapshotForDashboard(snapshot, display) + " | " + subscriptionLine(account, snapshot);
|
|
233
238
|
if (snapshot.primingFailure) {
|
|
234
239
|
healthyTone = "warning";
|
|
235
240
|
warnings += 1;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildQuotaEmailFallbackState, findQuotaCacheEntryForAccount, quotaWorkspaceKey, hasSafeQuotaEmailFallback, hasUniqueQuotaAccountId, normalizeQuotaAccountId, normalizeQuotaEmail, } from "../quota-readiness.js";
|
|
2
|
+
import { mergeQuotaCacheEntry, } from "../quota-cache.js";
|
|
2
3
|
import { DEFAULT_MODEL, DEFAULT_PROBE_MODEL, } from "../request/helpers/model-map.js";
|
|
3
4
|
import { getRateLimitResetTimeForFamily } from "../runtime/account-status.js";
|
|
4
5
|
/**
|
|
@@ -41,7 +42,10 @@ export function getPersistedQuotaViewForAccount(cache, account, accounts, now, e
|
|
|
41
42
|
/** Retain only quota fields from a probe, never its credentials or response body. */
|
|
42
43
|
function quotaEntryFromSnapshot(snapshot) {
|
|
43
44
|
return {
|
|
44
|
-
|
|
45
|
+
...(snapshot.primingCompleted ? { primingCompleted: true } : {}),
|
|
46
|
+
...(snapshot.primingFailure ? { primingFailure: snapshot.primingFailure } : {}),
|
|
47
|
+
...(snapshot.primingCompleted || snapshot.primingFailure ? { primingObservedAt: snapshot.primingObservedAt ?? Date.now() } : {}),
|
|
48
|
+
updatedAt: snapshot.observedAt ?? Date.now(),
|
|
45
49
|
status: snapshot.status,
|
|
46
50
|
model: snapshot.model,
|
|
47
51
|
planType: snapshot.planType,
|
|
@@ -64,14 +68,14 @@ export function updateQuotaCacheForAccount(cache, account, snapshot, accounts, e
|
|
|
64
68
|
const accountId = normalizeQuotaAccountId(account.accountId);
|
|
65
69
|
const hasUniqueAccountId = accountId !== null && hasUniqueQuotaAccountId(accounts, account);
|
|
66
70
|
if (hasUniqueAccountId) {
|
|
67
|
-
cache.byAccountId[accountId] = nextEntry;
|
|
71
|
+
cache.byAccountId[accountId] = mergeQuotaCacheEntry(cache.byAccountId[accountId], nextEntry);
|
|
68
72
|
changed = true;
|
|
69
73
|
}
|
|
70
74
|
const email = normalizeQuotaEmail(account.email);
|
|
71
75
|
if (email &&
|
|
72
76
|
hasSafeQuotaEmailFallback(emailFallbackState, account) &&
|
|
73
77
|
!hasUniqueAccountId) {
|
|
74
|
-
cache.byEmail[email] = nextEntry;
|
|
78
|
+
cache.byEmail[email] = mergeQuotaCacheEntry(cache.byEmail[email], nextEntry);
|
|
75
79
|
changed = true;
|
|
76
80
|
}
|
|
77
81
|
else if (email && cache.byEmail[email]) {
|
|
@@ -86,7 +90,7 @@ export function updateQuotaCacheForWorkspace(cache, account, workspaceId, snapsh
|
|
|
86
90
|
if (!key)
|
|
87
91
|
return;
|
|
88
92
|
cache.byWorkspace ??= {};
|
|
89
|
-
cache.byWorkspace[key] = quotaEntryFromSnapshot(snapshot);
|
|
93
|
+
cache.byWorkspace[key] = mergeQuotaCacheEntry(cache.byWorkspace[key], quotaEntryFromSnapshot(snapshot));
|
|
90
94
|
if (workspaceId === normalizeQuotaAccountId(account.accountId)) {
|
|
91
95
|
updateQuotaCacheForAccount(cache, account, snapshot, accounts);
|
|
92
96
|
}
|
|
@@ -44,7 +44,7 @@ export declare function modelEntitlements(model: RouteModel): {
|
|
|
44
44
|
reasoningLevels: string[];
|
|
45
45
|
accessPrograms: string[];
|
|
46
46
|
probes?: {
|
|
47
|
-
[k: string]: "
|
|
47
|
+
[k: string]: "unsupported" | "verified" | "unverified" | "downgraded";
|
|
48
48
|
} | undefined;
|
|
49
49
|
checkedAt?: number | undefined;
|
|
50
50
|
model: string;
|
|
@@ -4,6 +4,10 @@ export interface QuotaCacheWindow {
|
|
|
4
4
|
resetAtMs?: number;
|
|
5
5
|
}
|
|
6
6
|
export interface QuotaCacheEntry {
|
|
7
|
+
primingCompleted?: boolean;
|
|
8
|
+
/** Completion/failure time, independent of the quota header observation. */
|
|
9
|
+
primingObservedAt?: number;
|
|
10
|
+
primingFailure?: "timed out" | "stream ended early" | "upstream failed" | "response too large" | "network error";
|
|
7
11
|
updatedAt: number;
|
|
8
12
|
status: number;
|
|
9
13
|
model: string;
|
|
@@ -47,6 +51,8 @@ export declare function getQuotaCachePath(): string;
|
|
|
47
51
|
* will be empty if the on-disk file is absent, malformed, or could not be read.
|
|
48
52
|
*/
|
|
49
53
|
export declare function loadQuotaCache(): Promise<QuotaCacheData>;
|
|
54
|
+
/** Merge quota and priming evidence independently; subsequent quota retires old outcomes. */
|
|
55
|
+
export declare function mergeQuotaCacheEntry(latest: QuotaCacheEntry | undefined, update: QuotaCacheEntry): QuotaCacheEntry;
|
|
50
56
|
/**
|
|
51
57
|
* Persist the quota cache to the on-disk JSON file used by the multi-auth runtime.
|
|
52
58
|
*
|
package/dist/lib/quota-cache.js
CHANGED
|
@@ -58,6 +58,9 @@ function normalizeEntry(value) {
|
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
60
|
return {
|
|
61
|
+
...(value.primingCompleted === true ? { primingCompleted: true } : {}),
|
|
62
|
+
...(typeof value.primingFailure === "string" && ["timed out", "stream ended early", "upstream failed", "response too large", "network error"].includes(value.primingFailure) ? { primingFailure: value.primingFailure } : {}),
|
|
63
|
+
...(normalizeNumber(value.primingObservedAt) !== undefined ? { primingObservedAt: normalizeNumber(value.primingObservedAt) } : {}),
|
|
61
64
|
updatedAt,
|
|
62
65
|
status,
|
|
63
66
|
model: model.trim(),
|
|
@@ -158,6 +161,32 @@ async function readQuotaCache() {
|
|
|
158
161
|
...(parsed.byWorkspace ? { byWorkspace: normalizeEntryMap(parsed.byWorkspace) } : {}),
|
|
159
162
|
};
|
|
160
163
|
}
|
|
164
|
+
/** Merge quota and priming evidence independently; subsequent quota retires old outcomes. */
|
|
165
|
+
export function mergeQuotaCacheEntry(latest, update) {
|
|
166
|
+
if (!latest)
|
|
167
|
+
return update;
|
|
168
|
+
const quota = update.updatedAt >= latest.updatedAt ? update : latest;
|
|
169
|
+
const outcomeTime = (entry) => entry.primingCompleted || entry.primingFailure
|
|
170
|
+
? entry.primingObservedAt ?? entry.updatedAt : -Infinity;
|
|
171
|
+
// A timeout does not undo a completion from an overlapping attempt.
|
|
172
|
+
// Only completions at/after the newest quota observation remain relevant.
|
|
173
|
+
const completion = [update, latest].filter(entry => entry.primingCompleted && outcomeTime(entry) >= quota.updatedAt)
|
|
174
|
+
.sort((a, b) => outcomeTime(b) - outcomeTime(a))[0];
|
|
175
|
+
const evidence = completion ?? (outcomeTime(update) >= outcomeTime(latest) ? update : latest);
|
|
176
|
+
const result = { ...quota };
|
|
177
|
+
delete result.primingCompleted;
|
|
178
|
+
delete result.primingFailure;
|
|
179
|
+
delete result.primingObservedAt;
|
|
180
|
+
if (outcomeTime(evidence) >= quota.updatedAt) {
|
|
181
|
+
if (evidence.primingCompleted)
|
|
182
|
+
result.primingCompleted = true;
|
|
183
|
+
else if (evidence.primingFailure)
|
|
184
|
+
result.primingFailure = evidence.primingFailure;
|
|
185
|
+
if (evidence.primingObservedAt !== undefined)
|
|
186
|
+
result.primingObservedAt = evidence.primingObservedAt;
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
161
190
|
/** Reapply this run's changed entries, preserving unrelated or newer concurrent observations. */
|
|
162
191
|
function mergeQuotaChanges(current, proposed, baseline) {
|
|
163
192
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
@@ -168,24 +197,12 @@ function mergeQuotaChanges(current, proposed, baseline) {
|
|
|
168
197
|
continue;
|
|
169
198
|
const latest = current[namespace]?.[key], update = next[key];
|
|
170
199
|
if (update) {
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
current[namespace][key] = update;
|
|
174
|
-
}
|
|
175
|
-
else if (same(latest, before[key])) {
|
|
176
|
-
// The on-disk entry is still exactly the one this caller's
|
|
177
|
-
// baseline saw, so nothing concurrent touched this key:
|
|
178
|
-
// `update` is a deliberate write whose lower stamp can only
|
|
179
|
-
// come from a backward clock jump on this writer. Re-stamp
|
|
180
|
-
// it just ahead instead of silently losing it. A raced key
|
|
181
|
-
// (`!same`) falls through and keeps the on-disk entry: its
|
|
182
|
-
// higher stamp marks a newer observation, and bumping an
|
|
183
|
-
// older one past it would let stale quota data overwrite
|
|
184
|
-
// fresher data.
|
|
200
|
+
if (latest && update.updatedAt < latest.updatedAt && same(latest, before[key])) {
|
|
201
|
+
// Preserve the existing backward-clock handling for an unraced write.
|
|
185
202
|
update.updatedAt = latest.updatedAt + 1;
|
|
186
|
-
current[namespace] ??= {};
|
|
187
|
-
current[namespace][key] = update;
|
|
188
203
|
}
|
|
204
|
+
current[namespace] ??= {};
|
|
205
|
+
current[namespace][key] = mergeQuotaCacheEntry(latest, update);
|
|
189
206
|
}
|
|
190
207
|
else if (same(latest, before[key])) {
|
|
191
208
|
delete current[namespace]?.[key];
|
|
@@ -26,7 +26,10 @@ export interface CodexQuotaWindow {
|
|
|
26
26
|
resetAtMs?: number;
|
|
27
27
|
}
|
|
28
28
|
export interface CodexQuotaSnapshot {
|
|
29
|
+
/** Time quota headers were observed, before consuming the response stream. */
|
|
30
|
+
observedAt?: number;
|
|
29
31
|
primingCompleted?: boolean;
|
|
32
|
+
primingObservedAt?: number;
|
|
30
33
|
primingFailure?: FirstUseProbeError["reason"];
|
|
31
34
|
status: number;
|
|
32
35
|
planType?: string;
|
package/dist/lib/quota-probe.js
CHANGED
|
@@ -382,15 +382,16 @@ export async function fetchCodexQuotaSnapshot(options) {
|
|
|
382
382
|
}
|
|
383
383
|
const snapshotBase = parseQuotaSnapshotBase(response.headers, response.status);
|
|
384
384
|
if (snapshotBase) {
|
|
385
|
-
|
|
385
|
+
const observedAt = Date.now();
|
|
386
|
+
if (options.primeUnusedSubscription && needsSubscriptionFirstUse(snapshotBase, observedAt)) {
|
|
386
387
|
try {
|
|
387
388
|
await finishSubscriptionFirstUse(response, timeoutMs);
|
|
388
|
-
return { ...snapshotBase, model, primingCompleted: true };
|
|
389
|
+
return { ...snapshotBase, observedAt, model, primingObservedAt: Date.now(), primingCompleted: true };
|
|
389
390
|
}
|
|
390
391
|
catch (error) {
|
|
391
392
|
// Keep valid quota data without retrying an accepted inference.
|
|
392
393
|
if (error instanceof FirstUseProbeError)
|
|
393
|
-
return { ...snapshotBase, model, primingFailure: error.reason };
|
|
394
|
+
return { ...snapshotBase, observedAt, model, primingObservedAt: Date.now(), primingFailure: error.reason };
|
|
394
395
|
throw error;
|
|
395
396
|
}
|
|
396
397
|
}
|
|
@@ -400,7 +401,7 @@ export async function fetchCodexQuotaSnapshot(options) {
|
|
|
400
401
|
catch {
|
|
401
402
|
// Best effort cancellation.
|
|
402
403
|
}
|
|
403
|
-
return { ...snapshotBase, model };
|
|
404
|
+
return { ...snapshotBase, observedAt, model };
|
|
404
405
|
}
|
|
405
406
|
if (!response.ok) {
|
|
406
407
|
const bodyText = await response.text().catch(() => "");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { QuotaCacheData, QuotaCacheEntry } from "./quota-cache.js";
|
|
2
2
|
import type { AccountMetadataV3 } from "./storage.js";
|
|
3
|
-
export type QuotaCacheAccountRef = Pick<AccountMetadataV3, "accountId" | "email" | "recordId" | "workspaces" | "currentWorkspaceIndex"> & Partial<Pick<AccountMetadataV3, "refreshToken" | "addedAt">>;
|
|
3
|
+
export type QuotaCacheAccountRef = Pick<AccountMetadataV3, "accountId" | "email" | "recordId" | "workspaces" | "currentWorkspaceIndex"> & Partial<Pick<AccountMetadataV3, "refreshToken" | "addedAt" | "accessToken">>;
|
|
4
4
|
export declare function normalizeQuotaAccountId(value: string | undefined): string | null;
|
|
5
5
|
export declare function normalizeQuotaEmail(value: string | undefined): string | null;
|
|
6
6
|
export declare function hasUniqueQuotaAccountId(accounts: readonly QuotaCacheAccountRef[], account: QuotaCacheAccountRef): boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { extractAccountId } from "./auth/token-utils.js";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { resolveAccountRecordId } from "./storage/record-identity.js";
|
|
3
4
|
export function normalizeQuotaAccountId(value) {
|
|
@@ -101,7 +102,7 @@ export function quotaWorkspaceKey(account, workspaceId) {
|
|
|
101
102
|
export function quotaWorkspaceId(account) {
|
|
102
103
|
return account.workspaces?.length
|
|
103
104
|
? account.workspaces[account.currentWorkspaceIndex ?? 0]?.id.trim()
|
|
104
|
-
: account.accountId?.trim();
|
|
105
|
+
: account.accountId?.trim() || extractAccountId(account.accessToken);
|
|
105
106
|
}
|
|
106
107
|
/** Read exact-workspace quota, using legacy binding entries only for that binding. */
|
|
107
108
|
export function findQuotaCacheEntryForAccount(cache, account, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts), workspaceId = quotaWorkspaceId(account)) {
|
|
@@ -110,7 +111,10 @@ export function findQuotaCacheEntryForAccount(cache, account, accounts, emailFal
|
|
|
110
111
|
const key = workspaceId && quotaWorkspaceKey(account, workspaceId);
|
|
111
112
|
const scoped = key ? cache.byWorkspace?.[key] : undefined;
|
|
112
113
|
// Legacy entries describe only the stored binding, never a sibling workspace.
|
|
113
|
-
|
|
114
|
+
// A workspaces-bearing account whose selection does not resolve (invalid index
|
|
115
|
+
// or blank id) has no valid binding at all — never fall back to legacy keys.
|
|
116
|
+
if (normalizeQuotaAccountId(workspaceId) !== normalizeQuotaAccountId(account.accountId) ||
|
|
117
|
+
(account.workspaces?.length && !normalizeQuotaAccountId(workspaceId)))
|
|
114
118
|
return scoped ?? null;
|
|
115
119
|
const accountId = normalizeQuotaAccountId(account.accountId);
|
|
116
120
|
const newer = (legacy) => scoped && (!legacy || scoped.updatedAt >= legacy.updatedAt) ? scoped : legacy ?? null;
|
|
@@ -53,7 +53,7 @@ export declare class AccountModelCatalog {
|
|
|
53
53
|
reasoningLevels: string[];
|
|
54
54
|
accessPrograms: string[];
|
|
55
55
|
probes?: {
|
|
56
|
-
[k: string]: "
|
|
56
|
+
[k: string]: "unsupported" | "verified" | "unverified" | "downgraded";
|
|
57
57
|
} | undefined;
|
|
58
58
|
checkedAt?: number | undefined;
|
|
59
59
|
model: string;
|
|
@@ -2,7 +2,7 @@ import { createUsageStreamScanner } from "../usage/usage-extraction.js";
|
|
|
2
2
|
import { isRecord } from "../utils.js";
|
|
3
3
|
/** Only personal included subscriptions may receive an automatic first-use probe. */
|
|
4
4
|
export function needsSubscriptionFirstUse(snapshot, now) {
|
|
5
|
-
if (snapshot.status !== 200 || !["plus", "pro", "prolite"].includes(snapshot.planType?.toLowerCase() ?? ""))
|
|
5
|
+
if (snapshot.status !== 200 || !["plus", "pro", "prolite", "promax"].includes(snapshot.planType?.toLowerCase() ?? ""))
|
|
6
6
|
return false;
|
|
7
7
|
const allWindows = [snapshot.primary, snapshot.secondary];
|
|
8
8
|
if (allWindows.some(window => typeof window.usedPercent === "number" && window.usedPercent !== 0))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
4
4
|
"description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
"@codex-ai/plugin": "file:vendor/codex-ai-plugin",
|
|
178
178
|
"@codex-ai/sdk": "file:vendor/codex-ai-sdk",
|
|
179
179
|
"hono": "4.13.9",
|
|
180
|
-
"undici": "6.
|
|
180
|
+
"undici": "6.29.0",
|
|
181
181
|
"ws": "8.21.3",
|
|
182
182
|
"zod": "4.4.3"
|
|
183
183
|
},
|