codex-multi-auth 2.16.0 → 2.17.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 +9 -9
- package/LICENSE +21 -21
- package/README.md +487 -463
- package/assets/codex-multi-auth-icon.svg +39 -39
- package/assets/readme-hero.svg +31 -31
- package/config/README.md +31 -31
- package/config/codex-legacy.json +1221 -1221
- package/config/codex-modern.json +423 -423
- package/config/minimal-codex.json +15 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/lib/account-policy.d.ts +4 -0
- package/dist/lib/account-policy.d.ts.map +1 -1
- package/dist/lib/account-policy.js +8 -0
- package/dist/lib/accounts/rate-limits.d.ts.map +1 -1
- package/dist/lib/accounts/rate-limits.js +2 -0
- package/dist/lib/accounts.d.ts +15 -3
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +231 -30
- package/dist/lib/api-route-store.d.ts +24 -0
- package/dist/lib/api-route-store.d.ts.map +1 -0
- package/dist/lib/api-route-store.js +145 -0
- package/dist/lib/auth/account-access.d.ts +115 -0
- package/dist/lib/auth/account-access.d.ts.map +1 -0
- package/dist/lib/auth/account-access.js +214 -0
- package/dist/lib/auth/token-utils.d.ts +54 -1
- package/dist/lib/auth/token-utils.d.ts.map +1 -1
- package/dist/lib/auth/token-utils.js +92 -7
- package/dist/lib/cli.d.ts +1 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +4 -0
- package/dist/lib/codex-cli/state.d.ts +7 -0
- package/dist/lib/codex-cli/state.d.ts.map +1 -1
- package/dist/lib/codex-cli/state.js +18 -0
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +60 -8
- package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-manager-commands.js +1 -0
- package/dist/lib/codex-manager/account-pool-write.d.ts +3 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-pool-write.js +4 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts +14 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts.map +1 -0
- package/dist/lib/codex-manager/api-login-menu.js +224 -0
- package/dist/lib/codex-manager/commands/account.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/account.js +27 -0
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +6 -2
- package/dist/lib/codex-manager/commands/check.d.ts +7 -1
- package/dist/lib/codex-manager/commands/check.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/check.js +24 -3
- package/dist/lib/codex-manager/commands/forecast.d.ts +1 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/forecast.js +7 -3
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +5 -1
- package/dist/lib/codex-manager/commands/resets.d.ts +2 -0
- package/dist/lib/codex-manager/commands/resets.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/resets.js +67 -0
- package/dist/lib/codex-manager/commands/rotation.d.ts +2 -2
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/rotation.js +63 -12
- package/dist/lib/codex-manager/commands/status.d.ts +12 -1
- package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/status.js +166 -22
- package/dist/lib/codex-manager/commands/uninstall.js +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.js +3 -2
- package/dist/lib/codex-manager/health-check.d.ts +3 -0
- package/dist/lib/codex-manager/health-check.d.ts.map +1 -1
- package/dist/lib/codex-manager/health-check.js +57 -7
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/help.js +4 -2
- package/dist/lib/codex-manager/login-flow.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-flow.js +69 -7
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-data.js +21 -8
- package/dist/lib/codex-manager/login-oauth.d.ts +3 -0
- package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-oauth.js +6 -1
- package/dist/lib/codex-manager/login-workspace-choice.d.ts +11 -0
- package/dist/lib/codex-manager/login-workspace-choice.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-workspace-choice.js +37 -0
- package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -1
- package/dist/lib/codex-manager/persist-selected-account.js +2 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts +7 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/quota-cache-helpers.js +34 -19
- package/dist/lib/codex-manager/repair-commands.d.ts +13 -0
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +144 -9
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +25 -6
- package/dist/lib/concurrency.d.ts +3 -0
- package/dist/lib/concurrency.d.ts.map +1 -0
- package/dist/lib/concurrency.js +31 -0
- package/dist/lib/context-budget-response.js +8 -8
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/model-route-policy.d.ts +52 -0
- package/dist/lib/model-route-policy.d.ts.map +1 -0
- package/dist/lib/model-route-policy.js +159 -0
- package/dist/lib/oauth-success.html +125 -125
- package/dist/lib/policy/runtime-policy.d.ts +1 -0
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +3 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts +2 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -1
- package/dist/lib/preemptive-quota-scheduler.js +4 -0
- package/dist/lib/prompts/codex-host-bridge.js +138 -138
- package/dist/lib/prompts/codex.js +79 -79
- package/dist/lib/quota-cache.d.ts +7 -3
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +91 -59
- package/dist/lib/quota-probe.d.ts +5 -0
- package/dist/lib/quota-probe.d.ts.map +1 -1
- package/dist/lib/quota-probe.js +26 -2
- package/dist/lib/quota-readiness.d.ts +7 -2
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +25 -4
- package/dist/lib/request/client-cancellation.d.ts +5 -0
- package/dist/lib/request/client-cancellation.d.ts.map +1 -0
- package/dist/lib/request/client-cancellation.js +7 -0
- package/dist/lib/request/response-outcome.d.ts +25 -0
- package/dist/lib/request/response-outcome.d.ts.map +1 -0
- package/dist/lib/request/response-outcome.js +49 -0
- package/dist/lib/request/stream-failover-runtime.d.ts +2 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.js +29 -10
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +2 -8
- package/dist/lib/runtime/account-model-catalog.d.ts +64 -0
- package/dist/lib/runtime/account-model-catalog.d.ts.map +1 -0
- package/dist/lib/runtime/account-model-catalog.js +154 -0
- package/dist/lib/runtime/account-pool.d.ts +3 -1
- package/dist/lib/runtime/account-pool.d.ts.map +1 -1
- package/dist/lib/runtime/account-pool.js +4 -0
- package/dist/lib/runtime/account-reset-credits.d.ts +42 -0
- package/dist/lib/runtime/account-reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/account-reset-credits.js +82 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts +30 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-capabilities.js +434 -0
- package/dist/lib/runtime/api-model-runtime.d.ts +42 -0
- package/dist/lib/runtime/api-model-runtime.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-runtime.js +358 -0
- package/dist/lib/runtime/app-bind.d.ts +19 -1
- package/dist/lib/runtime/app-bind.d.ts.map +1 -1
- package/dist/lib/runtime/app-bind.js +89 -11
- package/dist/lib/runtime/automatic-account-checks.d.ts +35 -0
- package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-account-checks.js +140 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts +7 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-subscription-checks.js +54 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts +8 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/catalog-capabilities.js +61 -0
- package/dist/lib/runtime/inference-activity.d.ts +15 -0
- package/dist/lib/runtime/inference-activity.d.ts.map +1 -0
- package/dist/lib/runtime/inference-activity.js +95 -0
- package/dist/lib/runtime/model-discovery-status.d.ts +100 -0
- package/dist/lib/runtime/model-discovery-status.d.ts.map +1 -0
- package/dist/lib/runtime/model-discovery-status.js +387 -0
- package/dist/lib/runtime/native-account-storage.d.ts +11 -0
- package/dist/lib/runtime/native-account-storage.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-storage.js +50 -0
- package/dist/lib/runtime/native-account-sync.d.ts +19 -0
- package/dist/lib/runtime/native-account-sync.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-sync.js +62 -0
- package/dist/lib/runtime/native-binding-lock.d.ts +3 -0
- package/dist/lib/runtime/native-binding-lock.d.ts.map +1 -0
- package/dist/lib/runtime/native-binding-lock.js +5 -0
- package/dist/lib/runtime/native-client-auth.d.ts +3 -0
- package/dist/lib/runtime/native-client-auth.d.ts.map +1 -0
- package/dist/lib/runtime/native-client-auth.js +42 -0
- package/dist/lib/runtime/native-provider-config.d.ts +4 -0
- package/dist/lib/runtime/native-provider-config.d.ts.map +1 -0
- package/dist/lib/runtime/native-provider-config.js +52 -0
- package/dist/lib/runtime/native-rate-limits.d.ts +18 -0
- package/dist/lib/runtime/native-rate-limits.d.ts.map +1 -0
- package/dist/lib/runtime/native-rate-limits.js +135 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts +41 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credit-routing.js +66 -0
- package/dist/lib/runtime/reset-credits.d.ts +101 -0
- package/dist/lib/runtime/reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credits.js +162 -0
- package/dist/lib/runtime/response-output-history.d.ts +17 -0
- package/dist/lib/runtime/response-output-history.d.ts.map +1 -0
- package/dist/lib/runtime/response-output-history.js +85 -0
- package/dist/lib/runtime/responses-websocket.d.ts +31 -0
- package/dist/lib/runtime/responses-websocket.d.ts.map +1 -0
- package/dist/lib/runtime/responses-websocket.js +636 -0
- package/dist/lib/runtime/resume-picker.d.ts +41 -0
- package/dist/lib/runtime/resume-picker.d.ts.map +1 -0
- package/dist/lib/runtime/resume-picker.js +169 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts +6 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-account-selection.js +63 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts +33 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-server-types.d.ts +18 -0
- package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-capability-failures.d.ts +14 -0
- package/dist/lib/runtime/runtime-capability-failures.d.ts.map +1 -0
- package/dist/lib/runtime/runtime-capability-failures.js +76 -0
- package/dist/lib/runtime/runtime-observability.d.ts +7 -0
- package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-observability.js +42 -2
- package/dist/lib/runtime/subscription-first-use.d.ts +10 -0
- package/dist/lib/runtime/subscription-first-use.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-first-use.js +64 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts +6 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-event.js +31 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts +17 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-order.js +31 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts +15 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts.map +1 -0
- package/dist/lib/runtime/workspace-model-scopes.js +34 -0
- package/dist/lib/runtime-constants.d.ts +3 -0
- package/dist/lib/runtime-constants.d.ts.map +1 -1
- package/dist/lib/runtime-constants.js +5 -0
- package/dist/lib/runtime-paths.d.ts.map +1 -1
- package/dist/lib/runtime-paths.js +4 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +852 -42
- package/dist/lib/schemas.d.ts +20 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +3 -0
- package/dist/lib/storage/credential-sidecars.d.ts +13 -0
- package/dist/lib/storage/credential-sidecars.d.ts.map +1 -0
- package/dist/lib/storage/credential-sidecars.js +52 -0
- package/dist/lib/storage/file-lock.d.ts +9 -0
- package/dist/lib/storage/file-lock.d.ts.map +1 -0
- package/dist/lib/storage/file-lock.js +186 -0
- package/dist/lib/storage/flagged-storage.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage.js +12 -0
- package/dist/lib/storage/path-state.d.ts +2 -0
- package/dist/lib/storage/path-state.d.ts.map +1 -1
- package/dist/lib/storage/path-state.js +9 -0
- package/dist/lib/storage/paths.js +4 -4
- package/dist/lib/storage/pending-auth.d.ts +18 -0
- package/dist/lib/storage/pending-auth.d.ts.map +1 -0
- package/dist/lib/storage/pending-auth.js +155 -0
- package/dist/lib/storage/public-types.d.ts +13 -0
- package/dist/lib/storage/public-types.d.ts.map +1 -1
- package/dist/lib/storage/record-identity.d.ts +16 -0
- package/dist/lib/storage/record-identity.d.ts.map +1 -0
- package/dist/lib/storage/record-identity.js +16 -0
- package/dist/lib/storage/snapshot-merge.d.ts +16 -0
- package/dist/lib/storage/snapshot-merge.d.ts.map +1 -0
- package/dist/lib/storage/snapshot-merge.js +206 -0
- package/dist/lib/storage/transactions.d.ts.map +1 -1
- package/dist/lib/storage/transactions.js +5 -4
- package/dist/lib/storage.d.ts +6 -0
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +77 -7
- package/dist/lib/ui/auth-menu-builder.d.ts +2 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu-builder.js +1 -0
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +1 -0
- package/dist/lib/ui/check-progress.d.ts +8 -0
- package/dist/lib/ui/check-progress.d.ts.map +1 -0
- package/dist/lib/ui/check-progress.js +30 -0
- package/dist/lib/ui/format.d.ts +3 -1
- package/dist/lib/ui/format.d.ts.map +1 -1
- package/dist/lib/ui/format.js +8 -0
- package/dist/lib/ui/ui-copy.d.ts +2 -2
- package/dist/lib/ui/ui-copy.js +2 -2
- package/dist/lib/usage/pricing.js +2 -2
- package/dist/lib/usage/usage-extraction.d.ts +3 -1
- package/dist/lib/usage/usage-extraction.d.ts.map +1 -1
- package/dist/lib/usage/usage-extraction.js +46 -9
- package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
- package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
- package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
- package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
- package/node_modules/@codex-ai/plugin/package.json +9 -9
- package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
- package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
- package/node_modules/@codex-ai/sdk/package.json +8 -8
- package/package.json +200 -197
- package/scripts/codex-app-launcher.js +653 -653
- package/scripts/codex-app-router.js +373 -366
- package/scripts/codex-bin-resolver.js +313 -281
- package/scripts/codex-multi-auth.js +59 -59
- package/scripts/codex-routing.js +62 -61
- package/scripts/codex.js +6642 -6564
- package/scripts/install-codex-auth-utils.js +213 -213
- package/scripts/mcodex.js +367 -367
- package/scripts/postinstall.js +114 -114
- package/scripts/preuninstall.js +265 -265
- package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
- package/vendor/codex-ai-plugin/dist/index.js +2 -2
- package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
- package/vendor/codex-ai-plugin/dist/tool.js +29 -29
- package/vendor/codex-ai-plugin/package.json +9 -9
- package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
- package/vendor/codex-ai-sdk/dist/index.js +2 -2
- package/vendor/codex-ai-sdk/package.json +8 -8
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { CodexCliMirror, Workspace } from "../storage/public-types.js";
|
|
2
|
+
import type { AccountIdSource } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Which accounts the backend will actually let the current credentials act as.
|
|
5
|
+
*
|
|
6
|
+
* Codex CLI >= 0.156.0 resolves this itself through
|
|
7
|
+
* `GET /backend-api/wham/accounts/check` before every request and refuses to run
|
|
8
|
+
* when the account it was told to use is absent from the answer
|
|
9
|
+
* ("selected workspace missing from routing discovery"). The id/organization
|
|
10
|
+
* lists carried inside the token claims are NOT the same thing: a token can list
|
|
11
|
+
* an organization it has no live authorization for, so selecting a workspace from
|
|
12
|
+
* the claims alone can persist an account id that every later request rejects.
|
|
13
|
+
*/
|
|
14
|
+
export interface AuthorizedAccounts {
|
|
15
|
+
/** Every account id the response listed, in the order it listed them. */
|
|
16
|
+
accountIds: string[];
|
|
17
|
+
/** The id the backend itself considers the default, when it named one. */
|
|
18
|
+
defaultAccountId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface FetchAuthorizedAccountsOptions {
|
|
21
|
+
/** Injection seam for tests; defaults to the global fetch. */
|
|
22
|
+
fetch?: typeof globalThis.fetch;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reads the account ids out of a `wham/accounts/check` payload.
|
|
27
|
+
*
|
|
28
|
+
* Returns null when the payload carries no usable list, which the caller must
|
|
29
|
+
* treat as "unknown" rather than "nothing is authorized" — refusing every
|
|
30
|
+
* account on a shape we failed to parse would break logins for a response format
|
|
31
|
+
* change alone.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseAuthorizedAccounts(payload: unknown): AuthorizedAccounts | null;
|
|
34
|
+
/**
|
|
35
|
+
* Asks the backend which accounts these credentials may act as.
|
|
36
|
+
*
|
|
37
|
+
* Fails open (resolves null) for every error: this check exists to catch a
|
|
38
|
+
* selection that would not work, so an unreachable or unparseable answer must
|
|
39
|
+
* leave the caller's existing behavior untouched rather than block a login.
|
|
40
|
+
*/
|
|
41
|
+
export declare function fetchAuthorizedAccounts(accessToken: string, options?: FetchAuthorizedAccountsOptions): Promise<AuthorizedAccounts | null>;
|
|
42
|
+
export interface ConstrainedSelection {
|
|
43
|
+
/** The account id to actually persist. */
|
|
44
|
+
accountId: string;
|
|
45
|
+
/** True when the backend's answer forced a different id than requested. */
|
|
46
|
+
changed: boolean;
|
|
47
|
+
/** The id that was rejected, present only when `changed` is true. */
|
|
48
|
+
rejected?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Narrows a chosen account id to one the backend authorizes.
|
|
52
|
+
*
|
|
53
|
+
* Only ever narrows: with no authorization data, no default to fall back to, or
|
|
54
|
+
* an id that is already authorized, the caller's own choice is returned
|
|
55
|
+
* unchanged. That keeps this a guard against a known-bad write rather than a new
|
|
56
|
+
* way for a login to end up somewhere the user did not ask for.
|
|
57
|
+
*/
|
|
58
|
+
export declare function constrainSelectionToAuthorized(accountId: string, authorized: AuthorizedAccounts | null): ConstrainedSelection;
|
|
59
|
+
/** The slice of a resolved login selection this guard reads and rewrites. */
|
|
60
|
+
export interface AccountSelectionLike {
|
|
61
|
+
accountIdOverride?: string;
|
|
62
|
+
accountIdSource?: AccountIdSource;
|
|
63
|
+
accountLabel?: string;
|
|
64
|
+
workspaces?: Workspace[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Applies {@link constrainSelectionToAuthorized} to a resolved login selection.
|
|
68
|
+
*
|
|
69
|
+
* On a rewrite the source becomes `token`: the backend's default account IS the
|
|
70
|
+
* account these credentials are, so it must auto-follow later token refreshes
|
|
71
|
+
* (see `shouldUpdateAccountIdFromToken`) instead of being pinned the way an
|
|
72
|
+
* explicit org/manual choice is. The label follows the new id too; an empty
|
|
73
|
+
* label (not undefined) is deliberate, because the account-pool merge keeps
|
|
74
|
+
* the saved label on undefined and would go on naming the rejected workspace.
|
|
75
|
+
*
|
|
76
|
+
* The workspace list is narrowed with {@link toAuthorizedWorkspaces}.
|
|
77
|
+
*/
|
|
78
|
+
export declare function applyAuthorizedAccountConstraint<T extends AccountSelectionLike>(selection: T, authorized: AuthorizedAccounts | null): {
|
|
79
|
+
selection: T;
|
|
80
|
+
result: ConstrainedSelection | null;
|
|
81
|
+
};
|
|
82
|
+
/** The outcome of {@link refreshCodexCliMirror}. */
|
|
83
|
+
export type CodexCliMirrorUpdate = "set" | "cleared";
|
|
84
|
+
/**
|
|
85
|
+
* Re-checks an explicit (`manual`) binding and keeps its CodexCliMirror in
|
|
86
|
+
* step, mutating the record in place: set to the backend default while the
|
|
87
|
+
* explicit id is unauthorized, removed once it is authorized again. The
|
|
88
|
+
* explicit id itself is never changed. Fails open: no answer, no change.
|
|
89
|
+
*/
|
|
90
|
+
export declare function refreshCodexCliMirror(account: {
|
|
91
|
+
accountId?: string;
|
|
92
|
+
accountIdSource?: AccountIdSource;
|
|
93
|
+
codexCliMirror?: CodexCliMirror;
|
|
94
|
+
}, accessToken: string, options?: FetchAuthorizedAccountsOptions): Promise<CodexCliMirrorUpdate | null>;
|
|
95
|
+
/** The slice of a saved account record this migration reads and rewrites. */
|
|
96
|
+
export interface StoredAccountIdentity {
|
|
97
|
+
accountId?: string;
|
|
98
|
+
accountIdSource?: AccountIdSource;
|
|
99
|
+
accountLabel?: string;
|
|
100
|
+
workspaces?: Workspace[];
|
|
101
|
+
currentWorkspaceIndex?: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Rebinds a saved account's id when it is not one the backend currently
|
|
105
|
+
* authorizes, mutating the record in place. This is the migration path for
|
|
106
|
+
* accounts saved before this guard existed (or by `codex-multi-auth workspace
|
|
107
|
+
* <account> <workspace>`, which has no live check of its own).
|
|
108
|
+
*
|
|
109
|
+
* Scoped to `accountIdSource === "org"` — the one source that never
|
|
110
|
+
* auto-follows the token (`shouldUpdateAccountIdFromToken`). "token" /
|
|
111
|
+
* "id_token" already self-correct through `applyTokenAccountIdentity`, and
|
|
112
|
+
* "manual" is an explicit `login --org` binding this must not override.
|
|
113
|
+
*/
|
|
114
|
+
export declare function reboundUnauthorizedAccountIdentity(account: StoredAccountIdentity, accessToken: string, options?: FetchAuthorizedAccountsOptions): Promise<ConstrainedSelection | null>;
|
|
115
|
+
//# sourceMappingURL=account-access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-access.d.ts","sourceRoot":"","sources":["../../../lib/auth/account-access.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IAClC,yEAAyE;IACzE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,8BAA8B;IAC9C,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAeD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,OAAO,GACd,kBAAkB,GAAG,IAAI,CAgB3B;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC5C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,8BAAmC,GAC1C,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA0BpC;AAED,MAAM,WAAW,oBAAoB;IACpC,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC7C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,kBAAkB,GAAG,IAAI,GACnC,oBAAoB,CAUtB;AAED,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,oBAAoB,EAC9E,SAAS,EAAE,CAAC,EACZ,UAAU,EAAE,kBAAkB,GAAG,IAAI,GACnC;IAAE,SAAS,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAA;CAAE,CAsBvD;AA6BD,oDAAoD;AACpD,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,SAAS,CAAC;AAErD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;CAChC,EACD,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,8BAAmC,GAC1C,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAoBtC;AAED,6EAA6E;AAC7E,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kCAAkC,CACvD,OAAO,EAAE,qBAAqB,EAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,8BAAmC,GAC1C,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA4BtC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { CODEX_BASE_URL } from "../constants.js";
|
|
2
|
+
const ACCOUNTS_CHECK_PATH = "/wham/accounts/check";
|
|
3
|
+
const ACCOUNTS_CHECK_TIMEOUT_MS = 10_000;
|
|
4
|
+
function readString(value) {
|
|
5
|
+
if (typeof value !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
9
|
+
}
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reads the account ids out of a `wham/accounts/check` payload.
|
|
15
|
+
*
|
|
16
|
+
* Returns null when the payload carries no usable list, which the caller must
|
|
17
|
+
* treat as "unknown" rather than "nothing is authorized" — refusing every
|
|
18
|
+
* account on a shape we failed to parse would break logins for a response format
|
|
19
|
+
* change alone.
|
|
20
|
+
*/
|
|
21
|
+
export function parseAuthorizedAccounts(payload) {
|
|
22
|
+
if (!isRecord(payload))
|
|
23
|
+
return null;
|
|
24
|
+
const accounts = payload.accounts;
|
|
25
|
+
if (!Array.isArray(accounts))
|
|
26
|
+
return null;
|
|
27
|
+
const accountIds = [];
|
|
28
|
+
for (const entry of accounts) {
|
|
29
|
+
if (!isRecord(entry))
|
|
30
|
+
continue;
|
|
31
|
+
const id = readString(entry.id) ?? readString(entry.account_id);
|
|
32
|
+
if (id && !accountIds.includes(id))
|
|
33
|
+
accountIds.push(id);
|
|
34
|
+
}
|
|
35
|
+
if (accountIds.length === 0)
|
|
36
|
+
return null;
|
|
37
|
+
const defaultAccountId = readString(payload.default_account_id);
|
|
38
|
+
return defaultAccountId ? { accountIds, defaultAccountId } : { accountIds };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Asks the backend which accounts these credentials may act as.
|
|
42
|
+
*
|
|
43
|
+
* Fails open (resolves null) for every error: this check exists to catch a
|
|
44
|
+
* selection that would not work, so an unreachable or unparseable answer must
|
|
45
|
+
* leave the caller's existing behavior untouched rather than block a login.
|
|
46
|
+
*/
|
|
47
|
+
export async function fetchAuthorizedAccounts(accessToken, options = {}) {
|
|
48
|
+
const token = readString(accessToken);
|
|
49
|
+
if (!token)
|
|
50
|
+
return null;
|
|
51
|
+
const doFetch = options.fetch ?? globalThis.fetch;
|
|
52
|
+
const timeout = AbortSignal.timeout(ACCOUNTS_CHECK_TIMEOUT_MS);
|
|
53
|
+
const signal = options.signal
|
|
54
|
+
? AbortSignal.any([options.signal, timeout])
|
|
55
|
+
: timeout;
|
|
56
|
+
try {
|
|
57
|
+
const response = await doFetch(`${CODEX_BASE_URL}${ACCOUNTS_CHECK_PATH}`, {
|
|
58
|
+
method: "GET",
|
|
59
|
+
headers: {
|
|
60
|
+
authorization: `Bearer ${token}`,
|
|
61
|
+
accept: "application/json",
|
|
62
|
+
},
|
|
63
|
+
signal,
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok)
|
|
66
|
+
return null;
|
|
67
|
+
return parseAuthorizedAccounts(await response.json());
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Deliberately silent about the cause: the token is in scope here and the
|
|
71
|
+
// failure is advisory, so there is nothing safe or useful to log.
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Narrows a chosen account id to one the backend authorizes.
|
|
77
|
+
*
|
|
78
|
+
* Only ever narrows: with no authorization data, no default to fall back to, or
|
|
79
|
+
* an id that is already authorized, the caller's own choice is returned
|
|
80
|
+
* unchanged. That keeps this a guard against a known-bad write rather than a new
|
|
81
|
+
* way for a login to end up somewhere the user did not ask for.
|
|
82
|
+
*/
|
|
83
|
+
export function constrainSelectionToAuthorized(accountId, authorized) {
|
|
84
|
+
if (!authorized)
|
|
85
|
+
return { accountId, changed: false };
|
|
86
|
+
if (authorized.accountIds.includes(accountId)) {
|
|
87
|
+
return { accountId, changed: false };
|
|
88
|
+
}
|
|
89
|
+
const fallback = authorized.defaultAccountId;
|
|
90
|
+
if (!fallback || fallback === accountId) {
|
|
91
|
+
return { accountId, changed: false };
|
|
92
|
+
}
|
|
93
|
+
return { accountId: fallback, changed: true, rejected: accountId };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Applies {@link constrainSelectionToAuthorized} to a resolved login selection.
|
|
97
|
+
*
|
|
98
|
+
* On a rewrite the source becomes `token`: the backend's default account IS the
|
|
99
|
+
* account these credentials are, so it must auto-follow later token refreshes
|
|
100
|
+
* (see `shouldUpdateAccountIdFromToken`) instead of being pinned the way an
|
|
101
|
+
* explicit org/manual choice is. The label follows the new id too; an empty
|
|
102
|
+
* label (not undefined) is deliberate, because the account-pool merge keeps
|
|
103
|
+
* the saved label on undefined and would go on naming the rejected workspace.
|
|
104
|
+
*
|
|
105
|
+
* The workspace list is narrowed with {@link toAuthorizedWorkspaces}.
|
|
106
|
+
*/
|
|
107
|
+
export function applyAuthorizedAccountConstraint(selection, authorized) {
|
|
108
|
+
const current = readString(selection.accountIdOverride);
|
|
109
|
+
if (!current || !authorized)
|
|
110
|
+
return { selection, result: null };
|
|
111
|
+
const result = constrainSelectionToAuthorized(current, authorized);
|
|
112
|
+
if (!result.changed)
|
|
113
|
+
return { selection, result };
|
|
114
|
+
const workspaces = selection.workspaces
|
|
115
|
+
? toAuthorizedWorkspaces(selection.workspaces, authorized, result.accountId)
|
|
116
|
+
: undefined;
|
|
117
|
+
return {
|
|
118
|
+
selection: {
|
|
119
|
+
...selection,
|
|
120
|
+
accountIdOverride: result.accountId,
|
|
121
|
+
accountIdSource: "token",
|
|
122
|
+
accountLabel: workspaces?.find((workspace) => workspace.id === result.accountId)
|
|
123
|
+
?.name ?? "",
|
|
124
|
+
...(workspaces ? { workspaces } : {}),
|
|
125
|
+
},
|
|
126
|
+
result,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Keeps only workspaces the backend authorizes and makes `accountId` the one
|
|
131
|
+
* default, adding it when the token claims never listed it.
|
|
132
|
+
*
|
|
133
|
+
* The plugin host sends workspaces[currentWorkspaceIndex].id ahead of
|
|
134
|
+
* accountId, and the account-pool merge keeps a saved pointer while its id
|
|
135
|
+
* survives, else falls back to the default. With every unauthorized
|
|
136
|
+
* workspace gone and `accountId` the only default, neither path can land on
|
|
137
|
+
* a workspace the backend refuses.
|
|
138
|
+
*/
|
|
139
|
+
function toAuthorizedWorkspaces(workspaces, authorized, accountId) {
|
|
140
|
+
const kept = workspaces
|
|
141
|
+
.filter((workspace) => workspace.id === accountId || authorized.accountIds.includes(workspace.id))
|
|
142
|
+
.map((workspace) => ({ ...workspace, isDefault: workspace.id === accountId }));
|
|
143
|
+
if (!kept.some((workspace) => workspace.id === accountId)) {
|
|
144
|
+
kept.push({ id: accountId, enabled: true, isDefault: true });
|
|
145
|
+
}
|
|
146
|
+
return kept;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Re-checks an explicit (`manual`) binding and keeps its CodexCliMirror in
|
|
150
|
+
* step, mutating the record in place: set to the backend default while the
|
|
151
|
+
* explicit id is unauthorized, removed once it is authorized again. The
|
|
152
|
+
* explicit id itself is never changed. Fails open: no answer, no change.
|
|
153
|
+
*/
|
|
154
|
+
export async function refreshCodexCliMirror(account, accessToken, options = {}) {
|
|
155
|
+
if (account.accountIdSource !== "manual")
|
|
156
|
+
return null;
|
|
157
|
+
const currentId = readString(account.accountId);
|
|
158
|
+
if (!currentId)
|
|
159
|
+
return null;
|
|
160
|
+
const authorized = await fetchAuthorizedAccounts(accessToken, options);
|
|
161
|
+
if (!authorized)
|
|
162
|
+
return null;
|
|
163
|
+
if (authorized.accountIds.includes(currentId)) {
|
|
164
|
+
if (!account.codexCliMirror)
|
|
165
|
+
return null;
|
|
166
|
+
delete account.codexCliMirror;
|
|
167
|
+
return "cleared";
|
|
168
|
+
}
|
|
169
|
+
const result = constrainSelectionToAuthorized(currentId, authorized);
|
|
170
|
+
if (!result.changed)
|
|
171
|
+
return null;
|
|
172
|
+
const mirror = account.codexCliMirror;
|
|
173
|
+
if (mirror?.forAccountId === currentId && mirror.accountId === result.accountId) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
account.codexCliMirror = { forAccountId: currentId, accountId: result.accountId };
|
|
177
|
+
return "set";
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Rebinds a saved account's id when it is not one the backend currently
|
|
181
|
+
* authorizes, mutating the record in place. This is the migration path for
|
|
182
|
+
* accounts saved before this guard existed (or by `codex-multi-auth workspace
|
|
183
|
+
* <account> <workspace>`, which has no live check of its own).
|
|
184
|
+
*
|
|
185
|
+
* Scoped to `accountIdSource === "org"` — the one source that never
|
|
186
|
+
* auto-follows the token (`shouldUpdateAccountIdFromToken`). "token" /
|
|
187
|
+
* "id_token" already self-correct through `applyTokenAccountIdentity`, and
|
|
188
|
+
* "manual" is an explicit `login --org` binding this must not override.
|
|
189
|
+
*/
|
|
190
|
+
export async function reboundUnauthorizedAccountIdentity(account, accessToken, options = {}) {
|
|
191
|
+
if (account.accountIdSource !== "org")
|
|
192
|
+
return null;
|
|
193
|
+
const currentId = readString(account.accountId);
|
|
194
|
+
if (!currentId)
|
|
195
|
+
return null;
|
|
196
|
+
const authorized = await fetchAuthorizedAccounts(accessToken, options);
|
|
197
|
+
const result = constrainSelectionToAuthorized(currentId, authorized);
|
|
198
|
+
if (!authorized || !result.changed)
|
|
199
|
+
return null;
|
|
200
|
+
account.accountId = result.accountId;
|
|
201
|
+
account.accountIdSource = "token";
|
|
202
|
+
// The workspace pointer has to follow the rebind: the plugin host sends
|
|
203
|
+
// the pointed-at workspace id ahead of accountId.
|
|
204
|
+
if (account.workspaces) {
|
|
205
|
+
account.workspaces = toAuthorizedWorkspaces(account.workspaces, authorized, result.accountId);
|
|
206
|
+
const workspaceIndex = account.workspaces.findIndex((workspace) => workspace.id === result.accountId);
|
|
207
|
+
account.currentWorkspaceIndex = workspaceIndex;
|
|
208
|
+
account.accountLabel = account.workspaces[workspaceIndex]?.name ?? "";
|
|
209
|
+
}
|
|
210
|
+
else if (account.accountLabel !== undefined) {
|
|
211
|
+
account.accountLabel = "";
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Token utility functions for JWT parsing and account ID extraction.
|
|
3
3
|
* Extracted from accounts.ts to reduce module size and improve cohesion.
|
|
4
4
|
*/
|
|
5
|
+
import type { CodexCliMirror } from "../storage/public-types.js";
|
|
5
6
|
import type { AccountIdSource } from "../types.js";
|
|
6
7
|
/**
|
|
7
8
|
* Account ID candidate from token or organization data.
|
|
@@ -13,9 +14,13 @@ export interface AccountIdCandidate {
|
|
|
13
14
|
isDefault?: boolean;
|
|
14
15
|
isPersonal?: boolean;
|
|
15
16
|
}
|
|
17
|
+
/** Explicit metadata wins over the conventional Personal display name. */
|
|
18
|
+
export declare function isPersonalAccountCandidate(candidate: AccountIdCandidate): boolean;
|
|
16
19
|
/**
|
|
17
20
|
* Select the best workspace candidate for OAuth account binding.
|
|
18
|
-
*
|
|
21
|
+
* Prefer a uniquely identifiable Personal workspace. Ambiguous CLI logins
|
|
22
|
+
* require an explicit choice before reaching this fallback selector.
|
|
23
|
+
* Fallback order when no unique Personal candidate exists:
|
|
19
24
|
* 1) org default that is not personal
|
|
20
25
|
* 2) org default (any)
|
|
21
26
|
* 3) id_token candidate
|
|
@@ -30,6 +35,53 @@ export declare function selectBestAccountCandidate(candidates: AccountIdCandidat
|
|
|
30
35
|
* @returns Account ID string or undefined if not found
|
|
31
36
|
*/
|
|
32
37
|
export declare function extractAccountId(accessToken?: string): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Maps a stored account id to the value Codex CLI accepts as tokens.account_id.
|
|
40
|
+
* Codex CLI >= 0.156 checks that field against the token's ChatGPT workspaces;
|
|
41
|
+
* an OpenAI platform org id ("org-...") is never one of them, so it resolves to
|
|
42
|
+
* the token's chatgpt_account_id claim instead, or undefined without a claim.
|
|
43
|
+
* The auth.json writer and every stored-vs-auth.json comparison must share
|
|
44
|
+
* this mapping, or org-sourced accounts read as permanently drifted.
|
|
45
|
+
*/
|
|
46
|
+
/** Whether an id is an OpenAI platform org id ("org-..."), never a ChatGPT workspace. */
|
|
47
|
+
export declare function isOpenAiOrgId(accountId: string | undefined): boolean;
|
|
48
|
+
export declare function resolveCodexAuthAccountId(accountId: string | undefined, accessToken?: string, idToken?: string): string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The account id to hand the ~/.codex/auth.json writer for a saved account,
|
|
51
|
+
* and to compare against that file. Applies the account's live
|
|
52
|
+
* {@link CodexCliMirror} first, then resolveCodexAuthAccountId's org-id
|
|
53
|
+
* substitution. An org id without a token claim is returned unchanged so the
|
|
54
|
+
* writer can still drop it. Every auth.json writer and drift check goes
|
|
55
|
+
* through this; a raw `account.accountId` there writes back an id Codex CLI
|
|
56
|
+
* refuses.
|
|
57
|
+
*/
|
|
58
|
+
export declare function codexCliAccountIdFor(account: {
|
|
59
|
+
accountId?: string;
|
|
60
|
+
codexCliMirror?: CodexCliMirror;
|
|
61
|
+
}, accessToken?: string, idToken?: string): string | undefined;
|
|
62
|
+
interface CodexAccountIdentity {
|
|
63
|
+
accountId?: string;
|
|
64
|
+
accessToken?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The Codex CLI state's active account id with the access token of the
|
|
68
|
+
* snapshot it came from, so an "org-..." id (the legacy accounts.json keeps
|
|
69
|
+
* the raw id) can be resolved against that account's own token.
|
|
70
|
+
*/
|
|
71
|
+
export declare function codexCliActiveIdentity(state: {
|
|
72
|
+
activeAccountId?: string;
|
|
73
|
+
accounts?: ReadonlyArray<CodexAccountIdentity & {
|
|
74
|
+
isActive?: boolean;
|
|
75
|
+
}>;
|
|
76
|
+
}): CodexAccountIdentity;
|
|
77
|
+
/**
|
|
78
|
+
* Whether two account ids name the same Codex account. Equal raw ids match;
|
|
79
|
+
* otherwise each side goes through resolveCodexAuthAccountId with its own
|
|
80
|
+
* token, so a stored "org-..." id matches the workspace id the writer put in
|
|
81
|
+
* auth.json. Unresolvable ids (org id, no claim) never match a different id.
|
|
82
|
+
* Equal org ids still differ when both tokens name different workspaces.
|
|
83
|
+
*/
|
|
84
|
+
export declare function codexAuthAccountIdsMatch(left: CodexAccountIdentity, right: CodexAccountIdentity): boolean;
|
|
33
85
|
/**
|
|
34
86
|
* Extracts the email address from OAuth tokens.
|
|
35
87
|
* Checks id_token first (where OpenAI puts email), then falls back to access_token.
|
|
@@ -72,4 +124,5 @@ export declare function resolveRuntimeRequestIdentity(input: {
|
|
|
72
124
|
* @returns Sanitized email or undefined if invalid
|
|
73
125
|
*/
|
|
74
126
|
export declare function sanitizeEmail(email: string | undefined): string | undefined;
|
|
127
|
+
export {};
|
|
75
128
|
//# sourceMappingURL=token-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../../lib/auth/token-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../../lib/auth/token-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -180,19 +180,33 @@ function collectCandidatesFromPayload(payload, source) {
|
|
|
180
180
|
* Removes duplicate candidates by accountId.
|
|
181
181
|
*/
|
|
182
182
|
function uniqueCandidates(candidates) {
|
|
183
|
-
const
|
|
184
|
-
const result = [];
|
|
183
|
+
const byId = new Map();
|
|
185
184
|
for (const candidate of candidates) {
|
|
186
|
-
|
|
185
|
+
const kept = byId.get(candidate.accountId);
|
|
186
|
+
if (!kept) {
|
|
187
|
+
byId.set(candidate.accountId, { ...candidate });
|
|
187
188
|
continue;
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
}
|
|
190
|
+
const wasPersonal = isPersonalAccountCandidate(kept);
|
|
191
|
+
if (kept.isPersonal === undefined && candidate.isPersonal !== undefined) {
|
|
192
|
+
kept.isPersonal = candidate.isPersonal;
|
|
193
|
+
}
|
|
194
|
+
if (!wasPersonal && isPersonalAccountCandidate(candidate) && kept.isPersonal !== false) {
|
|
195
|
+
kept.label = candidate.label;
|
|
196
|
+
}
|
|
190
197
|
}
|
|
191
|
-
return
|
|
198
|
+
return [...byId.values()];
|
|
199
|
+
}
|
|
200
|
+
/** Explicit metadata wins over the conventional Personal display name. */
|
|
201
|
+
export function isPersonalAccountCandidate(candidate) {
|
|
202
|
+
return candidate.isPersonal === true ||
|
|
203
|
+
(candidate.isPersonal !== false && /^Personal(?:\s*\(|\s*\[|$)/i.test(candidate.label.trim()));
|
|
192
204
|
}
|
|
193
205
|
/**
|
|
194
206
|
* Select the best workspace candidate for OAuth account binding.
|
|
195
|
-
*
|
|
207
|
+
* Prefer a uniquely identifiable Personal workspace. Ambiguous CLI logins
|
|
208
|
+
* require an explicit choice before reaching this fallback selector.
|
|
209
|
+
* Fallback order when no unique Personal candidate exists:
|
|
196
210
|
* 1) org default that is not personal
|
|
197
211
|
* 2) org default (any)
|
|
198
212
|
* 3) id_token candidate
|
|
@@ -203,6 +217,9 @@ function uniqueCandidates(candidates) {
|
|
|
203
217
|
export function selectBestAccountCandidate(candidates) {
|
|
204
218
|
if (candidates.length === 0)
|
|
205
219
|
return undefined;
|
|
220
|
+
const personal = candidates.filter(isPersonalAccountCandidate);
|
|
221
|
+
if (personal.length === 1)
|
|
222
|
+
return personal[0];
|
|
206
223
|
const orgDefaultNonPersonal = candidates.find((candidate) => candidate.source === "org" && candidate.isDefault === true && candidate.isPersonal !== true);
|
|
207
224
|
if (orgDefaultNonPersonal)
|
|
208
225
|
return orgDefaultNonPersonal;
|
|
@@ -232,6 +249,74 @@ export function extractAccountId(accessToken) {
|
|
|
232
249
|
const accountId = decoded?.[JWT_CLAIM_PATH]?.chatgpt_account_id;
|
|
233
250
|
return typeof accountId === "string" && accountId.trim() ? accountId : undefined;
|
|
234
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Maps a stored account id to the value Codex CLI accepts as tokens.account_id.
|
|
254
|
+
* Codex CLI >= 0.156 checks that field against the token's ChatGPT workspaces;
|
|
255
|
+
* an OpenAI platform org id ("org-...") is never one of them, so it resolves to
|
|
256
|
+
* the token's chatgpt_account_id claim instead, or undefined without a claim.
|
|
257
|
+
* The auth.json writer and every stored-vs-auth.json comparison must share
|
|
258
|
+
* this mapping, or org-sourced accounts read as permanently drifted.
|
|
259
|
+
*/
|
|
260
|
+
/** Whether an id is an OpenAI platform org id ("org-..."), never a ChatGPT workspace. */
|
|
261
|
+
export function isOpenAiOrgId(accountId) {
|
|
262
|
+
return /^org-/i.test(accountId?.trim() ?? "");
|
|
263
|
+
}
|
|
264
|
+
export function resolveCodexAuthAccountId(accountId, accessToken, idToken) {
|
|
265
|
+
const trimmed = accountId?.trim();
|
|
266
|
+
if (!trimmed)
|
|
267
|
+
return undefined;
|
|
268
|
+
if (!isOpenAiOrgId(trimmed))
|
|
269
|
+
return trimmed;
|
|
270
|
+
return extractAccountId(accessToken) ?? extractAccountId(idToken);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The account id to hand the ~/.codex/auth.json writer for a saved account,
|
|
274
|
+
* and to compare against that file. Applies the account's live
|
|
275
|
+
* {@link CodexCliMirror} first, then resolveCodexAuthAccountId's org-id
|
|
276
|
+
* substitution. An org id without a token claim is returned unchanged so the
|
|
277
|
+
* writer can still drop it. Every auth.json writer and drift check goes
|
|
278
|
+
* through this; a raw `account.accountId` there writes back an id Codex CLI
|
|
279
|
+
* refuses.
|
|
280
|
+
*/
|
|
281
|
+
export function codexCliAccountIdFor(account, accessToken, idToken) {
|
|
282
|
+
const accountId = account.accountId?.trim();
|
|
283
|
+
const mirror = account.codexCliMirror;
|
|
284
|
+
const selected = accountId && mirror && mirror.forAccountId === accountId
|
|
285
|
+
? mirror.accountId
|
|
286
|
+
: account.accountId;
|
|
287
|
+
return resolveCodexAuthAccountId(selected, accessToken, idToken) ?? selected;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* The Codex CLI state's active account id with the access token of the
|
|
291
|
+
* snapshot it came from, so an "org-..." id (the legacy accounts.json keeps
|
|
292
|
+
* the raw id) can be resolved against that account's own token.
|
|
293
|
+
*/
|
|
294
|
+
export function codexCliActiveIdentity(state) {
|
|
295
|
+
const accountId = state.activeAccountId?.trim();
|
|
296
|
+
const accounts = state.accounts ?? [];
|
|
297
|
+
const snapshot = accounts.find((entry) => !!accountId && entry.accountId?.trim() === accountId) ??
|
|
298
|
+
accounts.find((entry) => entry.isActive);
|
|
299
|
+
return { accountId, accessToken: snapshot?.accessToken };
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Whether two account ids name the same Codex account. Equal raw ids match;
|
|
303
|
+
* otherwise each side goes through resolveCodexAuthAccountId with its own
|
|
304
|
+
* token, so a stored "org-..." id matches the workspace id the writer put in
|
|
305
|
+
* auth.json. Unresolvable ids (org id, no claim) never match a different id.
|
|
306
|
+
* Equal org ids still differ when both tokens name different workspaces.
|
|
307
|
+
*/
|
|
308
|
+
export function codexAuthAccountIdsMatch(left, right) {
|
|
309
|
+
const leftId = left.accountId?.trim();
|
|
310
|
+
const rightId = right.accountId?.trim();
|
|
311
|
+
if (!leftId || !rightId)
|
|
312
|
+
return false;
|
|
313
|
+
const leftResolved = resolveCodexAuthAccountId(leftId, left.accessToken);
|
|
314
|
+
const rightResolved = resolveCodexAuthAccountId(rightId, right.accessToken);
|
|
315
|
+
if (leftId === rightId) {
|
|
316
|
+
return !leftResolved || !rightResolved || leftResolved === rightResolved;
|
|
317
|
+
}
|
|
318
|
+
return !!leftResolved && leftResolved === rightResolved;
|
|
319
|
+
}
|
|
235
320
|
/**
|
|
236
321
|
* Extracts the email address from OAuth tokens.
|
|
237
322
|
* Checks id_token first (where OpenAI puts email), then falls back to access_token.
|
package/dist/lib/cli.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { AccountCurrentMarker } from "./runtime/runtime-current-account.js"
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function isNonInteractiveMode(): boolean;
|
|
10
10
|
export declare function promptAddAnotherAccount(currentCount: number): Promise<boolean>;
|
|
11
|
-
export type LoginMode = "add" | "forecast" | "fix" | "settings" | "fresh" | "manage" | "check" | "deep-check" | "verify-flagged" | "cancel";
|
|
11
|
+
export type LoginMode = "add" | "forecast" | "fix" | "settings" | "api-models" | "fresh" | "manage" | "check" | "deep-check" | "verify-flagged" | "cancel";
|
|
12
12
|
export interface ExistingAccountInfo {
|
|
13
13
|
accountId?: string;
|
|
14
14
|
accountLabel?: string;
|
package/dist/lib/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../lib/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAGN,KAAK,EACL,KAAK,aAAa,EAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAQ9C;AAED,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcpF;AAED,MAAM,MAAM,SAAS,GAClB,KAAK,GACL,UAAU,GACV,KAAK,GACL,UAAU,GACV,OAAO,GACP,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,gBAAgB,GAChB,QAAQ,CAAC;AAEZ,MAAM,WAAW,mBAAmB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../lib/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/cli.js
CHANGED
|
@@ -90,6 +90,8 @@ async function promptLoginModeFallback(existingAccounts) {
|
|
|
90
90
|
while (true) {
|
|
91
91
|
const answer = await rl.question(UI_COPY.fallback.selectModePrompt);
|
|
92
92
|
const normalized = answer.trim().toLowerCase();
|
|
93
|
+
if (normalized === "api")
|
|
94
|
+
return { mode: "api-models" };
|
|
93
95
|
if (normalized === "a" || normalized === "add")
|
|
94
96
|
return { mode: "add" };
|
|
95
97
|
if (normalized === "b" || normalized === "p" || normalized === "forecast") {
|
|
@@ -142,6 +144,8 @@ export async function promptLoginMode(existingAccounts, options = {}) {
|
|
|
142
144
|
return { mode: "forecast" };
|
|
143
145
|
case "fix":
|
|
144
146
|
return { mode: "fix" };
|
|
147
|
+
case "api-models":
|
|
148
|
+
return { mode: "api-models" };
|
|
145
149
|
case "settings":
|
|
146
150
|
return { mode: "settings" };
|
|
147
151
|
case "fresh":
|
|
@@ -13,6 +13,13 @@ export interface CodexCliState {
|
|
|
13
13
|
accounts: CodexCliAccountSnapshot[];
|
|
14
14
|
activeAccountId?: string;
|
|
15
15
|
activeEmail?: string;
|
|
16
|
+
/**
|
|
17
|
+
* The raw tokens.account_id of auth.json whenever auth.json exists, also
|
|
18
|
+
* when the state itself came from the legacy accounts.json. Codex CLI
|
|
19
|
+
* 0.156+ rejects an "org-..." value there (#700), unlike accounts.json,
|
|
20
|
+
* which keeps raw org ids.
|
|
21
|
+
*/
|
|
22
|
+
authFileAccountId?: string;
|
|
16
23
|
syncVersion?: number;
|
|
17
24
|
sourceUpdatedAtMs?: number;
|
|
18
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../lib/codex-cli/state.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,uBAAuB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,uBAAuB,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAsID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAgB/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAIhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../lib/codex-cli/state.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,uBAAuB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,uBAAuB,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAsID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAgB/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAIhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;AA0HD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA2K/B;AAED,wBAAsB,2BAA2B,CAChD,KAAK,EAAE,MAAM,GAAG,SAAS,GACvB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAgBzC;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AAED,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D"}
|
|
@@ -299,6 +299,7 @@ function parseCodexCliAuthState(path, parsed, sourceUpdatedAtMs) {
|
|
|
299
299
|
accounts: [snapshot],
|
|
300
300
|
activeAccountId: accountId,
|
|
301
301
|
activeEmail: email,
|
|
302
|
+
authFileAccountId: readTrimmedString(tokens.account_id) ?? readTrimmedString(tokens.accountId),
|
|
302
303
|
syncVersion: readNumber(parsed.codexMultiAuthSyncVersion),
|
|
303
304
|
sourceUpdatedAtMs,
|
|
304
305
|
};
|
|
@@ -372,6 +373,23 @@ export async function loadCodexCliState(options) {
|
|
|
372
373
|
}
|
|
373
374
|
const state = parseCodexCliState(accountsPath, parsed, sourceUpdatedAtMs);
|
|
374
375
|
if (state) {
|
|
376
|
+
if (hasAuthPath) {
|
|
377
|
+
// Codex CLI itself reads auth.json, so a stale org account_id
|
|
378
|
+
// there must stay visible behind a valid accounts.json.
|
|
379
|
+
try {
|
|
380
|
+
const authParsed = JSON.parse(await retryFsOperation(() => fs.readFile(authPath, "utf-8")));
|
|
381
|
+
const authTokens = isRecord(authParsed) && isRecord(authParsed.tokens)
|
|
382
|
+
? authParsed.tokens
|
|
383
|
+
: undefined;
|
|
384
|
+
state.authFileAccountId = authTokens
|
|
385
|
+
? (readTrimmedString(authTokens.account_id) ??
|
|
386
|
+
readTrimmedString(authTokens.accountId))
|
|
387
|
+
: undefined;
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// Unreadable auth.json: nothing to flag here.
|
|
391
|
+
}
|
|
392
|
+
}
|
|
375
393
|
incrementCodexCliMetric("readSuccesses");
|
|
376
394
|
log.debug("Loaded Codex CLI state", {
|
|
377
395
|
operation: "read-state",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../lib/codex-cli/writer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../lib/codex-cli/writer.ts"],"names":[],"mappings":"AA4BA,UAAU,eAAe;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AA8ND;;;;;;GAMG;AACH,wBAAgB,kCAAkC,IAAI,OAAO,CAG5D;AAiBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,2BAA2B,CAChD,UAAU,GAAE,MAAgC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAgDlB;AA4JD,wBAAsB,0BAA0B,CAC/C,SAAS,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,CAAC,CAkNlB;AAED,wBAAgB,sCAAsC,IAAI,MAAM,CAE/D"}
|