codex-multi-auth 2.17.2 → 2.18.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 +86 -425
- package/config/README.md +1 -1
- package/config/codex-legacy.json +12 -212
- package/config/codex-modern.json +4 -80
- package/config/minimal-codex.json +1 -1
- 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 +1 -2
- package/dist/lib/context-budget/model-context-windows.js +10 -13
- 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 +3 -3
- package/dist/lib/oc-chatgpt-target-detection.js +40 -13
- 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/error-classification.js +41 -52
- 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/fetch-helpers.js +1 -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 +2 -3
- package/dist/lib/request/helpers/model-map.js +120 -78
- 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 +1 -2
- package/dist/lib/request/request-transformer.js +51 -26
- 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 +0 -1
- 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 +1 -2
- package/dist/lib/ui/ui-copy.js +1 -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 +1 -2
- package/dist/lib/usage/pricing.js +41 -16
- 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 +385 -89
- package/skills/codex-auth-setup/SKILL.md +73 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
1
|
+
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { existsSync, 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";
|
|
6
6
|
import { isRecord, sleep } from "./utils.js";
|
|
7
7
|
import { tempPathFor } from "./temp-path.js";
|
|
8
|
+
import { assertJsonStoreFileMtimeUnchanged, getJsonStoreFileMtimeMs, withJsonStoreCasRetry, withJsonStoreFileLock, } from "./storage/json-store-lock.js";
|
|
8
9
|
const TOKEN_FILE_NAME = "local-client-tokens.json";
|
|
9
10
|
const TOKEN_PREFIX = "cma_local";
|
|
10
11
|
// Debounce window for persisting a record's lastUsedAt. Bearer verification is
|
|
@@ -43,6 +44,27 @@ function normalizeLabel(value) {
|
|
|
43
44
|
function hashToken(token) {
|
|
44
45
|
return `sha256:${createHash("sha256").update(token).digest("hex")}`;
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Constant-time equality for two `sha256:<hex>` token hashes.
|
|
49
|
+
*
|
|
50
|
+
* A `===` on the hex strings returns early at the first differing byte, so a
|
|
51
|
+
* local process that can spam verify calls could measure the comparison cost
|
|
52
|
+
* and recover a stored hash prefix byte-by-byte. Comparing the decoded digest
|
|
53
|
+
* bytes with timingSafeEqual removes the oracle; both inputs are validated to
|
|
54
|
+
* the fixed 32-byte shape first, so timingSafeEqual never throws.
|
|
55
|
+
*/
|
|
56
|
+
function sha256DigestBytes(hash) {
|
|
57
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(hash))
|
|
58
|
+
return null;
|
|
59
|
+
return Buffer.from(hash.slice("sha256:".length), "hex");
|
|
60
|
+
}
|
|
61
|
+
function tokenHashEqual(left, right) {
|
|
62
|
+
const leftDigest = sha256DigestBytes(left);
|
|
63
|
+
const rightDigest = sha256DigestBytes(right);
|
|
64
|
+
return (leftDigest !== null &&
|
|
65
|
+
rightDigest !== null &&
|
|
66
|
+
timingSafeEqual(leftDigest, rightDigest));
|
|
67
|
+
}
|
|
46
68
|
function createPlainToken() {
|
|
47
69
|
return `${TOKEN_PREFIX}_${randomBytes(32).toString("base64url")}`;
|
|
48
70
|
}
|
|
@@ -120,7 +142,46 @@ export async function loadLocalClientTokenStore() {
|
|
|
120
142
|
return emptyStore();
|
|
121
143
|
}
|
|
122
144
|
}
|
|
123
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Merge a caller-supplied store over the freshest on-disk store by token id.
|
|
147
|
+
* Records the caller does not carry are preserved (this store is append-only:
|
|
148
|
+
* rotation and revocation mark records in place, nothing deletes them), and
|
|
149
|
+
* the monotone fields a concurrent process may have advanced — `lastUsedAt`
|
|
150
|
+
* from verifies, `revokedAt` from revocations/rotations — are kept at their
|
|
151
|
+
* furthest value so a stale snapshot cannot un-revoke or rewind usage.
|
|
152
|
+
*/
|
|
153
|
+
function mergeTokenStoreRecords(current, incoming) {
|
|
154
|
+
const indexById = new Map();
|
|
155
|
+
const tokens = current.tokens.map((record, index) => {
|
|
156
|
+
indexById.set(record.id, index);
|
|
157
|
+
return record;
|
|
158
|
+
});
|
|
159
|
+
for (const record of incoming.tokens) {
|
|
160
|
+
const index = indexById.get(record.id);
|
|
161
|
+
if (index === undefined) {
|
|
162
|
+
indexById.set(record.id, tokens.length);
|
|
163
|
+
tokens.push(record);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const existing = tokens[index];
|
|
167
|
+
if (existing === undefined) {
|
|
168
|
+
// Unreachable: indexes recorded in indexById always point at a
|
|
169
|
+
// slot that exists in `tokens`.
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
tokens[index] = {
|
|
173
|
+
...record,
|
|
174
|
+
lastUsedAt: record.lastUsedAt === null
|
|
175
|
+
? existing.lastUsedAt
|
|
176
|
+
: existing.lastUsedAt === null
|
|
177
|
+
? record.lastUsedAt
|
|
178
|
+
: Math.max(record.lastUsedAt, existing.lastUsedAt),
|
|
179
|
+
revokedAt: record.revokedAt ?? existing.revokedAt,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return { version: 1, tokens };
|
|
183
|
+
}
|
|
184
|
+
async function writeStoreToDisk(store, expectedMtimeMs) {
|
|
124
185
|
const path = getLocalClientTokenPath();
|
|
125
186
|
const payload = normalizeStore(store);
|
|
126
187
|
const dir = getCodexMultiAuthDir();
|
|
@@ -153,6 +214,12 @@ async function writeStoreToDisk(store) {
|
|
|
153
214
|
finally {
|
|
154
215
|
await handle.close();
|
|
155
216
|
}
|
|
217
|
+
// Compare-and-swap guard: a writer that did not take the lockfile (or an
|
|
218
|
+
// expired-lock takeover racing this write) moved the target's mtime; abort
|
|
219
|
+
// with ESTALE so the caller reloads and re-merges instead of clobbering.
|
|
220
|
+
if (expectedMtimeMs !== undefined) {
|
|
221
|
+
await assertJsonStoreFileMtimeUnchanged(path, expectedMtimeMs);
|
|
222
|
+
}
|
|
156
223
|
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
157
224
|
try {
|
|
158
225
|
await fs.rename(tempPath, path);
|
|
@@ -177,8 +244,36 @@ async function writeStoreToDisk(store) {
|
|
|
177
244
|
}
|
|
178
245
|
}
|
|
179
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Run a token-store read→mutate→write inside the write queue (in-process
|
|
249
|
+
* serialization) AND the cross-process lock directory, with mtime CAS retry:
|
|
250
|
+
* every attempt re-stats the file, re-reads the freshest on-disk store, and
|
|
251
|
+
* re-applies `mutate` before writing — so an op whose snapshot raced a
|
|
252
|
+
* concurrent process's write reloads-and-retries rather than clobbering it.
|
|
253
|
+
* `mutate` must be re-appliable across retries (apply precomputed work onto
|
|
254
|
+
* the store it is handed, don't capture mutated state).
|
|
255
|
+
*/
|
|
256
|
+
async function updateLocalClientTokenStore(mutate) {
|
|
257
|
+
const path = getLocalClientTokenPath();
|
|
258
|
+
return enqueue(() => withJsonStoreFileLock(path, () => withJsonStoreCasRetry(async () => {
|
|
259
|
+
const expectedMtimeMs = await getJsonStoreFileMtimeMs(path);
|
|
260
|
+
const store = await loadLocalClientTokenStore();
|
|
261
|
+
const { result, dirty } = mutate(store);
|
|
262
|
+
if (dirty) {
|
|
263
|
+
await writeStoreToDisk(store, expectedMtimeMs);
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
})));
|
|
267
|
+
}
|
|
180
268
|
export async function saveLocalClientTokenStore(store) {
|
|
181
|
-
|
|
269
|
+
const path = getLocalClientTokenPath();
|
|
270
|
+
const incoming = normalizeStore(store);
|
|
271
|
+
await enqueue(() => withJsonStoreFileLock(path, () => withJsonStoreCasRetry(async () => {
|
|
272
|
+
const expectedMtimeMs = await getJsonStoreFileMtimeMs(path);
|
|
273
|
+
const current = await loadLocalClientTokenStore();
|
|
274
|
+
const merged = mergeTokenStoreRecords(current, incoming);
|
|
275
|
+
await writeStoreToDisk(merged, expectedMtimeMs);
|
|
276
|
+
})));
|
|
182
277
|
}
|
|
183
278
|
export function createLocalClientTokenRecord(input = {}) {
|
|
184
279
|
const plainToken = createPlainToken();
|
|
@@ -194,40 +289,40 @@ export function createLocalClientTokenRecord(input = {}) {
|
|
|
194
289
|
return { plainToken, record };
|
|
195
290
|
}
|
|
196
291
|
export async function addLocalClientToken(input = {}) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
292
|
+
// The token record is created once, outside the CAS retry: re-applying the
|
|
293
|
+
// same record onto a freshly-reloaded store is what makes each retry safe.
|
|
294
|
+
const created = createLocalClientTokenRecord(input);
|
|
295
|
+
return updateLocalClientTokenStore((store) => {
|
|
200
296
|
store.tokens.push(created.record);
|
|
201
|
-
|
|
202
|
-
return created;
|
|
297
|
+
return { result: created, dirty: true };
|
|
203
298
|
});
|
|
204
299
|
}
|
|
205
300
|
export async function rotateLocalClientToken(input) {
|
|
206
|
-
|
|
207
|
-
|
|
301
|
+
const now = input.now ?? Date.now();
|
|
302
|
+
let created = null;
|
|
303
|
+
return updateLocalClientTokenStore((store) => {
|
|
208
304
|
const existing = store.tokens.find((record) => record.id === input.id);
|
|
209
|
-
if (!existing || existing.revokedAt !== null)
|
|
210
|
-
return null;
|
|
211
|
-
|
|
305
|
+
if (!existing || existing.revokedAt !== null) {
|
|
306
|
+
return { result: null, dirty: false };
|
|
307
|
+
}
|
|
212
308
|
existing.revokedAt = now;
|
|
213
|
-
|
|
309
|
+
// Same record across CAS retries so a retry cannot mint a second token.
|
|
310
|
+
created ??= createLocalClientTokenRecord({
|
|
214
311
|
label: input.label ?? existing.label,
|
|
215
312
|
now,
|
|
216
313
|
});
|
|
217
314
|
store.tokens.push(created.record);
|
|
218
|
-
|
|
219
|
-
return created;
|
|
315
|
+
return { result: created, dirty: true };
|
|
220
316
|
});
|
|
221
317
|
}
|
|
222
318
|
export async function revokeLocalClientToken(id, now = Date.now()) {
|
|
223
|
-
return
|
|
224
|
-
const store = await loadLocalClientTokenStore();
|
|
319
|
+
return updateLocalClientTokenStore((store) => {
|
|
225
320
|
const existing = store.tokens.find((record) => record.id === id);
|
|
226
|
-
if (!existing || existing.revokedAt !== null)
|
|
227
|
-
return false;
|
|
321
|
+
if (!existing || existing.revokedAt !== null) {
|
|
322
|
+
return { result: false, dirty: false };
|
|
323
|
+
}
|
|
228
324
|
existing.revokedAt = now;
|
|
229
|
-
|
|
230
|
-
return true;
|
|
325
|
+
return { result: true, dirty: true };
|
|
231
326
|
});
|
|
232
327
|
}
|
|
233
328
|
export async function verifyLocalClientBearerToken(authorizationHeader, now = Date.now()) {
|
|
@@ -236,11 +331,10 @@ export async function verifyLocalClientBearerToken(authorizationHeader, now = Da
|
|
|
236
331
|
if (!token)
|
|
237
332
|
return null;
|
|
238
333
|
const tokenHash = hashToken(token);
|
|
239
|
-
return
|
|
240
|
-
const
|
|
241
|
-
const record = store.tokens.find((entry) => entry.revokedAt === null && entry.tokenHash === tokenHash);
|
|
334
|
+
return updateLocalClientTokenStore((store) => {
|
|
335
|
+
const record = store.tokens.find((entry) => entry.revokedAt === null && tokenHashEqual(entry.tokenHash, tokenHash));
|
|
242
336
|
if (!record)
|
|
243
|
-
return null;
|
|
337
|
+
return { result: null, dirty: false };
|
|
244
338
|
// Token match (verification correctness) is decided above and never
|
|
245
339
|
// depends on lastUsedAt. Always advance lastUsedAt in-memory so callers
|
|
246
340
|
// see a fresh value, but only flush to disk when it has not been
|
|
@@ -249,10 +343,11 @@ export async function verifyLocalClientBearerToken(authorizationHeader, now = Da
|
|
|
249
343
|
// recent usage on a coarse (>=60s) cadence.
|
|
250
344
|
const persisted = record.lastUsedAt;
|
|
251
345
|
record.lastUsedAt = now;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
346
|
+
return {
|
|
347
|
+
result: record,
|
|
348
|
+
dirty: persisted === null ||
|
|
349
|
+
now - persisted >= LAST_USED_PERSIST_THRESHOLD_MS,
|
|
350
|
+
};
|
|
256
351
|
});
|
|
257
352
|
}
|
|
258
353
|
export function resetLocalClientTokenWriteQueueForTests() {
|
package/dist/lib/logger.d.ts
CHANGED
|
@@ -45,4 +45,3 @@ export interface ScopedLogger {
|
|
|
45
45
|
export declare function createLogger(scope: string): ScopedLogger;
|
|
46
46
|
export declare function getRequestId(): number;
|
|
47
47
|
export { formatDuration, maskEmail, maskString, maskToken, sanitizeValue };
|
|
48
|
-
//# sourceMappingURL=logger.d.ts.map
|
package/dist/lib/logger.js
CHANGED
|
@@ -21,7 +21,17 @@ const TOKEN_PATTERNS = [
|
|
|
21
21
|
// line of defense and must recognize the project's own token shape too.
|
|
22
22
|
/cma_local_[A-Za-z0-9_-]{16,}/g,
|
|
23
23
|
];
|
|
24
|
-
|
|
24
|
+
// Label-shaped domain instead of `[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}`: letting `.`
|
|
25
|
+
// live inside the quantified class makes every dot a candidate split point,
|
|
26
|
+
// which backtracked quadratically (~3.5s) on dotted near-miss input. Labels
|
|
27
|
+
// are dot-free, so each dot has exactly one structural role.
|
|
28
|
+
// The `(?<!...)` lookbehind confines match starts to a run boundary: the
|
|
29
|
+
// unanchored pattern could otherwise begin inside an overlong local part or
|
|
30
|
+
// domain label and leave its leading/trailing edge visible in logs. Interior
|
|
31
|
+
// positions fail the lookbehind in O(1), which is also what keeps the
|
|
32
|
+
// unbounded quantifiers linear — each character run is scanned once from its
|
|
33
|
+
// edge instead of being rescanned from every offset.
|
|
34
|
+
const EMAIL_PATTERN = /(?<![a-zA-Z0-9._%+-])[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}/g;
|
|
25
35
|
const SENSITIVE_KEYS = new Set([
|
|
26
36
|
"access",
|
|
27
37
|
"accesstoken",
|
|
@@ -44,9 +44,8 @@ export declare function modelEntitlements(model: RouteModel): {
|
|
|
44
44
|
reasoningLevels: string[];
|
|
45
45
|
accessPrograms: string[];
|
|
46
46
|
probes?: {
|
|
47
|
-
[k: string]: "
|
|
47
|
+
[k: string]: "verified" | "unsupported" | "unverified" | "downgraded";
|
|
48
48
|
} | undefined;
|
|
49
49
|
checkedAt?: number | undefined;
|
|
50
50
|
model: string;
|
|
51
51
|
};
|
|
52
|
-
//# sourceMappingURL=model-route-policy.d.ts.map
|
|
@@ -66,4 +66,3 @@ export declare function resolveNamedBackupPath(name: string, storagePath: string
|
|
|
66
66
|
export declare function exportNamedBackupFile(name: string, dependencies: NamedBackupExportDependencies, options?: {
|
|
67
67
|
force?: boolean;
|
|
68
68
|
}): Promise<string>;
|
|
69
|
-
//# sourceMappingURL=named-backup-export.d.ts.map
|
|
@@ -35,7 +35,8 @@ export type OcChatgptTargetDetectionResult = OcChatgptTargetFound | OcChatgptTar
|
|
|
35
35
|
/**
|
|
36
36
|
* Detects the oc-chatgpt multi-auth storage target by evaluating explicit, canonical, and per-project candidate roots.
|
|
37
37
|
*
|
|
38
|
-
* Examines an explicit override (
|
|
38
|
+
* Examines an explicit override (OC_CODEX_MULTI_AUTH_DIR, the legacy OC_CHATGPT_MULTI_AUTH_DIR alias, or
|
|
39
|
+
* options.explicitRoot), the canonical user store (~/.opencode),
|
|
39
40
|
* and a per-project storage location (derived from options.projectRoot or the current working directory). For each candidate
|
|
40
41
|
* it checks for account artifacts and storage signals and returns a single resolved target, an ambiguity listing multiple
|
|
41
42
|
* matching candidates, or a "none" result with the attempted candidates. This function performs synchronous filesystem checks
|
|
@@ -45,7 +46,7 @@ export type OcChatgptTargetDetectionResult = OcChatgptTargetFound | OcChatgptTar
|
|
|
45
46
|
*
|
|
46
47
|
* @param options - Optional overrides:
|
|
47
48
|
* - explicitRoot: absolute path to force as the candidate root (use `null` to explicitly disable); if omitted the
|
|
48
|
-
*
|
|
49
|
+
* OC_CODEX_MULTI_AUTH_DIR environment variable is considered, then the legacy OC_CHATGPT_MULTI_AUTH_DIR alias.
|
|
49
50
|
* - projectRoot: explicit project root to derive per-project storage; if omitted the current working directory is used to
|
|
50
51
|
* discover the project root.
|
|
51
52
|
* @returns An OcChatgptTargetDetectionResult describing either a resolved `target` (with `descriptor` and a `resolution`
|
|
@@ -56,4 +57,3 @@ export declare function detectOcChatgptMultiAuthTarget(options?: {
|
|
|
56
57
|
projectRoot?: string | null;
|
|
57
58
|
}): OcChatgptTargetDetectionResult;
|
|
58
59
|
export {};
|
|
59
|
-
//# sourceMappingURL=oc-chatgpt-target-detection.d.ts.map
|
|
@@ -2,7 +2,14 @@ import { existsSync, readdirSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join, normalize, relative, resolve, sep, win32 } from "node:path";
|
|
4
4
|
import { findProjectRoot, getProjectStorageKey, resolveProjectStorageIdentityRoot, } from "./storage/paths.js";
|
|
5
|
-
|
|
5
|
+
// The sibling plugin renamed its account file from `openai-codex-accounts.json`
|
|
6
|
+
// (oc-chatgpt-multi-auth era) to `oc-codex-multi-auth-accounts.json`; both are
|
|
7
|
+
// detected, preferring the current name when a root holds both.
|
|
8
|
+
const ACCOUNT_FILE_NAMES = [
|
|
9
|
+
"oc-codex-multi-auth-accounts.json",
|
|
10
|
+
"openai-codex-accounts.json",
|
|
11
|
+
];
|
|
12
|
+
const ACCOUNT_FILE_NAME = ACCOUNT_FILE_NAMES[0];
|
|
6
13
|
const BACKUPS_DIR_NAME = "backups";
|
|
7
14
|
const PROJECTS_DIR_NAME = "projects";
|
|
8
15
|
const CANONICAL_HOME_BASENAME = ".opencode";
|
|
@@ -107,17 +114,32 @@ function deduplicatePaths(paths) {
|
|
|
107
114
|
}
|
|
108
115
|
return result;
|
|
109
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Returns the path of the primary account file under `root`, preferring the
|
|
119
|
+
* current `oc-codex-multi-auth-accounts.json` name over the legacy
|
|
120
|
+
* `openai-codex-accounts.json` name when both exist, or `null` when neither
|
|
121
|
+
* file (nor its `.wal` sidecar) is present.
|
|
122
|
+
*/
|
|
123
|
+
function findPrimaryAccountPath(root) {
|
|
124
|
+
for (const name of ACCOUNT_FILE_NAMES) {
|
|
125
|
+
const accountPath = join(root, name);
|
|
126
|
+
if (existsSync(accountPath) || existsSync(`${accountPath}.wal`)) {
|
|
127
|
+
return accountPath;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
110
132
|
/**
|
|
111
133
|
* Detects whether an account file or rotated account artifacts exist under the specified storage root.
|
|
112
134
|
*
|
|
113
|
-
* Scans for
|
|
135
|
+
* Scans for an account file under either known name (`oc-codex-multi-auth-accounts.json` or the legacy `openai-codex-accounts.json`) and its WAL variant, rotated/archived files matching either account filename pattern (excluding `.tmp`, `.wal`, and names containing `.rotate.`), and the backups directory. The probe is tolerant of unreadable directories (errors are ignored) and does not read file contents. Callers should be aware of concurrent filesystem changes — a `false` result does not guarantee no artifact will appear shortly after. On Windows, filesystem matching should be considered case-insensitive by callers. This check does not expose or parse any token contents.
|
|
114
136
|
*
|
|
115
137
|
* @param root - Filesystem path of the storage root to probe
|
|
138
|
+
* @param primaryAccountPath - Result of `findPrimaryAccountPath(root)`, so callers resolve the descriptor path once
|
|
116
139
|
* @returns `true` if any account file or rotated account artifact exists under `root` or its backups directory, `false` otherwise.
|
|
117
140
|
*/
|
|
118
|
-
function hasAccountArtifacts(root) {
|
|
119
|
-
|
|
120
|
-
if (existsSync(accountPath) || existsSync(`${accountPath}.wal`)) {
|
|
141
|
+
function hasAccountArtifacts(root, primaryAccountPath) {
|
|
142
|
+
if (primaryAccountPath !== null) {
|
|
121
143
|
return true;
|
|
122
144
|
}
|
|
123
145
|
const hasRotated = (dir) => {
|
|
@@ -126,7 +148,7 @@ function hasAccountArtifacts(root) {
|
|
|
126
148
|
for (const entry of entries) {
|
|
127
149
|
if (!entry.isFile())
|
|
128
150
|
continue;
|
|
129
|
-
if (!entry.name.startsWith(`${
|
|
151
|
+
if (!ACCOUNT_FILE_NAMES.some((name) => entry.name.startsWith(`${name}.`)))
|
|
130
152
|
continue;
|
|
131
153
|
if (entry.name.endsWith(".tmp"))
|
|
132
154
|
continue;
|
|
@@ -146,7 +168,7 @@ function hasAccountArtifacts(root) {
|
|
|
146
168
|
return true;
|
|
147
169
|
}
|
|
148
170
|
const backupsDir = join(root, BACKUPS_DIR_NAME);
|
|
149
|
-
if (existsSync(join(backupsDir,
|
|
171
|
+
if (ACCOUNT_FILE_NAMES.some((name) => existsSync(join(backupsDir, name)))) {
|
|
150
172
|
return true;
|
|
151
173
|
}
|
|
152
174
|
if (hasRotated(backupsDir)) {
|
|
@@ -191,7 +213,8 @@ function inferScopeFromRoot(root, canonicalRoot) {
|
|
|
191
213
|
/**
|
|
192
214
|
* Detects the oc-chatgpt multi-auth storage target by evaluating explicit, canonical, and per-project candidate roots.
|
|
193
215
|
*
|
|
194
|
-
* Examines an explicit override (
|
|
216
|
+
* Examines an explicit override (OC_CODEX_MULTI_AUTH_DIR, the legacy OC_CHATGPT_MULTI_AUTH_DIR alias, or
|
|
217
|
+
* options.explicitRoot), the canonical user store (~/.opencode),
|
|
195
218
|
* and a per-project storage location (derived from options.projectRoot or the current working directory). For each candidate
|
|
196
219
|
* it checks for account artifacts and storage signals and returns a single resolved target, an ambiguity listing multiple
|
|
197
220
|
* matching candidates, or a "none" result with the attempted candidates. This function performs synchronous filesystem checks
|
|
@@ -201,14 +224,17 @@ function inferScopeFromRoot(root, canonicalRoot) {
|
|
|
201
224
|
*
|
|
202
225
|
* @param options - Optional overrides:
|
|
203
226
|
* - explicitRoot: absolute path to force as the candidate root (use `null` to explicitly disable); if omitted the
|
|
204
|
-
*
|
|
227
|
+
* OC_CODEX_MULTI_AUTH_DIR environment variable is considered, then the legacy OC_CHATGPT_MULTI_AUTH_DIR alias.
|
|
205
228
|
* - projectRoot: explicit project root to derive per-project storage; if omitted the current working directory is used to
|
|
206
229
|
* discover the project root.
|
|
207
230
|
* @returns An OcChatgptTargetDetectionResult describing either a resolved `target` (with `descriptor` and a `resolution`
|
|
208
231
|
* of `"accounts"` or `"signals"`), an `ambiguous` outcome listing conflicting candidates, or `none` with the tried candidates.
|
|
209
232
|
*/
|
|
210
233
|
export function detectOcChatgptMultiAuthTarget(options) {
|
|
211
|
-
const explicitFromEnv = (
|
|
234
|
+
const explicitFromEnv = (firstNonEmpty([
|
|
235
|
+
process.env.OC_CODEX_MULTI_AUTH_DIR,
|
|
236
|
+
process.env.OC_CHATGPT_MULTI_AUTH_DIR,
|
|
237
|
+
]) ?? "").trim();
|
|
212
238
|
const hasExplicitRootOption = options !== undefined && "explicitRoot" in options;
|
|
213
239
|
const explicitRoot = (hasExplicitRootOption ? (options.explicitRoot ?? "") : explicitFromEnv).trim();
|
|
214
240
|
const userHome = getResolvedUserHomeDir();
|
|
@@ -233,9 +259,10 @@ export function detectOcChatgptMultiAuthTarget(options) {
|
|
|
233
259
|
: inferredScope === "project"
|
|
234
260
|
? "project"
|
|
235
261
|
: "default-global";
|
|
236
|
-
const
|
|
262
|
+
const primaryAccountPath = findPrimaryAccountPath(root);
|
|
263
|
+
const accountPath = primaryAccountPath ?? join(root, ACCOUNT_FILE_NAME);
|
|
237
264
|
const backupRoot = join(root, BACKUPS_DIR_NAME);
|
|
238
|
-
const hasAccountArtifactsFlag = hasAccountArtifacts(root);
|
|
265
|
+
const hasAccountArtifactsFlag = hasAccountArtifacts(root, primaryAccountPath);
|
|
239
266
|
return {
|
|
240
267
|
scope: inferredScope,
|
|
241
268
|
source,
|
|
@@ -314,7 +341,7 @@ export function detectOcChatgptMultiAuthTarget(options) {
|
|
|
314
341
|
}
|
|
315
342
|
return {
|
|
316
343
|
kind: "none",
|
|
317
|
-
reason: "No oc-chatgpt-multi-auth target root found; create ~/.opencode or supply OC_CHATGPT_MULTI_AUTH_DIR.",
|
|
344
|
+
reason: "No oc-chatgpt-multi-auth target root found; create ~/.opencode or supply OC_CODEX_MULTI_AUTH_DIR (legacy OC_CHATGPT_MULTI_AUTH_DIR is still accepted).",
|
|
318
345
|
tried: candidates.map(({ scope, source, root, accountPath, backupRoot }) => ({
|
|
319
346
|
scope,
|
|
320
347
|
source,
|
|
@@ -32,4 +32,3 @@ export declare function getTopCandidates(accountManager: AccountManager, modelFa
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function probeAccountsInParallel<T>(candidates: ProbeCandidate[], probeFn: (account: ManagedAccount, signal: AbortSignal) => Promise<T>, _options?: Partial<ParallelProbeOptions>): Promise<ProbeResult<T> | null>;
|
|
34
34
|
export declare function createProbeCandidates(accounts: ManagedAccount[]): ProbeCandidate[];
|
|
35
|
-
//# sourceMappingURL=parallel-probe.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hot-path caches for the runtime policy stores.
|
|
3
|
+
*
|
|
4
|
+
* `loadRuntimePolicyState` runs once per proxied request, and the proxy is a
|
|
5
|
+
* long-running process while the stores are mutated by separate CLI processes
|
|
6
|
+
* (`account pause`, `budget`, `routing profile`). The naive path re-read +
|
|
7
|
+
* re-parsed three JSON files and re-walked the project-root ancestor chain on
|
|
8
|
+
* every request. These caches keep semantics identical while reducing the
|
|
9
|
+
* steady-state cost to a handful of `statSync` calls:
|
|
10
|
+
*
|
|
11
|
+
* - Store entries are keyed by absolute file path and guarded by an
|
|
12
|
+
* `mtimeMs:ctimeMs:size` fingerprint (same approach as
|
|
13
|
+
* `lib/runtime/rotation-storage-meta.ts`): the store is only re-read when
|
|
14
|
+
* the fingerprint changes. `ctimeMs` is part of the fingerprint because it
|
|
15
|
+
* cannot be pinned back the way `mtimeMs` can — on POSIX every write bumps
|
|
16
|
+
* it, and on Windows every rename-replacement produces a new file creation
|
|
17
|
+
* time — so a rewrite that preserves mtime+size is still caught instead of
|
|
18
|
+
* being served stale for the TTL. A fingerprint match is additionally only
|
|
19
|
+
* trusted once the file's own mtime has settled past `MTIME_SETTLE_MS` —
|
|
20
|
+
* two rapid writes can share a coarse mtime tick on some filesystems (FAT
|
|
21
|
+
* 2s, ~1s Windows/network volumes), so inside the settle window we always
|
|
22
|
+
* re-read. `STORE_CACHE_TTL_MS` bounds staleness for the pathological case
|
|
23
|
+
* where a rewrite leaves mtime, ctime and size unchanged, and
|
|
24
|
+
* `STORE_CACHE_MAX_ENTRIES` bounds the map (tests rotate through many
|
|
25
|
+
* per-test `CODEX_MULTI_AUTH_DIR` temp dirs).
|
|
26
|
+
*
|
|
27
|
+
* Two failure modes get dedicated handling so they cannot poison the cache:
|
|
28
|
+
* a file rewritten *while* the loader is reading it is detected by
|
|
29
|
+
* re-statting after the load and only caching when the fingerprint is
|
|
30
|
+
* stable across the read (an old parse is never stored under the new
|
|
31
|
+
* file's fingerprint); and a read that resolves to the empty store while
|
|
32
|
+
* bytes still exist on disk — exhausted EBUSY/EPERM retries or corrupt
|
|
33
|
+
* JSON both surface as `emptyStore()` from the loaders — is served but
|
|
34
|
+
* never cached, so a transient failure cannot hide a real policy for the
|
|
35
|
+
* full TTL.
|
|
36
|
+
*
|
|
37
|
+
* - Project resolution (`findProjectRoot` + `resolveProjectStorageIdentityRoot`
|
|
38
|
+
* + `getProjectStorageKey`) is cached per resolved startDir for
|
|
39
|
+
* `PROJECT_RESOLUTION_TTL_MS` and guarded by two fingerprints: an
|
|
40
|
+
* mtime/ctime/size fingerprint of the resolved root's `.git` entry — the file
|
|
41
|
+
* whose contents drive worktree identity resolution — and the joined
|
|
42
|
+
* fingerprints of every ancestor directory that could host a marker, whose
|
|
43
|
+
* mtimes change when a marker file is created or deleted. Entries
|
|
44
|
+
* therefore invalidate when the project context differs (different
|
|
45
|
+
* startDir key, different resolved root), when the `.git` entry changes,
|
|
46
|
+
* or when a marker appears/disappears in a watched ancestor — the TTL is
|
|
47
|
+
* only the residual bound for coarse-mtime filesystems that report no
|
|
48
|
+
* change at all.
|
|
49
|
+
*
|
|
50
|
+
* Values held in the caches are shared, mutable objects. Callers must treat
|
|
51
|
+
* returned values as read-only; `loadRuntimePolicyState` clones what it hands
|
|
52
|
+
* out.
|
|
53
|
+
*/
|
|
54
|
+
import { type AccountPolicyStore } from "../account-policy.js";
|
|
55
|
+
import { type BudgetGuardStore } from "../budget-guard.js";
|
|
56
|
+
import { type ProjectRoutingProfileContext } from "../routing-profiles.js";
|
|
57
|
+
/**
|
|
58
|
+
* Cached variant of `loadAccountPolicyStore`. The returned store is shared
|
|
59
|
+
* cache state — treat as read-only.
|
|
60
|
+
*/
|
|
61
|
+
export declare function loadAccountPolicyStoreCached(): Promise<AccountPolicyStore>;
|
|
62
|
+
/**
|
|
63
|
+
* Cached variant of `loadBudgetGuardStore`. The returned store is shared
|
|
64
|
+
* cache state — treat as read-only.
|
|
65
|
+
*/
|
|
66
|
+
export declare function loadBudgetGuardStoreCached(): Promise<BudgetGuardStore>;
|
|
67
|
+
/**
|
|
68
|
+
* Cached variant of `resolveProjectRoutingProfile` for the per-request path.
|
|
69
|
+
* The project context (root/identity/key) comes from the bounded resolution
|
|
70
|
+
* cache; the profile itself is re-derived on every call from the
|
|
71
|
+
* fingerprint-guarded routing-profiles store, so profile edits are picked up
|
|
72
|
+
* as soon as the file's mtime/size changes and distinct project contexts can
|
|
73
|
+
* never observe each other's entries.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveProjectRoutingProfileCached(startDir?: string): Promise<ProjectRoutingProfileContext>;
|
|
76
|
+
/**
|
|
77
|
+
* Test-only: drop every cached store value and project resolution so each
|
|
78
|
+
* test starts from a clean read-from-disk state.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resetRuntimePolicyCacheForTests(): void;
|