codex-multi-auth 2.17.2 → 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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +83 -428
- package/dist/index.d.ts +0 -1
- package/dist/lib/account-policy.d.ts +18 -2
- package/dist/lib/account-policy.js +97 -40
- package/dist/lib/accounts/rate-limits.d.ts +0 -1
- package/dist/lib/accounts.d.ts +0 -1
- package/dist/lib/accounts.js +4 -5
- package/dist/lib/api-route-store.d.ts +0 -1
- package/dist/lib/audit.d.ts +0 -1
- package/dist/lib/audit.js +43 -12
- package/dist/lib/auth/account-access.d.ts +0 -1
- package/dist/lib/auth/account-access.js +5 -1
- package/dist/lib/auth/auth.d.ts +4 -3
- package/dist/lib/auth/auth.js +220 -28
- package/dist/lib/auth/browser.d.ts +0 -1
- package/dist/lib/auth/callback-guidance.d.ts +0 -1
- package/dist/lib/auth/device-auth.d.ts +0 -1
- package/dist/lib/auth/index.d.ts +0 -1
- package/dist/lib/auth/org-override.d.ts +0 -1
- package/dist/lib/auth/server.d.ts +1 -2
- package/dist/lib/auth/server.js +100 -53
- package/dist/lib/auth/token-utils.d.ts +0 -1
- package/dist/lib/auth-rate-limit.d.ts +0 -1
- package/dist/lib/budget-guard.d.ts +16 -2
- package/dist/lib/budget-guard.js +123 -43
- package/dist/lib/capability-policy.d.ts +0 -1
- package/dist/lib/circuit-breaker.d.ts +20 -1
- package/dist/lib/circuit-breaker.js +24 -5
- package/dist/lib/cli.d.ts +0 -1
- package/dist/lib/codex-cli/index.d.ts +0 -1
- package/dist/lib/codex-cli/observability.d.ts +0 -1
- package/dist/lib/codex-cli/state.d.ts +0 -1
- package/dist/lib/codex-cli/sync.d.ts +0 -1
- package/dist/lib/codex-cli/writer.d.ts +0 -1
- package/dist/lib/codex-manager/account-credentials.d.ts +0 -1
- package/dist/lib/codex-manager/account-manager-commands.d.ts +0 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts +0 -1
- package/dist/lib/codex-manager/active-account-sync.d.ts +6 -0
- package/dist/lib/codex-manager/active-account-sync.js +336 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts +0 -1
- package/dist/lib/codex-manager/backend-category-entry.d.ts +0 -1
- package/dist/lib/codex-manager/backend-category-helpers.d.ts +0 -1
- package/dist/lib/codex-manager/backend-category-prompt.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-controller.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-entry.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-helpers.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-prompt.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-schema.d.ts +0 -1
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts +0 -1
- package/dist/lib/codex-manager/commands/account.d.ts +8 -3
- package/dist/lib/codex-manager/commands/account.js +46 -34
- package/dist/lib/codex-manager/commands/best.d.ts +0 -1
- package/dist/lib/codex-manager/commands/bridge.d.ts +0 -1
- package/dist/lib/codex-manager/commands/budget.d.ts +8 -3
- package/dist/lib/codex-manager/commands/budget.js +6 -4
- package/dist/lib/codex-manager/commands/check.d.ts +0 -1
- package/dist/lib/codex-manager/commands/config-explain.d.ts +0 -1
- package/dist/lib/codex-manager/commands/debug-bundle.d.ts +0 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts +0 -1
- package/dist/lib/codex-manager/commands/history.d.ts +0 -1
- package/dist/lib/codex-manager/commands/init-config.d.ts +0 -1
- package/dist/lib/codex-manager/commands/integrations.d.ts +0 -1
- package/dist/lib/codex-manager/commands/limits.d.ts +0 -1
- package/dist/lib/codex-manager/commands/models.d.ts +0 -1
- package/dist/lib/codex-manager/commands/monitor.d.ts +0 -1
- package/dist/lib/codex-manager/commands/report.d.ts +0 -1
- package/dist/lib/codex-manager/commands/resets.d.ts +0 -1
- package/dist/lib/codex-manager/commands/resets.js +9 -1
- package/dist/lib/codex-manager/commands/rotation.d.ts +0 -1
- package/dist/lib/codex-manager/commands/status.d.ts +0 -1
- package/dist/lib/codex-manager/commands/switch.d.ts +0 -1
- package/dist/lib/codex-manager/commands/uninstall.d.ts +0 -1
- package/dist/lib/codex-manager/commands/unpin.d.ts +0 -1
- package/dist/lib/codex-manager/commands/usage.d.ts +0 -1
- package/dist/lib/codex-manager/commands/verify.d.ts +0 -1
- package/dist/lib/codex-manager/commands/why-selected.d.ts +0 -1
- package/dist/lib/codex-manager/commands/workspace.d.ts +0 -1
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts +0 -1
- package/dist/lib/codex-manager/dashboard-formatters.d.ts +0 -1
- package/dist/lib/codex-manager/dashboard-settings-controller.d.ts +0 -1
- package/dist/lib/codex-manager/dashboard-settings-data.d.ts +0 -1
- package/dist/lib/codex-manager/dashboard-settings-entry.d.ts +0 -1
- package/dist/lib/codex-manager/experimental-settings-entry.d.ts +0 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +0 -1
- package/dist/lib/codex-manager/experimental-settings-schema.d.ts +0 -1
- package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts +0 -1
- package/dist/lib/codex-manager/experimental-sync-target.d.ts +0 -1
- package/dist/lib/codex-manager/forecast-report-shared.d.ts +0 -1
- package/dist/lib/codex-manager/formatters/account-formatters.d.ts +0 -1
- package/dist/lib/codex-manager/formatters/index.d.ts +0 -1
- package/dist/lib/codex-manager/formatters/model-formatters.d.ts +0 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts +0 -1
- package/dist/lib/codex-manager/formatters/text-style.d.ts +0 -1
- package/dist/lib/codex-manager/health-check.d.ts +0 -1
- package/dist/lib/codex-manager/help.d.ts +0 -1
- package/dist/lib/codex-manager/login-action-panel.d.ts +0 -1
- package/dist/lib/codex-manager/login-flow.d.ts +0 -1
- package/dist/lib/codex-manager/login-menu-actions.d.ts +0 -1
- package/dist/lib/codex-manager/login-menu-data.d.ts +0 -1
- package/dist/lib/codex-manager/login-oauth.d.ts +0 -1
- package/dist/lib/codex-manager/login-workspace-choice.d.ts +0 -1
- package/dist/lib/codex-manager/manual-callback.d.ts +0 -1
- package/dist/lib/codex-manager/persist-selected-account.d.ts +0 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts +0 -1
- package/dist/lib/codex-manager/rate-limit-markers.d.ts +0 -1
- package/dist/lib/codex-manager/repair-commands.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub/backend.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub/experimental.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub/index.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub/shared.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub-entry.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub-menu.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub-prompt.d.ts +0 -1
- package/dist/lib/codex-manager/settings-hub.d.ts +0 -1
- package/dist/lib/codex-manager/settings-panels.d.ts +0 -1
- package/dist/lib/codex-manager/settings-persist-utils.d.ts +0 -1
- package/dist/lib/codex-manager/settings-preview.d.ts +0 -1
- package/dist/lib/codex-manager/settings-write-queue.d.ts +0 -1
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts +0 -1
- package/dist/lib/codex-manager/theme-settings-panel.d.ts +0 -1
- package/dist/lib/codex-manager/unified-settings-controller.d.ts +0 -1
- package/dist/lib/codex-manager/unified-settings-entry.d.ts +0 -1
- package/dist/lib/codex-manager.d.ts +1 -2
- package/dist/lib/codex-manager.js +5 -95
- package/dist/lib/concurrency.d.ts +0 -1
- package/dist/lib/config-schema.d.ts +0 -1
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/config.js +46 -241
- package/dist/lib/constants.d.ts +0 -1
- package/dist/lib/context-budget/model-context-windows.d.ts +0 -1
- package/dist/lib/context-budget-guard.d.ts +0 -1
- package/dist/lib/context-budget-response.d.ts +0 -1
- package/dist/lib/context-overflow.d.ts +0 -1
- package/dist/lib/dashboard-settings.d.ts +0 -1
- package/dist/lib/entitlement-cache.d.ts +0 -1
- package/dist/lib/env-parsing.d.ts +13 -1
- package/dist/lib/env-parsing.js +21 -0
- package/dist/lib/errors.d.ts +0 -1
- package/dist/lib/forecast.d.ts +0 -1
- package/dist/lib/fs-retry.d.ts +0 -1
- package/dist/lib/health.d.ts +0 -1
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/integration-generators.d.ts +0 -1
- package/dist/lib/live-account-sync.d.ts +0 -1
- package/dist/lib/local-bridge.d.ts +0 -1
- package/dist/lib/local-bridge.js +4 -1
- package/dist/lib/local-client-tokens.d.ts +0 -1
- package/dist/lib/local-client-tokens.js +125 -30
- package/dist/lib/logger.d.ts +0 -1
- package/dist/lib/logger.js +11 -1
- package/dist/lib/model-capability-matrix.d.ts +0 -1
- package/dist/lib/model-route-policy.d.ts +1 -2
- package/dist/lib/named-backup-export.d.ts +0 -1
- package/dist/lib/oc-chatgpt-import-adapter.d.ts +0 -1
- package/dist/lib/oc-chatgpt-orchestrator.d.ts +0 -1
- package/dist/lib/oc-chatgpt-target-detection.d.ts +0 -1
- package/dist/lib/parallel-probe.d.ts +0 -1
- package/dist/lib/policy/runtime-policy-cache.d.ts +80 -0
- package/dist/lib/policy/runtime-policy-cache.js +310 -0
- package/dist/lib/policy/runtime-policy.d.ts +1 -2
- package/dist/lib/policy/runtime-policy.js +46 -19
- package/dist/lib/preemptive-quota-scheduler.d.ts +0 -1
- package/dist/lib/proactive-refresh.d.ts +0 -1
- package/dist/lib/prompts/codex-host-bridge.d.ts +0 -1
- package/dist/lib/prompts/codex.d.ts +0 -1
- package/dist/lib/prompts/fetch-utils.d.ts +0 -1
- package/dist/lib/prompts/host-codex-prompt.d.ts +0 -1
- package/dist/lib/quota-cache.d.ts +0 -1
- package/dist/lib/quota-cache.js +60 -36
- package/dist/lib/quota-probe.d.ts +0 -1
- package/dist/lib/quota-probe.js +5 -2
- package/dist/lib/quota-readiness.d.ts +0 -1
- package/dist/lib/recovery/constants.d.ts +0 -1
- package/dist/lib/recovery/storage.d.ts +0 -1
- package/dist/lib/recovery/types.d.ts +0 -1
- package/dist/lib/recovery.d.ts +0 -1
- package/dist/lib/redaction.d.ts +0 -1
- package/dist/lib/refresh-guardian.d.ts +0 -1
- package/dist/lib/refresh-lease.d.ts +0 -1
- package/dist/lib/refresh-queue.d.ts +0 -1
- package/dist/lib/request/client-cancellation.d.ts +0 -1
- package/dist/lib/request/error-classification.d.ts +0 -1
- package/dist/lib/request/failover-config.d.ts +0 -1
- package/dist/lib/request/failure-policy.d.ts +0 -1
- package/dist/lib/request/fetch-helpers.d.ts +0 -1
- package/dist/lib/request/headers.d.ts +0 -1
- package/dist/lib/request/helpers/input-utils.d.ts +0 -1
- package/dist/lib/request/helpers/input-utils.js +88 -34
- package/dist/lib/request/helpers/model-map.d.ts +0 -1
- package/dist/lib/request/helpers/tool-utils.d.ts +0 -1
- package/dist/lib/request/helpers/tool-utils.js +421 -4
- package/dist/lib/request/index.d.ts +0 -1
- package/dist/lib/request/rate-limit-backoff.d.ts +0 -1
- package/dist/lib/request/rate-limit-decision.d.ts +0 -1
- package/dist/lib/request/request-attempt-budget.d.ts +0 -1
- package/dist/lib/request/request-init.d.ts +0 -1
- package/dist/lib/request/request-resilience.d.ts +0 -1
- package/dist/lib/request/request-transformer.d.ts +0 -1
- package/dist/lib/request/request-transformer.js +50 -25
- package/dist/lib/request/response-compaction.d.ts +0 -1
- package/dist/lib/request/response-handler.d.ts +0 -1
- package/dist/lib/request/response-metadata.d.ts +0 -1
- package/dist/lib/request/response-outcome.d.ts +0 -1
- package/dist/lib/request/stream-failover-runtime.d.ts +0 -1
- package/dist/lib/request/stream-failover.d.ts +0 -1
- package/dist/lib/request/stream-failover.js +28 -4
- package/dist/lib/request/token-refresh.d.ts +0 -1
- package/dist/lib/request/url-rewriting.d.ts +0 -1
- package/dist/lib/request/wait-utils.d.ts +0 -1
- package/dist/lib/rotation.d.ts +0 -1
- package/dist/lib/routing-mutex.d.ts +0 -1
- package/dist/lib/routing-profiles.d.ts +16 -2
- package/dist/lib/routing-profiles.js +119 -44
- package/dist/lib/runtime/account-check-helpers.d.ts +0 -1
- package/dist/lib/runtime/account-check-types.d.ts +0 -1
- package/dist/lib/runtime/account-check.d.ts +0 -1
- package/dist/lib/runtime/account-manager-cache-entry.d.ts +0 -1
- package/dist/lib/runtime/account-manager-cache.d.ts +0 -1
- package/dist/lib/runtime/account-model-catalog.d.ts +1 -2
- package/dist/lib/runtime/account-pool.d.ts +0 -1
- package/dist/lib/runtime/account-reset-credits.d.ts +0 -1
- package/dist/lib/runtime/account-reset-credits.js +8 -2
- package/dist/lib/runtime/account-scope.d.ts +0 -1
- package/dist/lib/runtime/account-select-event.d.ts +0 -1
- package/dist/lib/runtime/account-selection.d.ts +0 -1
- package/dist/lib/runtime/account-state.d.ts +0 -1
- package/dist/lib/runtime/account-status.d.ts +0 -1
- package/dist/lib/runtime/account-storage-scope-entry.d.ts +0 -1
- package/dist/lib/runtime/api-model-capabilities.d.ts +0 -1
- package/dist/lib/runtime/api-model-runtime.d.ts +0 -1
- package/dist/lib/runtime/app-bind.d.ts +0 -1
- package/dist/lib/runtime/app-helper-selection.d.ts +0 -1
- package/dist/lib/runtime/auth-facade.d.ts +0 -1
- package/dist/lib/runtime/automatic-account-checks.d.ts +0 -1
- package/dist/lib/runtime/automatic-subscription-checks.d.ts +0 -1
- package/dist/lib/runtime/browser-oauth-flow.d.ts +0 -1
- package/dist/lib/runtime/capability-boost.d.ts +0 -1
- package/dist/lib/runtime/catalog-capabilities.d.ts +0 -1
- package/dist/lib/runtime/config-toml.d.ts +0 -1
- package/dist/lib/runtime/context-budget-settings.d.ts +0 -1
- package/dist/lib/runtime/event-handler.d.ts +0 -1
- package/dist/lib/runtime/first-run.d.ts +0 -1
- package/dist/lib/runtime/flagged-verify-types.d.ts +0 -1
- package/dist/lib/runtime/hydrate-emails.d.ts +0 -1
- package/dist/lib/runtime/inference-activity.d.ts +0 -1
- package/dist/lib/runtime/live-sync-entry.d.ts +0 -1
- package/dist/lib/runtime/live-sync.d.ts +0 -1
- package/dist/lib/runtime/loader-setup.d.ts +0 -1
- package/dist/lib/runtime/login-menu-accounts.d.ts +0 -1
- package/dist/lib/runtime/manual-oauth-flow.d.ts +0 -1
- package/dist/lib/runtime/model-discovery-status.d.ts +2 -3
- package/dist/lib/runtime/native-account-storage.d.ts +0 -1
- package/dist/lib/runtime/native-account-sync.d.ts +0 -1
- package/dist/lib/runtime/native-binding-lock.d.ts +0 -1
- package/dist/lib/runtime/native-client-auth.d.ts +0 -1
- package/dist/lib/runtime/native-provider-config.d.ts +0 -1
- package/dist/lib/runtime/native-rate-limits.d.ts +2 -1
- package/dist/lib/runtime/native-rate-limits.js +23 -6
- package/dist/lib/runtime/preemptive-quota.d.ts +0 -1
- package/dist/lib/runtime/quota-headers.d.ts +0 -1
- package/dist/lib/runtime/quota-probe.d.ts +0 -1
- package/dist/lib/runtime/quota-settings.d.ts +0 -1
- package/dist/lib/runtime/refresh-guardian-entry.d.ts +0 -1
- package/dist/lib/runtime/refresh-guardian.d.ts +0 -1
- package/dist/lib/runtime/request-init.d.ts +0 -1
- package/dist/lib/runtime/reset-credit-routing.d.ts +0 -1
- package/dist/lib/runtime/reset-credits.d.ts +0 -1
- package/dist/lib/runtime/response-output-history.d.ts +0 -1
- package/dist/lib/runtime/responses-websocket.d.ts +0 -1
- package/dist/lib/runtime/resume-picker.d.ts +0 -1
- package/dist/lib/runtime/rotation-account-selection.d.ts +0 -1
- package/dist/lib/runtime/rotation-proxy-state.d.ts +0 -1
- package/dist/lib/runtime/rotation-server-types.d.ts +0 -1
- package/dist/lib/runtime/rotation-storage-meta.d.ts +0 -1
- package/dist/lib/runtime/rotation-token-refresh.d.ts +0 -1
- package/dist/lib/runtime/runtime-capability-failures.d.ts +0 -1
- package/dist/lib/runtime/runtime-current-account.d.ts +0 -1
- package/dist/lib/runtime/runtime-observability.d.ts +0 -1
- package/dist/lib/runtime/runtime-services.d.ts +0 -1
- package/dist/lib/runtime/session-affinity-entry.d.ts +0 -1
- package/dist/lib/runtime/session-recovery.d.ts +0 -1
- package/dist/lib/runtime/status-marker.d.ts +0 -1
- package/dist/lib/runtime/storage-scope.d.ts +0 -1
- package/dist/lib/runtime/subscription-first-use.d.ts +0 -1
- package/dist/lib/runtime/subscription-quota-event.d.ts +0 -1
- package/dist/lib/runtime/subscription-quota-order.d.ts +0 -1
- package/dist/lib/runtime/toast.d.ts +0 -1
- package/dist/lib/runtime/ui-runtime-entry.d.ts +0 -1
- package/dist/lib/runtime/ui-runtime.d.ts +0 -1
- package/dist/lib/runtime/verify-flagged.d.ts +0 -1
- package/dist/lib/runtime/workspace-model-scopes.d.ts +0 -1
- package/dist/lib/runtime-constants.d.ts +0 -1
- package/dist/lib/runtime-paths.d.ts +0 -1
- package/dist/lib/runtime-rotation-proxy.d.ts +1 -1
- package/dist/lib/runtime-rotation-proxy.js +133 -0
- package/dist/lib/schemas.d.ts +35 -13
- package/dist/lib/schemas.js +19 -2
- package/dist/lib/session-affinity.d.ts +0 -1
- package/dist/lib/shutdown.d.ts +0 -1
- package/dist/lib/storage/account-clear-entry.d.ts +0 -1
- package/dist/lib/storage/account-clear.d.ts +0 -1
- package/dist/lib/storage/account-match-utils.d.ts +0 -1
- package/dist/lib/storage/account-persistence.d.ts +0 -1
- package/dist/lib/storage/account-port.d.ts +0 -1
- package/dist/lib/storage/account-save-entry.d.ts +0 -1
- package/dist/lib/storage/account-save.d.ts +9 -2
- package/dist/lib/storage/account-save.js +4 -1
- package/dist/lib/storage/account-snapshot.d.ts +0 -1
- package/dist/lib/storage/backup-metadata-builder.d.ts +0 -1
- package/dist/lib/storage/backup-metadata.d.ts +0 -1
- package/dist/lib/storage/backup-paths.d.ts +0 -1
- package/dist/lib/storage/backup-restore.d.ts +0 -1
- package/dist/lib/storage/cache-artifacts.d.ts +0 -1
- package/dist/lib/storage/credential-sidecars.d.ts +0 -1
- package/dist/lib/storage/error-hints.d.ts +0 -1
- package/dist/lib/storage/file-lock.d.ts +0 -1
- package/dist/lib/storage/file-lock.js +33 -1
- package/dist/lib/storage/file-paths.d.ts +0 -1
- package/dist/lib/storage/fixture-guards.d.ts +0 -1
- package/dist/lib/storage/flagged-entry.d.ts +0 -1
- package/dist/lib/storage/flagged-load-entry.d.ts +0 -1
- package/dist/lib/storage/flagged-save-entry.d.ts +0 -1
- package/dist/lib/storage/flagged-storage-file.d.ts +0 -1
- package/dist/lib/storage/flagged-storage-io.d.ts +0 -1
- package/dist/lib/storage/flagged-storage.d.ts +0 -1
- package/dist/lib/storage/gitignore.d.ts +0 -1
- package/dist/lib/storage/hash.d.ts +0 -1
- package/dist/lib/storage/health.d.ts +0 -1
- package/dist/lib/storage/identity.d.ts +0 -1
- package/dist/lib/storage/import-export.d.ts +0 -1
- package/dist/lib/storage/json-store-lock.d.ts +105 -0
- package/dist/lib/storage/json-store-lock.js +259 -0
- package/dist/lib/storage/metadata-section.d.ts +0 -1
- package/dist/lib/storage/migrations.d.ts +0 -1
- package/dist/lib/storage/migrations.js +31 -18
- package/dist/lib/storage/named-backup-entry.d.ts +0 -1
- package/dist/lib/storage/named-backups-entry.d.ts +0 -1
- package/dist/lib/storage/named-backups.d.ts +0 -1
- package/dist/lib/storage/path-state.d.ts +0 -1
- package/dist/lib/storage/paths.d.ts +0 -1
- package/dist/lib/storage/pending-auth.d.ts +9 -3
- package/dist/lib/storage/pending-auth.js +30 -8
- package/dist/lib/storage/project-migration.d.ts +0 -1
- package/dist/lib/storage/public-types.d.ts +0 -1
- package/dist/lib/storage/record-identity.d.ts +0 -1
- package/dist/lib/storage/record-utils.d.ts +0 -1
- package/dist/lib/storage/restore-assessment.d.ts +0 -1
- package/dist/lib/storage/restore-backup-entry.d.ts +0 -1
- package/dist/lib/storage/restore-metadata.d.ts +0 -1
- package/dist/lib/storage/save-retry.d.ts +0 -1
- package/dist/lib/storage/snapshot-inspectors.d.ts +0 -1
- package/dist/lib/storage/snapshot-merge.d.ts +0 -1
- package/dist/lib/storage/storage-parser.d.ts +2 -1
- package/dist/lib/storage/storage-parser.js +10 -2
- package/dist/lib/storage/transactions.d.ts +0 -1
- package/dist/lib/storage.d.ts +15 -2
- package/dist/lib/storage.js +612 -25
- package/dist/lib/synthetic-response.d.ts +0 -1
- package/dist/lib/table-formatter.d.ts +0 -1
- package/dist/lib/temp-path.d.ts +0 -1
- package/dist/lib/tools/hashline-tools.d.ts +0 -1
- package/dist/lib/types.d.ts +0 -1
- package/dist/lib/ui/ansi.d.ts +0 -1
- package/dist/lib/ui/auth-menu-builder.d.ts +0 -1
- package/dist/lib/ui/auth-menu.d.ts +0 -1
- package/dist/lib/ui/check-progress.d.ts +0 -1
- package/dist/lib/ui/confirm.d.ts +0 -1
- package/dist/lib/ui/display-width.d.ts +0 -1
- package/dist/lib/ui/format.d.ts +0 -1
- package/dist/lib/ui/index.d.ts +0 -1
- package/dist/lib/ui/runtime.d.ts +0 -1
- package/dist/lib/ui/select.d.ts +0 -1
- package/dist/lib/ui/theme.d.ts +0 -1
- package/dist/lib/ui/ui-copy.d.ts +0 -1
- package/dist/lib/unified-settings.d.ts +13 -11
- package/dist/lib/unified-settings.js +22 -14
- package/dist/lib/update-notice.d.ts +0 -1
- package/dist/lib/usage/index.d.ts +0 -1
- package/dist/lib/usage/ledger.d.ts +0 -1
- package/dist/lib/usage/pricing.d.ts +0 -1
- package/dist/lib/usage/redaction.d.ts +0 -1
- package/dist/lib/usage/stream-usage-deferral.d.ts +0 -1
- package/dist/lib/usage/types.d.ts +0 -1
- package/dist/lib/usage/usage-extraction.d.ts +0 -1
- package/dist/lib/utils.d.ts +21 -1
- package/dist/lib/utils.js +31 -0
- package/dist/lib/wsl.d.ts +0 -1
- package/package.json +11 -5
- package/scripts/codex-bin-resolver.js +20 -1
- package/scripts/codex-multi-auth.js +7 -1
- package/scripts/codex.js +288 -7
- package/skills/codex-auth-setup/SKILL.md +73 -0
|
@@ -36,4 +36,3 @@ export type CallbackFailureContext = {
|
|
|
36
36
|
* @returns Guidance lines. Empty strings are intentional blank separators.
|
|
37
37
|
*/
|
|
38
38
|
export declare function describeCallbackFailure(reason: CallbackFailureReason, context?: CallbackFailureContext): string[];
|
|
39
|
-
//# sourceMappingURL=callback-guidance.d.ts.map
|
|
@@ -39,4 +39,3 @@ export declare function requestDeviceAuthorization(options?: DeviceAuthFlowOptio
|
|
|
39
39
|
export declare function pollDeviceAuthorization(deviceCode: DeviceAuthCode, options?: DeviceAuthFlowOptions): Promise<DeviceAuthCompletionResult>;
|
|
40
40
|
export declare function runDeviceAuthFlow(options?: DeviceAuthFlowOptions): Promise<TokenResult>;
|
|
41
41
|
export {};
|
|
42
|
-
//# sourceMappingURL=device-auth.d.ts.map
|
package/dist/lib/auth/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { OAuthServerInfo } from "../types.js";
|
|
|
6
6
|
* and retains a single authorization code on the server instance until consumed via `waitForCode`.
|
|
7
7
|
* Only one code is stored at a time; call `close` to abort polling and shut down the server.
|
|
8
8
|
*
|
|
9
|
-
* On platforms such as Windows, binding
|
|
9
|
+
* On platforms such as Windows, binding the callback port may fail if another process holds it
|
|
10
10
|
* or if firewall/antivirus restrictions prevent local binding; in that case the returned `ready`
|
|
11
11
|
* flag is `false` to allow a manual paste fallback.
|
|
12
12
|
*
|
|
@@ -21,4 +21,3 @@ import type { OAuthServerInfo } from "../types.js";
|
|
|
21
21
|
export declare function startLocalOAuthServer({ state, }: {
|
|
22
22
|
state: string;
|
|
23
23
|
}): Promise<OAuthServerInfo>;
|
|
24
|
-
//# sourceMappingURL=server.d.ts.map
|
package/dist/lib/auth/server.js
CHANGED
|
@@ -7,6 +7,22 @@ import { AUTH_REDIRECT } from "./auth.js";
|
|
|
7
7
|
// Resolve path to oauth-success.html (one level up from auth/ subfolder)
|
|
8
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const successHtml = fs.readFileSync(path.join(__dirname, "..", "oauth-success.html"), "utf-8");
|
|
10
|
+
/**
|
|
11
|
+
* Host the callback listener actually binds.
|
|
12
|
+
*
|
|
13
|
+
* The registered redirect URI keeps its registered host name
|
|
14
|
+
* (`http://localhost:1455/auth/callback`), but the LISTEN side pins a numeric
|
|
15
|
+
* IPv4 loopback: Node resolves a listen host through DNS, and on a dual-stack
|
|
16
|
+
* host "localhost" may resolve to ::1 first (leaving 127.0.0.1 clients unable
|
|
17
|
+
* to reach the callback) or — with a hostile hosts-file entry — somewhere
|
|
18
|
+
* off-box entirely. We therefore bind BOTH numeric loopbacks: whichever family
|
|
19
|
+
* a resolver picks lands on this listener, and a holder of the other family's
|
|
20
|
+
* same port still surfaces as EADDRINUSE instead of silently receiving the
|
|
21
|
+
* callback code.
|
|
22
|
+
*/
|
|
23
|
+
const OAUTH_BIND_HOSTS = AUTH_REDIRECT.host === "localhost"
|
|
24
|
+
? ["::1", "127.0.0.1"]
|
|
25
|
+
: [AUTH_REDIRECT.host];
|
|
10
26
|
/**
|
|
11
27
|
* Start a local HTTP server that captures an OAuth authorization code sent to /auth/callback.
|
|
12
28
|
*
|
|
@@ -14,7 +30,7 @@ const successHtml = fs.readFileSync(path.join(__dirname, "..", "oauth-success.ht
|
|
|
14
30
|
* and retains a single authorization code on the server instance until consumed via `waitForCode`.
|
|
15
31
|
* Only one code is stored at a time; call `close` to abort polling and shut down the server.
|
|
16
32
|
*
|
|
17
|
-
* On platforms such as Windows, binding
|
|
33
|
+
* On platforms such as Windows, binding the callback port may fail if another process holds it
|
|
18
34
|
* or if firewall/antivirus restrictions prevent local binding; in that case the returned `ready`
|
|
19
35
|
* flag is `false` to allow a manual paste fallback.
|
|
20
36
|
*
|
|
@@ -26,7 +42,7 @@ const successHtml = fs.readFileSync(path.join(__dirname, "..", "oauth-success.ht
|
|
|
26
42
|
* function to abort polling and close the server, and `waitForCode` which returns
|
|
27
43
|
* `{ code: string }` when a code becomes available or `null` on timeout/abort.
|
|
28
44
|
*/
|
|
29
|
-
export function startLocalOAuthServer({ state, }) {
|
|
45
|
+
export async function startLocalOAuthServer({ state, }) {
|
|
30
46
|
let pollAborted = false;
|
|
31
47
|
// Capture the authorization code/state in per-call closure variables rather
|
|
32
48
|
// than mutating the shared http.Server instance. Two logins in the same
|
|
@@ -35,7 +51,7 @@ export function startLocalOAuthServer({ state, }) {
|
|
|
35
51
|
// independent.
|
|
36
52
|
let capturedCode;
|
|
37
53
|
let capturedState;
|
|
38
|
-
const
|
|
54
|
+
const requestHandler = (req, res) => {
|
|
39
55
|
try {
|
|
40
56
|
const url = new URL(req.url || "", AUTH_REDIRECT.origin);
|
|
41
57
|
if (url.pathname !== AUTH_REDIRECT.path) {
|
|
@@ -72,58 +88,89 @@ export function startLocalOAuthServer({ state, }) {
|
|
|
72
88
|
res.statusCode = 500;
|
|
73
89
|
res.end("Internal error");
|
|
74
90
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ready: true,
|
|
83
|
-
close: () => {
|
|
84
|
-
pollAborted = true;
|
|
85
|
-
server.close();
|
|
86
|
-
},
|
|
87
|
-
waitForCode: async (expectedState) => {
|
|
88
|
-
const POLL_INTERVAL_MS = 100;
|
|
89
|
-
const TIMEOUT_MS = 5 * 60 * 1000;
|
|
90
|
-
const maxIterations = Math.floor(TIMEOUT_MS / POLL_INTERVAL_MS);
|
|
91
|
-
const poll = () => new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
92
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
93
|
-
if (pollAborted)
|
|
94
|
-
return null;
|
|
95
|
-
const lastCode = capturedCode;
|
|
96
|
-
if (lastCode) {
|
|
97
|
-
if (capturedState !== expectedState) {
|
|
98
|
-
logWarn("Discarding OAuth callback due to state mismatch in waitForCode");
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
return { code: lastCode };
|
|
102
|
-
}
|
|
103
|
-
await poll();
|
|
104
|
-
}
|
|
105
|
-
logWarn("OAuth poll timeout after 5 minutes");
|
|
106
|
-
return null;
|
|
107
|
-
},
|
|
91
|
+
};
|
|
92
|
+
const attempts = OAUTH_BIND_HOSTS.map((host) => {
|
|
93
|
+
const candidate = http.createServer(requestHandler);
|
|
94
|
+
candidate.unref();
|
|
95
|
+
const bound = new Promise((settle) => {
|
|
96
|
+
candidate.on("error", (err) => {
|
|
97
|
+
settle({ server: candidate, ok: false, code: err?.code });
|
|
108
98
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
logError(`Failed to bind ${AUTH_REDIRECT.origin} (${err?.code}). Falling back to manual paste.`);
|
|
112
|
-
resolve({
|
|
113
|
-
port: AUTH_REDIRECT.port,
|
|
114
|
-
ready: false,
|
|
115
|
-
bindErrorCode: err?.code,
|
|
116
|
-
close: () => {
|
|
117
|
-
pollAborted = true;
|
|
118
|
-
try {
|
|
119
|
-
server.close();
|
|
120
|
-
}
|
|
121
|
-
catch (closeErr) {
|
|
122
|
-
logError(`Failed to close OAuth server: ${closeErr?.message ?? String(closeErr)}`);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
waitForCode: (_expectedState) => Promise.resolve(null),
|
|
99
|
+
candidate.listen(AUTH_REDIRECT.port, host, () => {
|
|
100
|
+
settle({ server: candidate, ok: true });
|
|
126
101
|
});
|
|
127
102
|
});
|
|
103
|
+
return { candidate, bound };
|
|
128
104
|
});
|
|
105
|
+
const servers = attempts.map((attempt) => attempt.candidate);
|
|
106
|
+
const closeAll = () => {
|
|
107
|
+
for (const candidate of servers) {
|
|
108
|
+
try {
|
|
109
|
+
candidate.close();
|
|
110
|
+
}
|
|
111
|
+
catch (closeErr) {
|
|
112
|
+
logError(`Failed to close OAuth server: ${closeErr?.message ?? String(closeErr)}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const waitForCode = async (expectedState) => {
|
|
117
|
+
const POLL_INTERVAL_MS = 100;
|
|
118
|
+
const TIMEOUT_MS = 5 * 60 * 1000;
|
|
119
|
+
const maxIterations = Math.floor(TIMEOUT_MS / POLL_INTERVAL_MS);
|
|
120
|
+
const poll = () => new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
121
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
122
|
+
if (pollAborted)
|
|
123
|
+
return null;
|
|
124
|
+
const lastCode = capturedCode;
|
|
125
|
+
if (lastCode) {
|
|
126
|
+
if (capturedState !== expectedState) {
|
|
127
|
+
logWarn("Discarding OAuth callback due to state mismatch in waitForCode");
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return { code: lastCode };
|
|
131
|
+
}
|
|
132
|
+
await poll();
|
|
133
|
+
}
|
|
134
|
+
logWarn("OAuth poll timeout after 5 minutes");
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
const outcomes = await Promise.all(attempts.map((attempt) => attempt.bound));
|
|
138
|
+
const inUse = outcomes.find((outcome) => outcome.code === "EADDRINUSE");
|
|
139
|
+
const bound = outcomes
|
|
140
|
+
.filter((outcome) => outcome.ok)
|
|
141
|
+
.map((outcome) => outcome.server);
|
|
142
|
+
if (inUse || bound.length === 0) {
|
|
143
|
+
// A holder on ANY loopback family conflicts with the registered callback
|
|
144
|
+
// URI — surface it instead of degrading to whichever family was free.
|
|
145
|
+
// When nothing bound, report the first error observed.
|
|
146
|
+
const code = inUse?.code ?? outcomes.find((outcome) => !outcome.ok)?.code;
|
|
147
|
+
logError(`Failed to bind ${AUTH_REDIRECT.origin} (${code}). Falling back to manual paste.`);
|
|
148
|
+
for (const candidate of bound) {
|
|
149
|
+
try {
|
|
150
|
+
candidate.close();
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Best effort — the port was never ours to keep anyway.
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
port: AUTH_REDIRECT.port,
|
|
158
|
+
ready: false,
|
|
159
|
+
bindErrorCode: code,
|
|
160
|
+
close: () => {
|
|
161
|
+
pollAborted = true;
|
|
162
|
+
closeAll();
|
|
163
|
+
},
|
|
164
|
+
waitForCode: (_expectedState) => Promise.resolve(null),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
port: AUTH_REDIRECT.port,
|
|
169
|
+
ready: true,
|
|
170
|
+
close: () => {
|
|
171
|
+
pollAborted = true;
|
|
172
|
+
closeAll();
|
|
173
|
+
},
|
|
174
|
+
waitForCode,
|
|
175
|
+
};
|
|
129
176
|
}
|
|
@@ -32,9 +32,23 @@ export interface BudgetGuardEvaluation {
|
|
|
32
32
|
export declare function getBudgetGuardPath(): string;
|
|
33
33
|
export declare function normalizeBudgetKey(value: string): string | null;
|
|
34
34
|
export declare function loadBudgetGuardStore(): Promise<BudgetGuardStore>;
|
|
35
|
-
export declare function saveBudgetGuardStore(store: BudgetGuardStore): Promise<void>;
|
|
35
|
+
export declare function saveBudgetGuardStore(store: BudgetGuardStore, baseline?: BudgetGuardStore): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Run a budget-guard read→mutate→write inside the write queue (in-process
|
|
38
|
+
* serialization) AND the cross-process lock directory, with mtime CAS retry:
|
|
39
|
+
* every attempt re-reads the freshest on-disk store and re-applies `mutate`
|
|
40
|
+
* before writing — so a mutation is applied to the latest committed state
|
|
41
|
+
* rather than merged by whole-record `updatedAt`, which can drop or clobber
|
|
42
|
+
* a concurrent process's change to the same key. `mutate` must be
|
|
43
|
+
* re-appliable across retries (apply precomputed work onto the store it is
|
|
44
|
+
* handed, don't capture mutated state). Prefer this over load→upsert→save
|
|
45
|
+
* whenever the caller is mutating rather than importing a foreign store.
|
|
46
|
+
*/
|
|
47
|
+
export declare function updateBudgetGuardStore<T>(mutate: (store: BudgetGuardStore) => {
|
|
48
|
+
result: T;
|
|
49
|
+
dirty: boolean;
|
|
50
|
+
}): Promise<T>;
|
|
36
51
|
export declare function upsertBudgetLimit(store: BudgetGuardStore, limit: Omit<BudgetLimit, "updatedAt">, now?: number): BudgetLimit;
|
|
37
52
|
export declare function getBudgetWindowStart(window: BudgetWindow, now?: number): number;
|
|
38
53
|
export declare function evaluateBudgetGuard(limit: BudgetLimit, summary: UsageSummary): BudgetGuardEvaluation;
|
|
39
54
|
export declare function resetBudgetGuardWriteQueueForTests(): void;
|
|
40
|
-
//# sourceMappingURL=budget-guard.d.ts.map
|
package/dist/lib/budget-guard.js
CHANGED
|
@@ -3,11 +3,10 @@ import { basename, join } from "node:path";
|
|
|
3
3
|
import { logWarn } from "./logger.js";
|
|
4
4
|
import { getCodexMultiAuthDir } from "./runtime-paths.js";
|
|
5
5
|
import { isRecord, sleep } from "./utils.js";
|
|
6
|
-
import {
|
|
6
|
+
import { getJsonStoreFileMtimeMs, resetJsonStoreWriteQueuesForTests, stampUpdatedAt, withJsonStoreCasRetry, withJsonStoreFileLock, withJsonStoreWriteQueue, writeJsonStoreFileAtomicWithRetry, } from "./storage/json-store-lock.js";
|
|
7
7
|
const BUDGET_GUARD_FILE_NAME = "budget-guards.json";
|
|
8
8
|
const RETRYABLE_FS_CODES = new Set(["EBUSY", "EPERM"]);
|
|
9
9
|
const VALID_WINDOWS = new Set(["hour", "day", "week", "month"]);
|
|
10
|
-
let writeQueue = Promise.resolve();
|
|
11
10
|
function isRetryableFsError(error) {
|
|
12
11
|
const code = error?.code;
|
|
13
12
|
return typeof code === "string" && RETRYABLE_FS_CODES.has(code);
|
|
@@ -40,13 +39,35 @@ function normalizeLimit(key, value) {
|
|
|
40
39
|
: 0,
|
|
41
40
|
};
|
|
42
41
|
}
|
|
42
|
+
// Normalized keys can literally be Object.prototype member names —
|
|
43
|
+
// "constructor" and "__proto__" both survive normalizeKey untouched. On a
|
|
44
|
+
// plain object, reading an absent key resolves an inherited member
|
|
45
|
+
// ({}.constructor === Object), which made a same-named limit look "already
|
|
46
|
+
// present" to the merge and silently dropped the incoming entry; writing
|
|
47
|
+
// "__proto__" invokes the setter and mutates the prototype instead of storing
|
|
48
|
+
// anything. Null-prototype maps make every key a plain data slot regardless of
|
|
49
|
+
// name (same convention as lib/storage/snapshot-merge.ts).
|
|
50
|
+
function newLimitsMap() {
|
|
51
|
+
return Object.create(null);
|
|
52
|
+
}
|
|
53
|
+
// Writes into maps that callers may have built as plain object literals cannot
|
|
54
|
+
// rely on the map being null-prototype, so "__proto__" needs an own-property
|
|
55
|
+
// write that bypasses the inherited setter.
|
|
56
|
+
function writeLimitEntry(map, key, limit) {
|
|
57
|
+
Object.defineProperty(map, key, {
|
|
58
|
+
value: limit,
|
|
59
|
+
writable: true,
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
43
64
|
function emptyStore() {
|
|
44
|
-
return { version: 1, limits:
|
|
65
|
+
return { version: 1, limits: newLimitsMap() };
|
|
45
66
|
}
|
|
46
67
|
function normalizeStore(value) {
|
|
47
68
|
if (!isRecord(value) || value.version !== 1)
|
|
48
69
|
return emptyStore();
|
|
49
|
-
const limits =
|
|
70
|
+
const limits = newLimitsMap();
|
|
50
71
|
if (isRecord(value.limits)) {
|
|
51
72
|
for (const [rawKey, raw] of Object.entries(value.limits)) {
|
|
52
73
|
const key = normalizeKey(rawKey);
|
|
@@ -94,54 +115,113 @@ export async function loadBudgetGuardStore() {
|
|
|
94
115
|
return emptyStore();
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Per-key merge of the caller's normalized store over the freshest on-disk
|
|
120
|
+
* store. Budget entries carry `updatedAt`; the newer entry wins per key so a
|
|
121
|
+
* save built on a stale snapshot cannot resurrect an older limit over a
|
|
122
|
+
* concurrent process's newer one. Keys the caller does not carry are
|
|
123
|
+
* preserved (upsert-only store — nothing deletes entries), matching the
|
|
124
|
+
* config save's patch-over-fresh-read semantics.
|
|
125
|
+
*
|
|
126
|
+
* When `baseline` (the caller's pre-edit snapshot) is supplied, entries
|
|
127
|
+
* identical to it are untouched carried copies and skipped entirely, so a
|
|
128
|
+
* stale snapshot row can never be re-stamped over a raced write. Entries
|
|
129
|
+
* that differ are deliberate writes and must not lose purely on timestamp:
|
|
130
|
+
* the upsert-time floor stamps against the caller's snapshot, but a
|
|
131
|
+
* concurrent writer can land a still-newer entry before this merge runs, so
|
|
132
|
+
* the merge re-stamps against the freshest on-disk entry instead of
|
|
133
|
+
* silently dropping the edit. Without a baseline every supplied entry is a
|
|
134
|
+
* plain `updatedAt >=` upsert.
|
|
135
|
+
*/
|
|
136
|
+
function mergeBudgetGuardLimits(current, incoming, baseline) {
|
|
137
|
+
const merged = {
|
|
138
|
+
version: 1,
|
|
139
|
+
limits: Object.assign(newLimitsMap(), current.limits),
|
|
140
|
+
};
|
|
141
|
+
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
142
|
+
for (const [key, limit] of Object.entries(incoming.limits)) {
|
|
143
|
+
const existing = merged.limits[key];
|
|
144
|
+
if (!baseline) {
|
|
145
|
+
if (!existing || limit.updatedAt >= existing.updatedAt) {
|
|
146
|
+
merged.limits[key] = limit;
|
|
120
147
|
}
|
|
148
|
+
continue;
|
|
121
149
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
if (same(limit, baseline.limits[key]))
|
|
151
|
+
continue;
|
|
152
|
+
limit.updatedAt = stampUpdatedAt(limit.updatedAt, existing?.updatedAt);
|
|
153
|
+
merged.limits[key] = limit;
|
|
154
|
+
}
|
|
155
|
+
return merged;
|
|
156
|
+
}
|
|
157
|
+
export async function saveBudgetGuardStore(store, baseline) {
|
|
158
|
+
const path = getBudgetGuardPath();
|
|
159
|
+
const incoming = normalizeStore(store);
|
|
160
|
+
// Normalize at invocation like `incoming`: later caller-side mutation of
|
|
161
|
+
// `baseline` must not shift which entries the merge counts as deliberate.
|
|
162
|
+
const prior = baseline ? normalizeStore(baseline) : undefined;
|
|
163
|
+
// Per-path promise queue serializes writers inside THIS process; the
|
|
164
|
+
// lock directory closes the same window against OTHER processes. Inside the lock
|
|
165
|
+
// every attempt re-stats (CAS), re-reads the freshest on-disk store, and
|
|
166
|
+
// merges this call's entries over it — so a save that raced a concurrent
|
|
167
|
+
// write reloads-and-retries rather than blindly overwriting it.
|
|
168
|
+
await withJsonStoreWriteQueue(path, async () => {
|
|
169
|
+
await withJsonStoreFileLock(path, async () => {
|
|
170
|
+
await withJsonStoreCasRetry(async () => {
|
|
171
|
+
const expectedMtimeMs = await getJsonStoreFileMtimeMs(path);
|
|
172
|
+
const current = await loadBudgetGuardStore();
|
|
173
|
+
const merged = mergeBudgetGuardLimits(current, incoming, prior);
|
|
174
|
+
await fs.mkdir(getCodexMultiAuthDir(), {
|
|
175
|
+
recursive: true,
|
|
176
|
+
mode: 0o700,
|
|
177
|
+
});
|
|
178
|
+
await writeJsonStoreFileAtomicWithRetry(path, merged, {
|
|
179
|
+
expectedMtimeMs,
|
|
180
|
+
mode: 0o600,
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Run a budget-guard read→mutate→write inside the write queue (in-process
|
|
188
|
+
* serialization) AND the cross-process lock directory, with mtime CAS retry:
|
|
189
|
+
* every attempt re-reads the freshest on-disk store and re-applies `mutate`
|
|
190
|
+
* before writing — so a mutation is applied to the latest committed state
|
|
191
|
+
* rather than merged by whole-record `updatedAt`, which can drop or clobber
|
|
192
|
+
* a concurrent process's change to the same key. `mutate` must be
|
|
193
|
+
* re-appliable across retries (apply precomputed work onto the store it is
|
|
194
|
+
* handed, don't capture mutated state). Prefer this over load→upsert→save
|
|
195
|
+
* whenever the caller is mutating rather than importing a foreign store.
|
|
196
|
+
*/
|
|
197
|
+
export async function updateBudgetGuardStore(mutate) {
|
|
198
|
+
const path = getBudgetGuardPath();
|
|
199
|
+
return withJsonStoreWriteQueue(path, () => withJsonStoreFileLock(path, () => withJsonStoreCasRetry(async () => {
|
|
200
|
+
const expectedMtimeMs = await getJsonStoreFileMtimeMs(path);
|
|
201
|
+
const store = await loadBudgetGuardStore();
|
|
202
|
+
const { result, dirty } = mutate(store);
|
|
203
|
+
if (dirty) {
|
|
204
|
+
await fs.mkdir(getCodexMultiAuthDir(), {
|
|
205
|
+
recursive: true,
|
|
206
|
+
mode: 0o700,
|
|
207
|
+
});
|
|
208
|
+
await writeJsonStoreFileAtomicWithRetry(path, normalizeStore(store), { expectedMtimeMs, mode: 0o600 });
|
|
131
209
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
writeQueue = queued.then(() => undefined, () => undefined);
|
|
135
|
-
await queued;
|
|
210
|
+
return result;
|
|
211
|
+
})));
|
|
136
212
|
}
|
|
137
213
|
export function upsertBudgetLimit(store, limit, now = Date.now()) {
|
|
138
214
|
const key = normalizeKey(limit.key);
|
|
139
215
|
if (!key)
|
|
140
216
|
throw new Error("Budget key is required");
|
|
141
|
-
const next = normalizeLimit(key, {
|
|
217
|
+
const next = normalizeLimit(key, {
|
|
218
|
+
...limit,
|
|
219
|
+
key,
|
|
220
|
+
updatedAt: stampUpdatedAt(now, store.limits[key]?.updatedAt),
|
|
221
|
+
});
|
|
142
222
|
if (!next)
|
|
143
223
|
throw new Error("Invalid budget limit");
|
|
144
|
-
store.limits
|
|
224
|
+
writeLimitEntry(store.limits, key, next);
|
|
145
225
|
return next;
|
|
146
226
|
}
|
|
147
227
|
export function getBudgetWindowStart(window, now = Date.now()) {
|
|
@@ -207,5 +287,5 @@ export function evaluateBudgetGuard(limit, summary) {
|
|
|
207
287
|
};
|
|
208
288
|
}
|
|
209
289
|
export function resetBudgetGuardWriteQueueForTests() {
|
|
210
|
-
|
|
290
|
+
resetJsonStoreWriteQueuesForTests(getBudgetGuardPath());
|
|
211
291
|
}
|
|
@@ -9,6 +9,20 @@ export type CircuitState = "closed" | "open" | "half-open";
|
|
|
9
9
|
export declare class CircuitOpenError extends Error {
|
|
10
10
|
constructor(message?: string);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Non-throwing admission result, for hot paths that would otherwise pay for a
|
|
14
|
+
* {@link CircuitOpenError} allocation on every rejection during a storm.
|
|
15
|
+
* `reason` names the gate that rejected so callers can keep their own error
|
|
16
|
+
* taxonomy without parsing exception messages.
|
|
17
|
+
*/
|
|
18
|
+
export type CircuitAdmissionResult = {
|
|
19
|
+
ok: true;
|
|
20
|
+
} | {
|
|
21
|
+
ok: false;
|
|
22
|
+
reason: "open" | "half-open";
|
|
23
|
+
/** Milliseconds until a fresh attempt may be admitted. */
|
|
24
|
+
retryAfterMs: number;
|
|
25
|
+
};
|
|
12
26
|
export declare class CircuitBreaker {
|
|
13
27
|
private state;
|
|
14
28
|
private failures;
|
|
@@ -16,6 +30,12 @@ export declare class CircuitBreaker {
|
|
|
16
30
|
private halfOpenAttempts;
|
|
17
31
|
private config;
|
|
18
32
|
constructor(config?: Partial<CircuitBreakerConfig>);
|
|
33
|
+
/**
|
|
34
|
+
* Same admission decision as {@link canExecute} but returns a result
|
|
35
|
+
* object instead of throwing, so reject-heavy callers stay exception-free.
|
|
36
|
+
* Admitting a probe still consumes the half-open attempt slot.
|
|
37
|
+
*/
|
|
38
|
+
tryCanExecute(): CircuitAdmissionResult;
|
|
19
39
|
canExecute(): boolean;
|
|
20
40
|
isAvailable(now?: number): boolean;
|
|
21
41
|
recordSuccess(): void;
|
|
@@ -41,4 +61,3 @@ export declare function clearCircuitBreakers(): void;
|
|
|
41
61
|
* than inheriting an open one (accounts-02).
|
|
42
62
|
*/
|
|
43
63
|
export declare function removeCircuitBreaker(key: string): void;
|
|
44
|
-
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -19,14 +19,23 @@ export class CircuitBreaker {
|
|
|
19
19
|
constructor(config = {}) {
|
|
20
20
|
this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Same admission decision as {@link canExecute} but returns a result
|
|
24
|
+
* object instead of throwing, so reject-heavy callers stay exception-free.
|
|
25
|
+
* Admitting a probe still consumes the half-open attempt slot.
|
|
26
|
+
*/
|
|
27
|
+
tryCanExecute() {
|
|
23
28
|
const now = Date.now();
|
|
24
29
|
if (this.state === "open") {
|
|
25
30
|
if (now - this.lastStateChange >= this.config.resetTimeoutMs) {
|
|
26
31
|
this.transitionToHalfOpen(now);
|
|
27
32
|
}
|
|
28
33
|
else {
|
|
29
|
-
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
reason: "open",
|
|
37
|
+
retryAfterMs: Math.max(0, this.config.resetTimeoutMs - (now - this.lastStateChange)),
|
|
38
|
+
};
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
41
|
if (this.state === "half-open") {
|
|
@@ -35,13 +44,23 @@ export class CircuitBreaker {
|
|
|
35
44
|
this.resetHalfOpenProbeWindow(now);
|
|
36
45
|
}
|
|
37
46
|
else {
|
|
38
|
-
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
reason: "half-open",
|
|
50
|
+
retryAfterMs: Math.max(0, this.config.resetTimeoutMs - (now - this.lastStateChange)),
|
|
51
|
+
};
|
|
39
52
|
}
|
|
40
53
|
}
|
|
41
54
|
this.halfOpenAttempts += 1;
|
|
42
|
-
return true;
|
|
55
|
+
return { ok: true };
|
|
43
56
|
}
|
|
44
|
-
return true;
|
|
57
|
+
return { ok: true };
|
|
58
|
+
}
|
|
59
|
+
canExecute() {
|
|
60
|
+
const result = this.tryCanExecute();
|
|
61
|
+
if (result.ok)
|
|
62
|
+
return true;
|
|
63
|
+
throw new CircuitOpenError(result.reason === "half-open" ? "Circuit is half-open" : "Circuit is open");
|
|
45
64
|
}
|
|
46
65
|
isAvailable(now = Date.now()) {
|
|
47
66
|
if (this.state === "open") {
|
package/dist/lib/cli.d.ts
CHANGED
|
@@ -68,4 +68,3 @@ export interface AccountSelectionOptions {
|
|
|
68
68
|
export declare function promptAccountSelection(candidates: AccountSelectionCandidate[], options?: AccountSelectionOptions): Promise<AccountSelectionCandidate | null>;
|
|
69
69
|
export { isTTY };
|
|
70
70
|
export type { AccountStatus };
|
|
71
|
-
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -99,4 +99,3 @@ export declare function loadCodexCliState(options?: {
|
|
|
99
99
|
export declare function lookupCodexCliTokensByEmail(email: string | undefined): Promise<CodexCliTokenCacheEntry | null>;
|
|
100
100
|
export declare function clearCodexCliStateCache(): void;
|
|
101
101
|
export declare function __resetCodexCliWarningCacheForTests(): void;
|
|
102
|
-
//# sourceMappingURL=state.d.ts.map
|
|
@@ -60,4 +60,3 @@ export declare function ensureCodexCliFileAuthStore(configPath?: string): Promis
|
|
|
60
60
|
export declare function setCodexCliActiveSelection(selection: ActiveSelection): Promise<boolean>;
|
|
61
61
|
export declare function getLastCodexCliSelectionWriteTimestamp(): number;
|
|
62
62
|
export {};
|
|
63
|
-
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only: clear the storage-fingerprint cache so each test re-reads from
|
|
3
|
+
* disk instead of inheriting a previous scenario's "already synced" state.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resetActiveAccountSyncMetaForTests(): void;
|
|
6
|
+
export declare function autoSyncActiveAccountToCodex(): Promise<boolean>;
|