codex-multi-auth 2.3.0-beta.0 → 2.3.0-beta.2
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 +4 -3
- package/config/schema/config.schema.json +268 -21
- package/dist/index.js +0 -1
- package/dist/lib/account-policy.js +0 -1
- package/dist/lib/accounts/rate-limits.js +0 -1
- package/dist/lib/accounts.d.ts +3 -8
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +2 -3
- package/dist/lib/audit.js +0 -1
- package/dist/lib/auth/auth.js +0 -1
- package/dist/lib/auth/browser.js +0 -1
- package/dist/lib/auth/device-auth.js +0 -1
- package/dist/lib/auth/index.js +0 -1
- package/dist/lib/auth/org-override.js +0 -1
- package/dist/lib/auth/server.js +0 -1
- package/dist/lib/auth/token-utils.js +0 -1
- package/dist/lib/auth-rate-limit.js +0 -1
- package/dist/lib/budget-guard.js +0 -1
- package/dist/lib/capability-policy.js +0 -1
- package/dist/lib/circuit-breaker.js +0 -1
- package/dist/lib/cli.js +1 -2
- package/dist/lib/codex-cli/index.js +0 -1
- package/dist/lib/codex-cli/observability.js +0 -1
- package/dist/lib/codex-cli/state.js +0 -1
- package/dist/lib/codex-cli/sync.d.ts +2 -2
- package/dist/lib/codex-cli/sync.d.ts.map +1 -1
- package/dist/lib/codex-cli/sync.js +1 -2
- package/dist/lib/codex-cli/writer.js +0 -1
- package/dist/lib/codex-manager/account-credentials.d.ts +13 -0
- package/dist/lib/codex-manager/account-credentials.d.ts.map +1 -0
- package/dist/lib/codex-manager/account-credentials.js +55 -0
- package/dist/lib/codex-manager/account-manager-commands.js +0 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts +95 -0
- package/dist/lib/codex-manager/account-pool-write.d.ts.map +1 -0
- package/dist/lib/codex-manager/account-pool-write.js +165 -0
- package/dist/lib/codex-manager/account-pool-write.js.map +1 -0
- package/dist/lib/codex-manager/backend-category-entry.js +0 -1
- package/dist/lib/codex-manager/backend-category-helpers.js +0 -1
- package/dist/lib/codex-manager/backend-category-prompt.js +0 -1
- package/dist/lib/codex-manager/backend-settings-controller.js +0 -1
- package/dist/lib/codex-manager/backend-settings-entry.js +0 -1
- package/dist/lib/codex-manager/backend-settings-helpers.js +0 -1
- package/dist/lib/codex-manager/backend-settings-prompt.js +0 -1
- package/dist/lib/codex-manager/backend-settings-schema.js +0 -1
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts +1 -1
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/behavior-settings-panel.js +0 -1
- package/dist/lib/codex-manager/commands/account.js +0 -1
- package/dist/lib/codex-manager/commands/best.d.ts +8 -0
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +64 -1
- package/dist/lib/codex-manager/commands/bridge.js +0 -1
- package/dist/lib/codex-manager/commands/budget.js +0 -1
- package/dist/lib/codex-manager/commands/check.js +0 -1
- package/dist/lib/codex-manager/commands/config-explain.js +0 -1
- package/dist/lib/codex-manager/commands/debug-bundle.js +0 -1
- package/dist/lib/codex-manager/commands/forecast.js +0 -1
- package/dist/lib/codex-manager/commands/init-config.js +0 -1
- package/dist/lib/codex-manager/commands/integrations.js +0 -1
- package/dist/lib/codex-manager/commands/models.js +0 -1
- package/dist/lib/codex-manager/commands/monitor.js +0 -1
- package/dist/lib/codex-manager/commands/report.js +0 -1
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/rotation.js +1 -4
- package/dist/lib/codex-manager/commands/status.js +0 -1
- package/dist/lib/codex-manager/commands/switch.js +0 -1
- package/dist/lib/codex-manager/commands/uninstall.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/uninstall.js +2 -33
- package/dist/lib/codex-manager/commands/unpin.js +0 -1
- package/dist/lib/codex-manager/commands/usage.js +0 -1
- package/dist/lib/codex-manager/commands/verify.js +0 -1
- package/dist/lib/codex-manager/commands/why-selected.js +0 -1
- package/dist/lib/codex-manager/commands/workspace.js +0 -1
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts +1 -1
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/dashboard-display-panel.js +0 -1
- package/dist/lib/codex-manager/dashboard-formatters.js +0 -1
- package/dist/lib/codex-manager/dashboard-settings-controller.js +0 -1
- package/dist/lib/codex-manager/dashboard-settings-data.js +0 -1
- package/dist/lib/codex-manager/dashboard-settings-entry.js +0 -1
- package/dist/lib/codex-manager/experimental-settings-entry.js +0 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.js +0 -1
- package/dist/lib/codex-manager/experimental-settings-schema.js +1 -2
- package/dist/lib/codex-manager/experimental-sync-target-entry.js +0 -1
- package/dist/lib/codex-manager/experimental-sync-target.js +0 -1
- package/dist/lib/codex-manager/forecast-report-commands.js +0 -1
- package/dist/lib/codex-manager/forecast-report-shared.d.ts +2 -2
- package/dist/lib/codex-manager/forecast-report-shared.d.ts.map +1 -1
- package/dist/lib/codex-manager/forecast-report-shared.js +5 -21
- package/dist/lib/codex-manager/formatters/account-formatters.d.ts +11 -0
- package/dist/lib/codex-manager/formatters/account-formatters.d.ts.map +1 -0
- package/dist/lib/codex-manager/formatters/account-formatters.js +79 -0
- package/dist/lib/codex-manager/formatters/index.d.ts +5 -0
- package/dist/lib/codex-manager/formatters/index.d.ts.map +1 -0
- package/dist/lib/codex-manager/formatters/index.js +4 -0
- package/dist/lib/codex-manager/formatters/model-formatters.d.ts +12 -0
- package/dist/lib/codex-manager/formatters/model-formatters.d.ts.map +1 -0
- package/dist/lib/codex-manager/formatters/model-formatters.js +23 -0
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts +11 -0
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -0
- package/dist/lib/codex-manager/formatters/quota-formatters.js +104 -0
- package/dist/lib/codex-manager/formatters/text-style.d.ts +14 -0
- package/dist/lib/codex-manager/formatters/text-style.d.ts.map +1 -0
- package/dist/lib/codex-manager/formatters/text-style.js +111 -0
- package/dist/lib/codex-manager/health-check.d.ts +14 -0
- package/dist/lib/codex-manager/health-check.d.ts.map +1 -0
- package/dist/lib/codex-manager/health-check.js +278 -0
- package/dist/lib/codex-manager/help.js +0 -1
- package/dist/lib/codex-manager/login-action-panel.d.ts +4 -0
- package/dist/lib/codex-manager/login-action-panel.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-action-panel.js +238 -0
- package/dist/lib/codex-manager/login-flow.d.ts +17 -0
- package/dist/lib/codex-manager/login-flow.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-flow.js +387 -0
- package/dist/lib/codex-manager/login-menu-actions.d.ts +20 -0
- package/dist/lib/codex-manager/login-menu-actions.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-menu-actions.js +303 -0
- package/dist/lib/codex-manager/login-menu-data.d.ts +19 -0
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-menu-data.js +378 -0
- package/dist/lib/codex-manager/login-oauth.d.ts +55 -0
- package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-oauth.js +345 -0
- package/dist/lib/codex-manager/manual-callback.d.ts +33 -0
- package/dist/lib/codex-manager/manual-callback.d.ts.map +1 -0
- package/dist/lib/codex-manager/manual-callback.js +30 -0
- package/dist/lib/codex-manager/manual-callback.js.map +1 -0
- package/dist/lib/codex-manager/persist-selected-account.d.ts +24 -0
- package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -0
- package/dist/lib/codex-manager/persist-selected-account.js +107 -0
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts +18 -0
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -0
- package/dist/lib/codex-manager/quota-cache-helpers.js +112 -0
- package/dist/lib/codex-manager/rate-limit-markers.js +0 -1
- package/dist/lib/codex-manager/repair-commands.js +0 -1
- package/dist/lib/codex-manager/settings-hub/backend.js +1 -2
- package/dist/lib/codex-manager/settings-hub/dashboard.js +1 -2
- package/dist/lib/codex-manager/settings-hub/experimental.js +1 -2
- package/dist/lib/codex-manager/settings-hub/index.js +1 -2
- package/dist/lib/codex-manager/settings-hub/shared.js +0 -1
- package/dist/lib/codex-manager/settings-hub-entry.js +0 -1
- package/dist/lib/codex-manager/settings-hub-menu.js +0 -1
- package/dist/lib/codex-manager/settings-hub-prompt.js +0 -1
- package/dist/lib/codex-manager/settings-hub.js +0 -1
- package/dist/lib/codex-manager/settings-panels.js +0 -1
- package/dist/lib/codex-manager/settings-persist-utils.js +0 -1
- package/dist/lib/codex-manager/settings-preview.js +0 -1
- package/dist/lib/codex-manager/settings-write-queue.js +0 -1
- package/dist/lib/codex-manager/statusline-order.js +0 -1
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts +1 -1
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/statusline-settings-panel.js +0 -1
- package/dist/lib/codex-manager/theme-settings-panel.d.ts +1 -1
- package/dist/lib/codex-manager/theme-settings-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/theme-settings-panel.js +0 -1
- package/dist/lib/codex-manager/unified-settings-controller.js +0 -1
- package/dist/lib/codex-manager/unified-settings-entry.js +0 -1
- package/dist/lib/codex-manager.d.ts +2 -4
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +219 -2578
- package/dist/lib/codex-manager.js.map +1 -1
- package/dist/lib/config-schema.d.ts +32 -0
- package/dist/lib/config-schema.d.ts.map +1 -0
- package/dist/lib/config-schema.js +96 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +60 -104
- package/dist/lib/constants.js +0 -1
- package/dist/lib/context-overflow.js +0 -1
- package/dist/lib/dashboard-settings.js +0 -1
- package/dist/lib/entitlement-cache.js +0 -1
- package/dist/lib/env-parsing.js +0 -1
- package/dist/lib/errors.js +0 -1
- package/dist/lib/forecast.js +0 -1
- package/dist/lib/fs-retry.d.ts +46 -0
- package/dist/lib/fs-retry.d.ts.map +1 -1
- package/dist/lib/fs-retry.js +74 -6
- package/dist/lib/health.js +0 -1
- package/dist/lib/index.js +0 -1
- package/dist/lib/integration-generators.js +0 -1
- package/dist/lib/live-account-sync.js +0 -1
- package/dist/lib/local-bridge.js +0 -1
- package/dist/lib/local-client-tokens.js +0 -1
- package/dist/lib/logger.js +0 -1
- package/dist/lib/model-capability-matrix.js +0 -1
- package/dist/lib/named-backup-export.js +0 -1
- package/dist/lib/oc-chatgpt-import-adapter.js +0 -1
- package/dist/lib/oc-chatgpt-orchestrator.js +0 -1
- package/dist/lib/oc-chatgpt-target-detection.js +0 -1
- package/dist/lib/parallel-probe.js +0 -1
- package/dist/lib/policy/runtime-policy.js +0 -1
- package/dist/lib/preemptive-quota-scheduler.js +0 -1
- package/dist/lib/proactive-refresh.js +0 -1
- package/dist/lib/prompts/codex-host-bridge.js +0 -1
- package/dist/lib/prompts/codex.d.ts +3 -11
- package/dist/lib/prompts/codex.d.ts.map +1 -1
- package/dist/lib/prompts/codex.js +4 -12
- package/dist/lib/prompts/fetch-utils.js +0 -1
- package/dist/lib/prompts/host-codex-prompt.js +0 -1
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +15 -43
- package/dist/lib/quota-probe.js +0 -1
- package/dist/lib/quota-readiness.js +0 -1
- package/dist/lib/recovery/constants.js +0 -1
- package/dist/lib/recovery/index.js +0 -1
- package/dist/lib/recovery/storage.d.ts.map +1 -1
- package/dist/lib/recovery/storage.js +30 -51
- package/dist/lib/recovery/storage.js.map +1 -1
- package/dist/lib/recovery/types.js +0 -1
- package/dist/lib/recovery.js +0 -1
- package/dist/lib/refresh-guardian.js +0 -1
- package/dist/lib/refresh-lease.d.ts.map +1 -1
- package/dist/lib/refresh-lease.js +1 -4
- package/dist/lib/refresh-queue.js +0 -1
- package/dist/lib/request/error-classification.d.ts +75 -0
- package/dist/lib/request/error-classification.d.ts.map +1 -0
- package/dist/lib/request/error-classification.js +295 -0
- package/dist/lib/request/failover-config.js +0 -1
- package/dist/lib/request/failure-policy.js +0 -1
- package/dist/lib/request/fetch-helpers.d.ts +10 -114
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
- package/dist/lib/request/fetch-helpers.js +7 -589
- package/dist/lib/request/headers.d.ts +33 -0
- package/dist/lib/request/headers.d.ts.map +1 -0
- package/dist/lib/request/headers.js +64 -0
- package/dist/lib/request/helpers/input-utils.js +0 -1
- package/dist/lib/request/helpers/model-map.d.ts +10 -0
- package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
- package/dist/lib/request/helpers/model-map.js +11 -1
- package/dist/lib/request/helpers/tool-utils.js +0 -1
- package/dist/lib/request/index.js +0 -1
- package/dist/lib/request/rate-limit-backoff.js +0 -1
- package/dist/lib/request/rate-limit-decision.d.ts +28 -0
- package/dist/lib/request/rate-limit-decision.d.ts.map +1 -0
- package/dist/lib/request/rate-limit-decision.js +191 -0
- package/dist/lib/request/request-attempt-budget.js +0 -1
- package/dist/lib/request/request-init.js +0 -1
- package/dist/lib/request/request-resilience.js +0 -1
- package/dist/lib/request/request-transformer.js +0 -1
- package/dist/lib/request/response-compaction.js +0 -1
- package/dist/lib/request/response-handler.js +0 -1
- package/dist/lib/request/response-metadata.js +0 -1
- package/dist/lib/request/stream-failover-runtime.d.ts +8 -0
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -0
- package/dist/lib/request/stream-failover-runtime.js +149 -0
- package/dist/lib/request/stream-failover.js +0 -1
- package/dist/lib/request/token-refresh.d.ts +30 -0
- package/dist/lib/request/token-refresh.d.ts.map +1 -0
- package/dist/lib/request/token-refresh.js +116 -0
- package/dist/lib/request/url-rewriting.d.ts +24 -0
- package/dist/lib/request/url-rewriting.d.ts.map +1 -0
- package/dist/lib/request/url-rewriting.js +153 -0
- package/dist/lib/request/wait-utils.js +0 -1
- package/dist/lib/rotation.d.ts +1 -1
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +0 -1
- package/dist/lib/routing-mutex.js +0 -1
- package/dist/lib/routing-profiles.js +0 -1
- package/dist/lib/runtime/account-check-helpers.js +0 -1
- package/dist/lib/runtime/account-check-types.js +0 -1
- package/dist/lib/runtime/account-check.js +0 -1
- package/dist/lib/runtime/account-health-check.js +0 -1
- package/dist/lib/runtime/account-manager-cache-entry.js +0 -1
- package/dist/lib/runtime/account-manager-cache.js +0 -1
- package/dist/lib/runtime/account-pool.js +0 -1
- package/dist/lib/runtime/account-scope.js +0 -1
- package/dist/lib/runtime/account-select-event.js +0 -1
- package/dist/lib/runtime/account-selection.js +0 -1
- package/dist/lib/runtime/account-state.js +0 -1
- package/dist/lib/runtime/account-status.js +0 -1
- package/dist/lib/runtime/account-storage-scope-entry.js +0 -1
- package/dist/lib/runtime/app-bind.js +0 -1
- package/dist/lib/runtime/auth-facade.js +0 -1
- package/dist/lib/runtime/browser-oauth-flow.js +0 -1
- package/dist/lib/runtime/capability-boost.js +0 -1
- package/dist/lib/runtime/config-toml.js +0 -1
- package/dist/lib/runtime/event-handler.js +0 -1
- package/dist/lib/runtime/first-run.d.ts +80 -0
- package/dist/lib/runtime/first-run.d.ts.map +1 -0
- package/dist/lib/runtime/first-run.js +327 -0
- package/dist/lib/runtime/flagged-verify-types.js +0 -1
- package/dist/lib/runtime/hydrate-emails.js +0 -1
- package/dist/lib/runtime/live-sync-entry.js +0 -1
- package/dist/lib/runtime/live-sync.js +0 -1
- package/dist/lib/runtime/loader-setup.js +0 -1
- package/dist/lib/runtime/login-menu-accounts.js +0 -1
- package/dist/lib/runtime/manual-oauth-flow.js +0 -1
- package/dist/lib/runtime/oauth-browser-flow.js +0 -1
- package/dist/lib/runtime/preemptive-quota.js +0 -1
- package/dist/lib/runtime/quota-headers.js +0 -1
- package/dist/lib/runtime/quota-probe.js +0 -1
- package/dist/lib/runtime/quota-settings.js +0 -1
- package/dist/lib/runtime/refresh-guardian-entry.js +0 -1
- package/dist/lib/runtime/refresh-guardian.js +0 -1
- package/dist/lib/runtime/request-init.js +0 -1
- package/dist/lib/runtime/rotation-account-selection.d.ts +38 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -0
- package/dist/lib/runtime/rotation-account-selection.js +172 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts +54 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -0
- package/dist/lib/runtime/rotation-proxy-state.js +56 -0
- package/dist/lib/runtime/rotation-server-types.d.ts +57 -0
- package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -0
- package/dist/lib/runtime/rotation-server-types.js +1 -0
- package/dist/lib/runtime/rotation-storage-meta.d.ts +40 -0
- package/dist/lib/runtime/rotation-storage-meta.d.ts.map +1 -0
- package/dist/lib/runtime/rotation-storage-meta.js +143 -0
- package/dist/lib/runtime/rotation-token-refresh.d.ts +25 -0
- package/dist/lib/runtime/rotation-token-refresh.d.ts.map +1 -0
- package/dist/lib/runtime/rotation-token-refresh.js +99 -0
- package/dist/lib/runtime/runtime-current-account.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-current-account.js +1 -4
- package/dist/lib/runtime/runtime-observability.js +0 -1
- package/dist/lib/runtime/runtime-services.js +0 -1
- package/dist/lib/runtime/session-affinity-entry.js +0 -1
- package/dist/lib/runtime/session-affinity.js +0 -1
- package/dist/lib/runtime/session-recovery.js +0 -1
- package/dist/lib/runtime/status-marker.js +0 -1
- package/dist/lib/runtime/storage-scope.js +0 -1
- package/dist/lib/runtime/toast.js +0 -1
- package/dist/lib/runtime/ui-runtime-entry.js +0 -1
- package/dist/lib/runtime/ui-runtime.js +0 -1
- package/dist/lib/runtime/verify-flagged.js +0 -1
- package/dist/lib/runtime-constants.js +0 -1
- package/dist/lib/runtime-paths.js +0 -1
- package/dist/lib/runtime-rotation-proxy.d.ts +7 -124
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +614 -1353
- package/dist/lib/schemas.d.ts +3 -3
- package/dist/lib/schemas.js +1 -2
- package/dist/lib/session-affinity.js +0 -1
- package/dist/lib/shutdown.js +0 -1
- package/dist/lib/storage/account-clear-entry.js +0 -1
- package/dist/lib/storage/account-clear.js +0 -1
- package/dist/lib/storage/account-match-utils.js +0 -1
- package/dist/lib/storage/account-persistence.d.ts +1 -1
- package/dist/lib/storage/account-persistence.d.ts.map +1 -1
- package/dist/lib/storage/account-persistence.js +0 -1
- package/dist/lib/storage/account-port.d.ts +1 -1
- package/dist/lib/storage/account-port.d.ts.map +1 -1
- package/dist/lib/storage/account-port.js +0 -1
- package/dist/lib/storage/account-save-entry.d.ts +1 -1
- package/dist/lib/storage/account-save-entry.d.ts.map +1 -1
- package/dist/lib/storage/account-save-entry.js +0 -1
- package/dist/lib/storage/account-save.d.ts +1 -1
- package/dist/lib/storage/account-save.d.ts.map +1 -1
- package/dist/lib/storage/account-save.js +0 -1
- package/dist/lib/storage/account-snapshot.js +0 -1
- package/dist/lib/storage/backup-metadata-builder.d.ts +1 -1
- package/dist/lib/storage/backup-metadata-builder.d.ts.map +1 -1
- package/dist/lib/storage/backup-metadata-builder.js +0 -1
- package/dist/lib/storage/backup-metadata.d.ts +13 -0
- package/dist/lib/storage/backup-metadata.d.ts.map +1 -1
- package/dist/lib/storage/backup-metadata.js +0 -1
- package/dist/lib/storage/backup-paths.js +0 -1
- package/dist/lib/storage/backup-restore.d.ts +1 -1
- package/dist/lib/storage/backup-restore.d.ts.map +1 -1
- package/dist/lib/storage/backup-restore.js +0 -1
- package/dist/lib/storage/cache-artifacts.js +0 -1
- package/dist/lib/storage/error-hints.js +0 -1
- package/dist/lib/storage/file-paths.js +0 -1
- package/dist/lib/storage/fixture-guards.d.ts +1 -1
- package/dist/lib/storage/fixture-guards.d.ts.map +1 -1
- package/dist/lib/storage/fixture-guards.js +0 -1
- package/dist/lib/storage/flagged-entry.js +0 -1
- package/dist/lib/storage/flagged-load-entry.d.ts +1 -1
- package/dist/lib/storage/flagged-load-entry.d.ts.map +1 -1
- package/dist/lib/storage/flagged-load-entry.js +0 -1
- package/dist/lib/storage/flagged-save-entry.d.ts +1 -1
- package/dist/lib/storage/flagged-save-entry.d.ts.map +1 -1
- package/dist/lib/storage/flagged-save-entry.js +0 -1
- package/dist/lib/storage/flagged-storage-file.d.ts +1 -1
- package/dist/lib/storage/flagged-storage-file.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage-file.js +0 -1
- package/dist/lib/storage/flagged-storage-io.d.ts +1 -1
- package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage-io.js +0 -1
- package/dist/lib/storage/flagged-storage.d.ts +1 -1
- package/dist/lib/storage/flagged-storage.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage.js +15 -2
- package/dist/lib/storage/flagged-storage.js.map +1 -1
- package/dist/lib/storage/gitignore.js +0 -1
- package/dist/lib/storage/hash.js +0 -1
- package/dist/lib/storage/health.js +0 -1
- package/dist/lib/storage/identity.js +0 -1
- package/dist/lib/storage/import-export.d.ts +1 -1
- package/dist/lib/storage/import-export.d.ts.map +1 -1
- package/dist/lib/storage/import-export.js +0 -1
- package/dist/lib/storage/metadata-section.js +0 -1
- package/dist/lib/storage/migrations.d.ts +5 -48
- package/dist/lib/storage/migrations.d.ts.map +1 -1
- package/dist/lib/storage/migrations.js +5 -2
- package/dist/lib/storage/named-backup-entry.js +0 -1
- package/dist/lib/storage/named-backups-entry.d.ts +1 -1
- package/dist/lib/storage/named-backups-entry.d.ts.map +1 -1
- package/dist/lib/storage/named-backups-entry.js +0 -1
- package/dist/lib/storage/named-backups.js +0 -1
- package/dist/lib/storage/path-state.js +0 -1
- package/dist/lib/storage/paths.js +0 -1
- package/dist/lib/storage/project-migration.d.ts +1 -1
- package/dist/lib/storage/project-migration.d.ts.map +1 -1
- package/dist/lib/storage/project-migration.js +0 -1
- package/dist/lib/storage/public-types.d.ts +70 -0
- package/dist/lib/storage/public-types.d.ts.map +1 -0
- package/dist/lib/storage/public-types.js +6 -0
- package/dist/lib/storage/record-utils.js +0 -1
- package/dist/lib/storage/restore-assessment.d.ts +1 -1
- package/dist/lib/storage/restore-assessment.d.ts.map +1 -1
- package/dist/lib/storage/restore-assessment.js +0 -1
- package/dist/lib/storage/restore-backup-entry.d.ts +1 -1
- package/dist/lib/storage/restore-backup-entry.d.ts.map +1 -1
- package/dist/lib/storage/restore-backup-entry.js +0 -1
- package/dist/lib/storage/restore-metadata.d.ts +1 -1
- package/dist/lib/storage/restore-metadata.d.ts.map +1 -1
- package/dist/lib/storage/restore-metadata.js +0 -1
- package/dist/lib/storage/restore.d.ts +1 -1
- package/dist/lib/storage/restore.d.ts.map +1 -1
- package/dist/lib/storage/restore.js +0 -1
- package/dist/lib/storage/save-retry.d.ts +10 -0
- package/dist/lib/storage/save-retry.d.ts.map +1 -0
- package/dist/lib/storage/save-retry.js +26 -0
- package/dist/lib/storage/snapshot-inspectors.d.ts +1 -1
- package/dist/lib/storage/snapshot-inspectors.d.ts.map +1 -1
- package/dist/lib/storage/snapshot-inspectors.js +0 -1
- package/dist/lib/storage/storage-parser.d.ts +1 -1
- package/dist/lib/storage/storage-parser.d.ts.map +1 -1
- package/dist/lib/storage/storage-parser.js +0 -1
- package/dist/lib/storage/transactions.d.ts +1 -1
- package/dist/lib/storage/transactions.d.ts.map +1 -1
- package/dist/lib/storage/transactions.js +0 -1
- package/dist/lib/storage.d.ts +3 -24
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +17 -32
- package/dist/lib/table-formatter.js +0 -1
- package/dist/lib/tools/hashline-tools.js +0 -1
- package/dist/lib/types.js +0 -1
- package/dist/lib/ui/ansi.js +0 -1
- package/dist/lib/ui/auth-menu-builder.d.ts +89 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -0
- package/dist/lib/ui/auth-menu-builder.js +350 -0
- package/dist/lib/ui/auth-menu.d.ts +2 -76
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +3 -349
- package/dist/lib/ui/confirm.js +0 -1
- package/dist/lib/ui/copy.d.ts +2 -0
- package/dist/lib/ui/copy.d.ts.map +1 -1
- package/dist/lib/ui/copy.js +2 -0
- package/dist/lib/ui/copy.js.map +1 -1
- package/dist/lib/ui/display-width.js +0 -1
- package/dist/lib/ui/format.js +0 -1
- package/dist/lib/ui/index.d.ts +10 -0
- package/dist/lib/ui/index.d.ts.map +1 -0
- package/dist/lib/ui/index.js +9 -0
- package/dist/lib/ui/runtime.js +0 -1
- package/dist/lib/ui/select.js +0 -1
- package/dist/lib/ui/theme.js +0 -1
- package/dist/lib/ui/ui-copy.d.ts +159 -0
- package/dist/lib/ui/ui-copy.d.ts.map +1 -0
- package/dist/lib/ui/ui-copy.js +163 -0
- package/dist/lib/unified-settings.js +0 -1
- package/dist/lib/update-notice.js +0 -1
- package/dist/lib/usage/index.js +0 -1
- package/dist/lib/usage/ledger.js +0 -1
- package/dist/lib/usage/pricing.js +0 -1
- package/dist/lib/usage/redaction.js +0 -1
- package/dist/lib/usage/types.js +0 -1
- package/dist/lib/utils.js +0 -1
- package/package.json +8 -8
- package/scripts/postinstall.js +34 -265
- package/scripts/preuninstall.js +2 -2
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
// Lazy first-run setup (audit roadmap §4.5.4).
|
|
2
|
+
//
|
|
3
|
+
// The npm postinstall script used to detect the packaged Codex desktop app,
|
|
4
|
+
// auto-bind runtime rotation, and install OS launcher shortcuts. That work now
|
|
5
|
+
// runs here, on the first CLI invocation, so package installs stay
|
|
6
|
+
// side-effect-free. The hook is guarded by a marker file under the runtime
|
|
7
|
+
// root (~/.codex/multi-auth), claimed with an exclusive create so concurrent
|
|
8
|
+
// first invocations run the setup at most once, and every step is best-effort:
|
|
9
|
+
// a failure is debug-logged (messages only — never tokens or emails) and the
|
|
10
|
+
// command proceeds normally.
|
|
11
|
+
import { randomBytes } from "node:crypto";
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { open, rename, unlink } from "node:fs/promises";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
16
|
+
import process from "node:process";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import { getCodexRuntimeRotationProxy, loadPluginConfig } from "../config.js";
|
|
19
|
+
import { withFileOperationRetry } from "../fs-retry.js";
|
|
20
|
+
import { createLogger } from "../logger.js";
|
|
21
|
+
import { getCodexMultiAuthDir } from "../runtime-paths.js";
|
|
22
|
+
import { bindCodexAppRuntimeRotation, getAppBindStatus } from "./app-bind.js";
|
|
23
|
+
const log = createLogger("first-run");
|
|
24
|
+
const FIRST_RUN_MARKER_FILE = "first-run-setup.json";
|
|
25
|
+
export const FIRST_RUN_MARKER_VERSION = 1;
|
|
26
|
+
const TRUE_VALUES = new Set(["1", "true", "yes"]);
|
|
27
|
+
const FALSE_VALUES = new Set(["0", "false", "no"]);
|
|
28
|
+
const CI_ENV_KEYS = [
|
|
29
|
+
"CI",
|
|
30
|
+
"GITHUB_ACTIONS",
|
|
31
|
+
"GITLAB_CI",
|
|
32
|
+
"CIRCLECI",
|
|
33
|
+
"BUILDKITE",
|
|
34
|
+
"TF_BUILD",
|
|
35
|
+
"TEAMCITY_VERSION",
|
|
36
|
+
"JENKINS_URL",
|
|
37
|
+
"TRAVIS",
|
|
38
|
+
"APPVEYOR",
|
|
39
|
+
"BITBUCKET_BUILD_NUMBER",
|
|
40
|
+
];
|
|
41
|
+
export function readOptionalBoolean(value) {
|
|
42
|
+
if (value === undefined || value.trim().length === 0)
|
|
43
|
+
return null;
|
|
44
|
+
const normalized = value.trim().toLowerCase();
|
|
45
|
+
if (TRUE_VALUES.has(normalized))
|
|
46
|
+
return true;
|
|
47
|
+
if (FALSE_VALUES.has(normalized))
|
|
48
|
+
return false;
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function isEnabledEnvFlag(env, key) {
|
|
52
|
+
const value = env[key];
|
|
53
|
+
if (value === undefined || value.trim().length === 0)
|
|
54
|
+
return false;
|
|
55
|
+
return readOptionalBoolean(value) !== false;
|
|
56
|
+
}
|
|
57
|
+
export function isCiEnvironment(env = process.env) {
|
|
58
|
+
if (readOptionalBoolean(env.npm_config_ignore_scripts) === true)
|
|
59
|
+
return true;
|
|
60
|
+
return CI_ENV_KEYS.some((key) => isEnabledEnvFlag(env, key));
|
|
61
|
+
}
|
|
62
|
+
function directoryContainsEntryWithPrefix(directory, prefix) {
|
|
63
|
+
try {
|
|
64
|
+
return readdirSync(directory, { withFileTypes: true }).some((entry) => entry.name.startsWith(prefix));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function hasCodexDesktopApp(options = {}) {
|
|
71
|
+
const env = options.env ?? process.env;
|
|
72
|
+
const platform = options.platform ?? process.platform;
|
|
73
|
+
const home = options.home ?? homedir();
|
|
74
|
+
if (platform === "win32") {
|
|
75
|
+
const localAppData = (env.LOCALAPPDATA ?? "").trim() || join(home, "AppData", "Local");
|
|
76
|
+
const programFiles = (env.ProgramFiles ?? env.ProgramW6432 ?? "").trim() || "C:\\Program Files";
|
|
77
|
+
return (directoryContainsEntryWithPrefix(join(localAppData, "Packages"), "OpenAI.Codex_") ||
|
|
78
|
+
directoryContainsEntryWithPrefix(join(programFiles, "WindowsApps"), "OpenAI.Codex_"));
|
|
79
|
+
}
|
|
80
|
+
if (platform === "darwin") {
|
|
81
|
+
return (existsSync("/Applications/Codex.app") ||
|
|
82
|
+
existsSync(join(home, "Applications", "Codex.app")));
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
export function resolveRotationEnabled(env = process.env, readConfigRotation = () => getCodexRuntimeRotationProxy(loadPluginConfig()) === true) {
|
|
87
|
+
const envOverride = readOptionalBoolean(env.CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY);
|
|
88
|
+
if (envOverride !== null)
|
|
89
|
+
return envOverride;
|
|
90
|
+
try {
|
|
91
|
+
return readConfigRotation();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Rotation defaults on; a malformed config must not block first-run setup.
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function shouldBindCodexAppOnFirstRun(options) {
|
|
99
|
+
const env = options.env ?? process.env;
|
|
100
|
+
if (isCiEnvironment(env))
|
|
101
|
+
return false;
|
|
102
|
+
const bindOverride = readOptionalBoolean(env.CODEX_MULTI_AUTH_APP_BIND);
|
|
103
|
+
if (bindOverride !== null)
|
|
104
|
+
return bindOverride;
|
|
105
|
+
const installOverride = readOptionalBoolean(env.CODEX_MULTI_AUTH_APP_BIND_INSTALL);
|
|
106
|
+
if (installOverride !== null)
|
|
107
|
+
return installOverride;
|
|
108
|
+
if (!options.rotationEnabled)
|
|
109
|
+
return false;
|
|
110
|
+
return options.appDetected;
|
|
111
|
+
}
|
|
112
|
+
export function shouldInstallCodexAppLauncherOnFirstRun(options) {
|
|
113
|
+
const env = options.env ?? process.env;
|
|
114
|
+
if (isCiEnvironment(env))
|
|
115
|
+
return false;
|
|
116
|
+
const installOverride = readOptionalBoolean(env.CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL);
|
|
117
|
+
if (installOverride !== null)
|
|
118
|
+
return installOverride;
|
|
119
|
+
return options.rotationEnabled;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* First-run setup only fires for a durable, global-style install. The old
|
|
123
|
+
* postinstall gate was `npm_config_global`, which does not exist at CLI
|
|
124
|
+
* runtime, so this approximates it from the module location instead:
|
|
125
|
+
*
|
|
126
|
+
* - must live under a `node_modules` segment (a dev checkout or the test
|
|
127
|
+
* suite runs straight from the repository tree and stays side-effect-free)
|
|
128
|
+
* - must NOT be an npx cache run (`.../_npx/<hash>/node_modules/...`):
|
|
129
|
+
* someone trying the tool once must not get app bind/launcher mutations,
|
|
130
|
+
* and must not burn the once-only marker before a real install
|
|
131
|
+
* - must NOT be a project-local install (module path inside the invoking
|
|
132
|
+
* working directory): `npm install` into an app's node_modules is not a
|
|
133
|
+
* machine-level install either
|
|
134
|
+
*/
|
|
135
|
+
export function isInstalledPackageContext(modulePath = fileURLToPath(import.meta.url), cwd = process.cwd()) {
|
|
136
|
+
const segments = modulePath.split(sep);
|
|
137
|
+
if (!segments.includes("node_modules"))
|
|
138
|
+
return false;
|
|
139
|
+
if (segments.includes("_npx"))
|
|
140
|
+
return false;
|
|
141
|
+
const fromCwd = relative(cwd, modulePath);
|
|
142
|
+
if (fromCwd && !fromCwd.startsWith("..") && !isAbsolute(fromCwd)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
export function getFirstRunMarkerPath() {
|
|
148
|
+
return join(getCodexMultiAuthDir(), FIRST_RUN_MARKER_FILE);
|
|
149
|
+
}
|
|
150
|
+
function errorMessage(error) {
|
|
151
|
+
return error instanceof Error ? error.message : String(error);
|
|
152
|
+
}
|
|
153
|
+
function isErrnoCode(error, code) {
|
|
154
|
+
return (error instanceof Error &&
|
|
155
|
+
"code" in error &&
|
|
156
|
+
error.code === code);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Claims the marker with an exclusive create so that, across processes, at
|
|
160
|
+
* most one first invocation runs the setup. Returns false when another
|
|
161
|
+
* process already holds (or completed) the claim.
|
|
162
|
+
*/
|
|
163
|
+
function claimFirstRunMarker(markerPath, startedAt) {
|
|
164
|
+
mkdirSync(dirname(markerPath), { recursive: true });
|
|
165
|
+
const payload = `${JSON.stringify({ version: FIRST_RUN_MARKER_VERSION, startedAt }, null, "\t")}\n`;
|
|
166
|
+
try {
|
|
167
|
+
writeFileSync(markerPath, payload, { flag: "wx", mode: 0o600 });
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
if (isErrnoCode(error, "EEXIST"))
|
|
172
|
+
return false;
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function atomicWriteMarker(target, content) {
|
|
177
|
+
await withFileOperationRetry(async () => {
|
|
178
|
+
const tempPath = join(dirname(target), [
|
|
179
|
+
`.${basename(target)}`,
|
|
180
|
+
String(process.pid),
|
|
181
|
+
String(Date.now()),
|
|
182
|
+
randomBytes(4).toString("hex"),
|
|
183
|
+
"tmp",
|
|
184
|
+
].join("."));
|
|
185
|
+
let moved = false;
|
|
186
|
+
let handle = null;
|
|
187
|
+
try {
|
|
188
|
+
handle = await open(tempPath, "w", 0o600);
|
|
189
|
+
await handle.writeFile(content, "utf8");
|
|
190
|
+
await handle.sync();
|
|
191
|
+
await handle.close();
|
|
192
|
+
handle = null;
|
|
193
|
+
await rename(tempPath, target);
|
|
194
|
+
moved = true;
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await handle?.close().catch(() => undefined);
|
|
198
|
+
if (!moved) {
|
|
199
|
+
await unlink(tempPath).catch(() => undefined);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function finalizeFirstRunMarker(markerPath, startedAt, outcome, now) {
|
|
205
|
+
const payload = `${JSON.stringify({
|
|
206
|
+
version: FIRST_RUN_MARKER_VERSION,
|
|
207
|
+
startedAt,
|
|
208
|
+
completedAt: now(),
|
|
209
|
+
appBind: outcome.appBind,
|
|
210
|
+
launcher: outcome.launcher,
|
|
211
|
+
}, null, "\t")}\n`;
|
|
212
|
+
try {
|
|
213
|
+
await atomicWriteMarker(markerPath, payload);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
// The claim file already guarantees once-only behavior; losing the
|
|
217
|
+
// completion details is acceptable.
|
|
218
|
+
log.debug("first-run marker finalize failed", {
|
|
219
|
+
error: errorMessage(error),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Resolves the launcher installer from the packaged scripts/ directory,
|
|
225
|
+
* trying the dist layout first and the source layout second.
|
|
226
|
+
*
|
|
227
|
+
* @internal `candidateOverride` exists only so tests can exercise the
|
|
228
|
+
* fallback order and failure modes with real temp files.
|
|
229
|
+
*/
|
|
230
|
+
export async function loadLauncherInstall(candidateOverride) {
|
|
231
|
+
const candidates = candidateOverride ?? [
|
|
232
|
+
fileURLToPath(new URL("../../../scripts/codex-app-launcher.js", import.meta.url)),
|
|
233
|
+
fileURLToPath(new URL("../../scripts/codex-app-launcher.js", import.meta.url)),
|
|
234
|
+
];
|
|
235
|
+
for (const candidate of candidates) {
|
|
236
|
+
if (!existsSync(candidate))
|
|
237
|
+
continue;
|
|
238
|
+
const launcherModule = (await import(pathToFileURL(candidate).href));
|
|
239
|
+
return typeof launcherModule.installCodexAppLauncher === "function"
|
|
240
|
+
? launcherModule.installCodexAppLauncher
|
|
241
|
+
: null;
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
async function defaultBindCodexApp(env, rotationEnabled, detectDesktopApp, notify) {
|
|
246
|
+
const currentStatus = await getAppBindStatus().catch(() => null);
|
|
247
|
+
const appDetected = detectDesktopApp() || currentStatus?.bound === true;
|
|
248
|
+
if (!shouldBindCodexAppOnFirstRun({ env, rotationEnabled, appDetected })) {
|
|
249
|
+
return "skipped";
|
|
250
|
+
}
|
|
251
|
+
const result = await bindCodexAppRuntimeRotation();
|
|
252
|
+
if (result?.message) {
|
|
253
|
+
notify(result.message);
|
|
254
|
+
}
|
|
255
|
+
return "completed";
|
|
256
|
+
}
|
|
257
|
+
async function defaultInstallLauncher(env, rotationEnabled, notify) {
|
|
258
|
+
if (!shouldInstallCodexAppLauncherOnFirstRun({ env, rotationEnabled })) {
|
|
259
|
+
return "skipped";
|
|
260
|
+
}
|
|
261
|
+
const installLauncher = await loadLauncherInstall();
|
|
262
|
+
if (!installLauncher)
|
|
263
|
+
return "skipped";
|
|
264
|
+
await installLauncher({ log: notify });
|
|
265
|
+
return "completed";
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Runs the lazily deferred install setup (Codex app bind + launcher routing)
|
|
269
|
+
* exactly once per runtime root. Never throws and never blocks a command on
|
|
270
|
+
* failure: every error path resolves with a skip/failed status and only
|
|
271
|
+
* debug-logs sanitized messages.
|
|
272
|
+
*/
|
|
273
|
+
export async function ensureFirstRunSetup(deps = {}) {
|
|
274
|
+
try {
|
|
275
|
+
const env = deps.env ?? process.env;
|
|
276
|
+
if (isCiEnvironment(env))
|
|
277
|
+
return { ran: false, reason: "ci" };
|
|
278
|
+
const installed = deps.installedContext ?? isInstalledPackageContext();
|
|
279
|
+
if (!installed)
|
|
280
|
+
return { ran: false, reason: "not-installed" };
|
|
281
|
+
const markerPath = deps.markerPath ?? getFirstRunMarkerPath();
|
|
282
|
+
if (existsSync(markerPath))
|
|
283
|
+
return { ran: false, reason: "already-done" };
|
|
284
|
+
const now = deps.now ?? Date.now;
|
|
285
|
+
const startedAt = now();
|
|
286
|
+
if (!claimFirstRunMarker(markerPath, startedAt)) {
|
|
287
|
+
return { ran: false, reason: "claim-race" };
|
|
288
|
+
}
|
|
289
|
+
// Library default goes through the structured logger; the CLI entrypoint
|
|
290
|
+
// passes a stderr notify so interactive users still see bind messages.
|
|
291
|
+
const notify = deps.notify ?? ((message) => log.info(message));
|
|
292
|
+
const detectDesktopApp = deps.detectDesktopApp ?? (() => hasCodexDesktopApp({ env }));
|
|
293
|
+
const rotationEnabled = deps.resolveRotation
|
|
294
|
+
? deps.resolveRotation()
|
|
295
|
+
: resolveRotationEnabled(env);
|
|
296
|
+
const outcome = {
|
|
297
|
+
appBind: "skipped",
|
|
298
|
+
launcher: "skipped",
|
|
299
|
+
};
|
|
300
|
+
try {
|
|
301
|
+
outcome.appBind = await (deps.bindCodexApp
|
|
302
|
+
? deps.bindCodexApp()
|
|
303
|
+
: defaultBindCodexApp(env, rotationEnabled, detectDesktopApp, notify));
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
outcome.appBind = "failed";
|
|
307
|
+
log.debug("first-run app bind skipped", { error: errorMessage(error) });
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
310
|
+
outcome.launcher = await (deps.installLauncher
|
|
311
|
+
? deps.installLauncher()
|
|
312
|
+
: defaultInstallLauncher(env, rotationEnabled, notify));
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
outcome.launcher = "failed";
|
|
316
|
+
log.debug("first-run launcher install skipped", {
|
|
317
|
+
error: errorMessage(error),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
await finalizeFirstRunMarker(markerPath, startedAt, outcome, now);
|
|
321
|
+
return { ran: true, ...outcome };
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
log.debug("first-run setup skipped", { error: errorMessage(error) });
|
|
325
|
+
return { ran: false, reason: "error" };
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -9,4 +9,3 @@ export function applyPreemptiveQuotaSettingsFromConfig(pluginConfig, deps) {
|
|
|
9
9
|
export function resolveUiRuntimeFromConfig(loadPluginConfig, applyUiRuntimeFromConfig) {
|
|
10
10
|
return applyUiRuntimeFromConfig(loadPluginConfig());
|
|
11
11
|
}
|
|
12
|
-
//# sourceMappingURL=quota-settings.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AccountManager, ManagedAccount } from "../accounts.js";
|
|
2
|
+
import type { ModelFamily } from "../prompts/codex.js";
|
|
3
|
+
import type { RuntimePolicyDecision } from "../policy/runtime-policy.js";
|
|
4
|
+
import type { SessionAffinityStore } from "../session-affinity.js";
|
|
5
|
+
/**
|
|
6
|
+
* `chooseAccount` is a SYNC selector that internally advances the rotation
|
|
7
|
+
* cursor (the session-affinity-preferred branch and the round-robin fallback
|
|
8
|
+
* both call `accountManager.markSwitched(...)`, and the hybrid selector advances
|
|
9
|
+
* its own cursor). It does NOT acquire the routing mutex itself.
|
|
10
|
+
*
|
|
11
|
+
* Concurrency (L4): when `routingMutex === "enabled"`, the proxy hot path runs
|
|
12
|
+
* this whole call AND the subsequent `markSwitchedLocked` commit inside a single
|
|
13
|
+
* `withRoutingMutex` acquisition, so concurrent requests serialize selection +
|
|
14
|
+
* cursor advance and cannot stampede the same account. `withRoutingMutex` is
|
|
15
|
+
* reentrant (AsyncLocalStorage), so the nested `markSwitchedLocked` — and the
|
|
16
|
+
* later one in `persistRuntimeActiveAccount` — run inline without re-acquiring
|
|
17
|
+
* the non-reentrant FIFO queue (no deadlock). In legacy mode the inline
|
|
18
|
+
* `markSwitched` calls below are used unchanged and no lock is taken, so default
|
|
19
|
+
* behavior and perf are identical. See the hot-path caller in
|
|
20
|
+
* `startRuntimeRotationProxy` and the regression in
|
|
21
|
+
* `test/runtime-rotation-proxy.test.ts`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function chooseAccount(params: {
|
|
24
|
+
accountManager: AccountManager;
|
|
25
|
+
sessionAffinityStore: SessionAffinityStore | null;
|
|
26
|
+
sessionKey: string | null;
|
|
27
|
+
family: ModelFamily;
|
|
28
|
+
model: string | null;
|
|
29
|
+
attemptedIndexes: ReadonlySet<number>;
|
|
30
|
+
now: number;
|
|
31
|
+
policy: RuntimePolicyDecision | null;
|
|
32
|
+
pinnedIndex: number | null;
|
|
33
|
+
skipReasons?: Map<number, string>;
|
|
34
|
+
stickyBoostByAccount?: Record<number, number>;
|
|
35
|
+
pidOffsetEnabled?: boolean;
|
|
36
|
+
schedulingStrategy?: "hybrid" | "sequential";
|
|
37
|
+
}): ManagedAccount | null;
|
|
38
|
+
//# sourceMappingURL=rotation-account-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotation-account-selection.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-account-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACrC,cAAc,EAAE,cAAc,CAAC;IAC/B,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;CAC7C,GAAG,cAAc,GAAG,IAAI,CAsJxB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chooseAccount` is a SYNC selector that internally advances the rotation
|
|
3
|
+
* cursor (the session-affinity-preferred branch and the round-robin fallback
|
|
4
|
+
* both call `accountManager.markSwitched(...)`, and the hybrid selector advances
|
|
5
|
+
* its own cursor). It does NOT acquire the routing mutex itself.
|
|
6
|
+
*
|
|
7
|
+
* Concurrency (L4): when `routingMutex === "enabled"`, the proxy hot path runs
|
|
8
|
+
* this whole call AND the subsequent `markSwitchedLocked` commit inside a single
|
|
9
|
+
* `withRoutingMutex` acquisition, so concurrent requests serialize selection +
|
|
10
|
+
* cursor advance and cannot stampede the same account. `withRoutingMutex` is
|
|
11
|
+
* reentrant (AsyncLocalStorage), so the nested `markSwitchedLocked` — and the
|
|
12
|
+
* later one in `persistRuntimeActiveAccount` — run inline without re-acquiring
|
|
13
|
+
* the non-reentrant FIFO queue (no deadlock). In legacy mode the inline
|
|
14
|
+
* `markSwitched` calls below are used unchanged and no lock is taken, so default
|
|
15
|
+
* behavior and perf are identical. See the hot-path caller in
|
|
16
|
+
* `startRuntimeRotationProxy` and the regression in
|
|
17
|
+
* `test/runtime-rotation-proxy.test.ts`.
|
|
18
|
+
*/
|
|
19
|
+
export function chooseAccount(params) {
|
|
20
|
+
const { accountManager, sessionAffinityStore, sessionKey, family, model, attemptedIndexes, now, policy, pinnedIndex, skipReasons, stickyBoostByAccount, pidOffsetEnabled, schedulingStrategy, } = params;
|
|
21
|
+
// Manual pin (from `codex-multi-auth switch <n>`) overrides every other
|
|
22
|
+
// selection signal. We do NOT call markSwitched here — the proxy must not
|
|
23
|
+
// clobber the pin set by the CLI. See issue #474.
|
|
24
|
+
if (typeof pinnedIndex === "number") {
|
|
25
|
+
if (attemptedIndexes.has(pinnedIndex)) {
|
|
26
|
+
skipReasons?.set(pinnedIndex, "already-attempted");
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (pinnedIndex < 0 || pinnedIndex >= accountManager.getAccountCount()) {
|
|
30
|
+
skipReasons?.set(pinnedIndex, "missing");
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
if (policy?.blockedAccountIndexes.has(pinnedIndex)) {
|
|
34
|
+
skipReasons?.set(pinnedIndex, "policy-blocked");
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const pinned = accountManager.getAccountByIndex(pinnedIndex);
|
|
38
|
+
if (!pinned || pinned.enabled === false) {
|
|
39
|
+
skipReasons?.set(pinnedIndex, "disabled");
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const reason = accountManager.getAccountRuntimeSkipReason(pinnedIndex, family, model);
|
|
43
|
+
if (reason) {
|
|
44
|
+
skipReasons?.set(pinnedIndex, reason);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return pinned;
|
|
48
|
+
}
|
|
49
|
+
// Sequential / drain-first mode (issue #509): the active account governs ALL
|
|
50
|
+
// new requests, so we deliberately SKIP the per-session affinity tier — there
|
|
51
|
+
// is no per-chat stickiness, every request follows the single active account.
|
|
52
|
+
// The manual pin above still wins (handled first). When the active account is
|
|
53
|
+
// exhausted the selector advances to the next available account and earlier
|
|
54
|
+
// accounts reclaim the slot once their quota recovers.
|
|
55
|
+
if (schedulingStrategy === "sequential") {
|
|
56
|
+
const selected = accountManager.getCurrentOrNextForFamilySequential(family, model, policy?.blockedAccountIndexes);
|
|
57
|
+
if (selected &&
|
|
58
|
+
!attemptedIndexes.has(selected.index) &&
|
|
59
|
+
!policy?.blockedAccountIndexes.has(selected.index)) {
|
|
60
|
+
const reason = accountManager.getAccountRuntimeSkipReason(selected.index, family, model);
|
|
61
|
+
if (!reason)
|
|
62
|
+
return selected;
|
|
63
|
+
skipReasons?.set(selected.index, reason);
|
|
64
|
+
}
|
|
65
|
+
// Active account was attempted/blocked/skipped this request (e.g. it just
|
|
66
|
+
// rate-limited mid-loop): fall through to the shared linear scan to find
|
|
67
|
+
// the next eligible account to TRY. Pass advanceActivePointer=false so a
|
|
68
|
+
// transient, non-exhausting failure on the active account does not
|
|
69
|
+
// permanently move the drain-first primary — only
|
|
70
|
+
// getCurrentOrNextForFamilySequential advances it, and only on true
|
|
71
|
+
// exhaustion.
|
|
72
|
+
return chooseLinearScanFallback({
|
|
73
|
+
accountManager,
|
|
74
|
+
family,
|
|
75
|
+
model,
|
|
76
|
+
attemptedIndexes,
|
|
77
|
+
policy,
|
|
78
|
+
skipReasons,
|
|
79
|
+
advanceActivePointer: false,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const preferredIndex = sessionAffinityStore?.getPreferredAccountIndex(sessionKey, now);
|
|
83
|
+
if (typeof preferredIndex === "number" &&
|
|
84
|
+
!attemptedIndexes.has(preferredIndex) &&
|
|
85
|
+
!policy?.blockedAccountIndexes.has(preferredIndex)) {
|
|
86
|
+
const preferred = accountManager.getAccountByIndex(preferredIndex);
|
|
87
|
+
if (preferred) {
|
|
88
|
+
const reason = accountManager.getAccountRuntimeSkipReason(preferred.index, family, model);
|
|
89
|
+
if (reason) {
|
|
90
|
+
skipReasons?.set(preferred.index, reason);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// L4 (deferred): unlocked cursor mutation — see chooseAccount header.
|
|
94
|
+
accountManager.markSwitched(preferred, "rotation", family);
|
|
95
|
+
return preferred;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const selected = accountManager.getCurrentOrNextForFamilyHybrid(family, model, {
|
|
100
|
+
scoreBoostByAccount: {
|
|
101
|
+
...(policy?.scoreBoostByAccount ?? {}),
|
|
102
|
+
...(stickyBoostByAccount ?? {}),
|
|
103
|
+
},
|
|
104
|
+
// accounts-05: carry the PID-offset distribution into the default-on proxy
|
|
105
|
+
// path too (index.ts already does). Without it, parallel proxy processes can
|
|
106
|
+
// stampede the same account instead of spreading across the pool.
|
|
107
|
+
pidOffsetEnabled,
|
|
108
|
+
});
|
|
109
|
+
if (selected &&
|
|
110
|
+
!attemptedIndexes.has(selected.index) &&
|
|
111
|
+
!policy?.blockedAccountIndexes.has(selected.index)) {
|
|
112
|
+
const reason = accountManager.getAccountRuntimeSkipReason(selected.index, family, model);
|
|
113
|
+
if (!reason)
|
|
114
|
+
return selected;
|
|
115
|
+
skipReasons?.set(selected.index, reason);
|
|
116
|
+
}
|
|
117
|
+
return chooseLinearScanFallback({
|
|
118
|
+
accountManager,
|
|
119
|
+
family,
|
|
120
|
+
model,
|
|
121
|
+
attemptedIndexes,
|
|
122
|
+
policy,
|
|
123
|
+
skipReasons,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Shared linear-scan fallback used by both the hybrid and sequential selection
|
|
128
|
+
* paths in `chooseAccount`. Walks every account in pool order and returns the
|
|
129
|
+
* first one that is not already attempted, not policy-blocked, and has no
|
|
130
|
+
* runtime skip reason (rate-limited / cooling down / circuit-open), recording a
|
|
131
|
+
* skip reason for each rejected candidate. Returns null when no eligible
|
|
132
|
+
* account remains.
|
|
133
|
+
*
|
|
134
|
+
* `advanceActivePointer` (default `true`) controls whether the winner is
|
|
135
|
+
* committed as the new active/cursor position via `markSwitched`. The hybrid
|
|
136
|
+
* path wants this (round-robin advance). The sequential path passes `false`:
|
|
137
|
+
* its within-request fallback only needs an account to TRY this request, and
|
|
138
|
+
* must NOT move `currentAccountIndexByFamily` — otherwise a transient,
|
|
139
|
+
* non-exhausting failure on the active account (which leaves it `isUsable` but
|
|
140
|
+
* present in `attemptedIndexes`) would permanently switch the drain-first
|
|
141
|
+
* primary even though it was never exhausted (issue #509 regression caught in
|
|
142
|
+
* review). In sequential mode only `getCurrentOrNextForFamilySequential` is
|
|
143
|
+
* allowed to advance the active pointer, and only on true exhaustion.
|
|
144
|
+
*/
|
|
145
|
+
function chooseLinearScanFallback(params) {
|
|
146
|
+
const { accountManager, family, model, attemptedIndexes, policy, skipReasons, advanceActivePointer = true, } = params;
|
|
147
|
+
for (const account of accountManager.getAccountsSnapshot()) {
|
|
148
|
+
if (attemptedIndexes.has(account.index)) {
|
|
149
|
+
skipReasons?.set(account.index, "already-attempted");
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (policy?.blockedAccountIndexes.has(account.index)) {
|
|
153
|
+
skipReasons?.set(account.index, "policy-blocked");
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const reason = accountManager.getAccountRuntimeSkipReason(account.index, family, model);
|
|
157
|
+
if (!reason) {
|
|
158
|
+
const live = accountManager.getAccountByIndex(account.index);
|
|
159
|
+
if (!live)
|
|
160
|
+
continue;
|
|
161
|
+
// L4 (deferred): unlocked cursor mutation — see chooseAccount header.
|
|
162
|
+
// Skipped in sequential mode (advanceActivePointer=false) so a
|
|
163
|
+
// within-request retry never reassigns the drain-first primary.
|
|
164
|
+
if (advanceActivePointer) {
|
|
165
|
+
accountManager.markSwitched(live, "rotation", family);
|
|
166
|
+
}
|
|
167
|
+
return live;
|
|
168
|
+
}
|
|
169
|
+
skipReasons?.set(account.index, reason);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|