codex-multi-auth 0.1.2 → 0.1.4
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/README.md +6 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/auth/auth.d.ts +6 -2
- package/dist/lib/auth/auth.d.ts.map +1 -1
- package/dist/lib/auth/auth.js +34 -11
- package/dist/lib/auth/auth.js.map +1 -1
- package/dist/lib/auth/server.d.ts +1 -1
- package/dist/lib/auth/server.js +3 -3
- package/dist/lib/codex-cli/state.d.ts +9 -0
- package/dist/lib/codex-cli/state.d.ts.map +1 -1
- package/dist/lib/codex-cli/state.js +14 -0
- package/dist/lib/codex-cli/state.js.map +1 -1
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +106 -14
- package/dist/lib/codex-cli/writer.js.map +1 -1
- package/dist/lib/codex-manager/settings-hub.d.ts +16 -1
- package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-hub.js +28 -2
- package/dist/lib/codex-manager/settings-hub.js.map +1 -1
- package/dist/lib/codex-manager.d.ts +1 -0
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +320 -18
- package/dist/lib/codex-manager.js.map +1 -1
- package/dist/lib/oauth-success.html +192 -260
- package/dist/lib/parallel-probe.d.ts +7 -0
- package/dist/lib/parallel-probe.d.ts.map +1 -1
- package/dist/lib/parallel-probe.js +37 -9
- package/dist/lib/parallel-probe.js.map +1 -1
- package/dist/lib/refresh-queue.d.ts +4 -5
- package/dist/lib/refresh-queue.d.ts.map +1 -1
- package/dist/lib/refresh-queue.js +99 -21
- package/dist/lib/refresh-queue.js.map +1 -1
- package/dist/lib/request/fetch-helpers.d.ts +12 -4
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
- package/dist/lib/request/fetch-helpers.js +53 -25
- package/dist/lib/request/fetch-helpers.js.map +1 -1
- package/dist/lib/request/helpers/tool-utils.d.ts.map +1 -1
- package/dist/lib/request/helpers/tool-utils.js +36 -6
- package/dist/lib/request/helpers/tool-utils.js.map +1 -1
- package/dist/lib/request/rate-limit-backoff.d.ts +7 -0
- package/dist/lib/request/rate-limit-backoff.d.ts.map +1 -1
- package/dist/lib/request/rate-limit-backoff.js +24 -4
- package/dist/lib/request/rate-limit-backoff.js.map +1 -1
- package/dist/lib/request/request-transformer.d.ts +10 -0
- package/dist/lib/request/request-transformer.d.ts.map +1 -1
- package/dist/lib/request/request-transformer.js +61 -37
- package/dist/lib/request/request-transformer.js.map +1 -1
- package/dist/lib/rotation.d.ts +19 -0
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +60 -39
- package/dist/lib/rotation.js.map +1 -1
- package/dist/lib/ui/copy.d.ts +1 -1
- package/dist/lib/ui/copy.js +1 -1
- package/dist/lib/utils.d.ts +6 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +11 -0
- package/dist/lib/utils.js.map +1 -1
- package/package.json +9 -5
- package/scripts/audit-dev-allowlist.js +186 -94
- package/scripts/benchmark-runtime-path.mjs +166 -0
- package/scripts/codex.js +57 -1
- package/scripts/copy-oauth-success.js +42 -3
- package/scripts/install-codex-auth-utils.js +69 -0
- package/scripts/install-codex-auth.js +16 -7
|
@@ -15,6 +15,7 @@ import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./quota-probe
|
|
|
15
15
|
import { queuedRefresh } from "./refresh-queue.js";
|
|
16
16
|
import { loadQuotaCache, saveQuotaCache, } from "./quota-cache.js";
|
|
17
17
|
import { getStoragePath, loadFlaggedAccounts, loadAccounts, saveFlaggedAccounts, saveAccounts, setStoragePath, } from "./storage.js";
|
|
18
|
+
import { getCodexCliAuthPath, getCodexCliConfigPath, loadCodexCliState, } from "./codex-cli/state.js";
|
|
18
19
|
import { setCodexCliActiveSelection } from "./codex-cli/writer.js";
|
|
19
20
|
import { ANSI } from "./ui/ansi.js";
|
|
20
21
|
import { UI_COPY } from "./ui/copy.js";
|
|
@@ -214,17 +215,17 @@ function printUsage() {
|
|
|
214
215
|
"Codex Multi-Auth CLI",
|
|
215
216
|
"",
|
|
216
217
|
"Usage:",
|
|
217
|
-
" codex
|
|
218
|
-
" codex
|
|
219
|
-
" codex
|
|
220
|
-
" codex
|
|
221
|
-
" codex
|
|
222
|
-
" codex
|
|
223
|
-
" codex
|
|
224
|
-
" codex
|
|
225
|
-
" codex
|
|
226
|
-
" codex
|
|
227
|
-
" codex
|
|
218
|
+
" codex auth login",
|
|
219
|
+
" codex auth list",
|
|
220
|
+
" codex auth status",
|
|
221
|
+
" codex auth switch <index>",
|
|
222
|
+
" codex auth check",
|
|
223
|
+
" codex auth features",
|
|
224
|
+
" codex auth verify-flagged [--dry-run] [--json] [--no-restore]",
|
|
225
|
+
" codex auth forecast [--live] [--json] [--model <model>]",
|
|
226
|
+
" codex auth report [--live] [--json] [--model <model>] [--out <path>]",
|
|
227
|
+
" codex auth fix [--dry-run] [--json] [--live] [--model <model>]",
|
|
228
|
+
" codex auth doctor [--json] [--fix] [--dry-run]",
|
|
228
229
|
"",
|
|
229
230
|
"Notes:",
|
|
230
231
|
" - Uses ~/.codex/multi-auth/openai-codex-accounts.json",
|
|
@@ -2728,6 +2729,103 @@ async function runDoctor(args) {
|
|
|
2728
2729
|
});
|
|
2729
2730
|
}
|
|
2730
2731
|
}
|
|
2732
|
+
const codexAuthPath = getCodexCliAuthPath();
|
|
2733
|
+
const codexConfigPath = getCodexCliConfigPath();
|
|
2734
|
+
let codexAuthEmail;
|
|
2735
|
+
let codexAuthAccountId;
|
|
2736
|
+
addCheck({
|
|
2737
|
+
key: "codex-auth-file",
|
|
2738
|
+
severity: existsSync(codexAuthPath) ? "ok" : "warn",
|
|
2739
|
+
message: existsSync(codexAuthPath)
|
|
2740
|
+
? "Codex auth file found"
|
|
2741
|
+
: "Codex auth file does not exist",
|
|
2742
|
+
details: codexAuthPath,
|
|
2743
|
+
});
|
|
2744
|
+
if (existsSync(codexAuthPath)) {
|
|
2745
|
+
try {
|
|
2746
|
+
const raw = await fs.readFile(codexAuthPath, "utf-8");
|
|
2747
|
+
const parsed = JSON.parse(raw);
|
|
2748
|
+
if (parsed && typeof parsed === "object") {
|
|
2749
|
+
const payload = parsed;
|
|
2750
|
+
const tokens = payload.tokens && typeof payload.tokens === "object"
|
|
2751
|
+
? payload.tokens
|
|
2752
|
+
: null;
|
|
2753
|
+
const accessToken = tokens && typeof tokens.access_token === "string"
|
|
2754
|
+
? tokens.access_token
|
|
2755
|
+
: undefined;
|
|
2756
|
+
const idToken = tokens && typeof tokens.id_token === "string"
|
|
2757
|
+
? tokens.id_token
|
|
2758
|
+
: undefined;
|
|
2759
|
+
const accountIdFromFile = tokens && typeof tokens.account_id === "string"
|
|
2760
|
+
? tokens.account_id
|
|
2761
|
+
: undefined;
|
|
2762
|
+
const emailFromFile = typeof payload.email === "string" ? payload.email : undefined;
|
|
2763
|
+
codexAuthEmail = sanitizeEmail(emailFromFile ?? extractAccountEmail(accessToken, idToken));
|
|
2764
|
+
codexAuthAccountId = accountIdFromFile ?? extractAccountId(accessToken);
|
|
2765
|
+
}
|
|
2766
|
+
addCheck({
|
|
2767
|
+
key: "codex-auth-readable",
|
|
2768
|
+
severity: "ok",
|
|
2769
|
+
message: "Codex auth file is readable",
|
|
2770
|
+
details: codexAuthEmail || codexAuthAccountId
|
|
2771
|
+
? `email=${codexAuthEmail ?? "unknown"}, accountId=${codexAuthAccountId ?? "unknown"}`
|
|
2772
|
+
: undefined,
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
catch (error) {
|
|
2776
|
+
addCheck({
|
|
2777
|
+
key: "codex-auth-readable",
|
|
2778
|
+
severity: "error",
|
|
2779
|
+
message: "Unable to read Codex auth file",
|
|
2780
|
+
details: error instanceof Error ? error.message : String(error),
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
addCheck({
|
|
2785
|
+
key: "codex-config-file",
|
|
2786
|
+
severity: existsSync(codexConfigPath) ? "ok" : "warn",
|
|
2787
|
+
message: existsSync(codexConfigPath)
|
|
2788
|
+
? "Codex config file found"
|
|
2789
|
+
: "Codex config file does not exist",
|
|
2790
|
+
details: codexConfigPath,
|
|
2791
|
+
});
|
|
2792
|
+
let codexAuthStoreMode;
|
|
2793
|
+
if (existsSync(codexConfigPath)) {
|
|
2794
|
+
try {
|
|
2795
|
+
const configRaw = await fs.readFile(codexConfigPath, "utf-8");
|
|
2796
|
+
const match = configRaw.match(/^\s*cli_auth_credentials_store\s*=\s*"([^"]+)"\s*$/m);
|
|
2797
|
+
if (match?.[1]) {
|
|
2798
|
+
codexAuthStoreMode = match[1].trim();
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
catch (error) {
|
|
2802
|
+
addCheck({
|
|
2803
|
+
key: "codex-auth-store",
|
|
2804
|
+
severity: "warn",
|
|
2805
|
+
message: "Unable to read Codex auth-store config",
|
|
2806
|
+
details: error instanceof Error ? error.message : String(error),
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
if (!checks.some((check) => check.key === "codex-auth-store")) {
|
|
2811
|
+
addCheck({
|
|
2812
|
+
key: "codex-auth-store",
|
|
2813
|
+
severity: codexAuthStoreMode === "file" ? "ok" : "warn",
|
|
2814
|
+
message: codexAuthStoreMode === "file"
|
|
2815
|
+
? "Codex auth storage is set to file"
|
|
2816
|
+
: "Codex auth storage is not explicitly set to file",
|
|
2817
|
+
details: codexAuthStoreMode ? `mode=${codexAuthStoreMode}` : "mode=unset",
|
|
2818
|
+
});
|
|
2819
|
+
}
|
|
2820
|
+
const codexCliState = await loadCodexCliState({ forceRefresh: true });
|
|
2821
|
+
addCheck({
|
|
2822
|
+
key: "codex-cli-state",
|
|
2823
|
+
severity: codexCliState ? "ok" : "warn",
|
|
2824
|
+
message: codexCliState
|
|
2825
|
+
? "Codex CLI state loaded"
|
|
2826
|
+
: "Codex CLI state unavailable",
|
|
2827
|
+
details: codexCliState?.path,
|
|
2828
|
+
});
|
|
2731
2829
|
const storage = await loadAccounts();
|
|
2732
2830
|
let fixChanged = false;
|
|
2733
2831
|
let fixActions = [];
|
|
@@ -2857,6 +2955,111 @@ async function runDoctor(args) {
|
|
|
2857
2955
|
message: "Current account aligns with forecast recommendation",
|
|
2858
2956
|
});
|
|
2859
2957
|
}
|
|
2958
|
+
if (activeExists) {
|
|
2959
|
+
const activeAccount = storage.accounts[activeIndex];
|
|
2960
|
+
const managerActiveEmail = sanitizeEmail(activeAccount?.email);
|
|
2961
|
+
const managerActiveAccountId = activeAccount?.accountId;
|
|
2962
|
+
const codexActiveEmail = sanitizeEmail(codexCliState?.activeEmail) ?? codexAuthEmail;
|
|
2963
|
+
const codexActiveAccountId = codexCliState?.activeAccountId ?? codexAuthAccountId;
|
|
2964
|
+
const isEmailMismatch = !!managerActiveEmail &&
|
|
2965
|
+
!!codexActiveEmail &&
|
|
2966
|
+
managerActiveEmail !== codexActiveEmail;
|
|
2967
|
+
const isAccountIdMismatch = !!managerActiveAccountId &&
|
|
2968
|
+
!!codexActiveAccountId &&
|
|
2969
|
+
managerActiveAccountId !== codexActiveAccountId;
|
|
2970
|
+
addCheck({
|
|
2971
|
+
key: "active-selection-sync",
|
|
2972
|
+
severity: isEmailMismatch || isAccountIdMismatch ? "warn" : "ok",
|
|
2973
|
+
message: isEmailMismatch || isAccountIdMismatch
|
|
2974
|
+
? "Manager active account and Codex active account are not aligned"
|
|
2975
|
+
: "Manager active account and Codex active account are aligned",
|
|
2976
|
+
details: `manager=${managerActiveEmail ?? managerActiveAccountId ?? "unknown"} | codex=${codexActiveEmail ?? codexActiveAccountId ?? "unknown"}`,
|
|
2977
|
+
});
|
|
2978
|
+
if (options.fix && activeAccount) {
|
|
2979
|
+
let syncAccessToken = activeAccount.accessToken;
|
|
2980
|
+
let syncRefreshToken = activeAccount.refreshToken;
|
|
2981
|
+
let syncExpiresAt = activeAccount.expiresAt;
|
|
2982
|
+
let syncIdToken;
|
|
2983
|
+
let storageChangedFromDoctorSync = false;
|
|
2984
|
+
if (!hasUsableAccessToken(activeAccount, now)) {
|
|
2985
|
+
if (options.dryRun) {
|
|
2986
|
+
fixActions.push({
|
|
2987
|
+
key: "doctor-refresh",
|
|
2988
|
+
message: `Prepared active-account token refresh for account ${activeIndex + 1} (dry-run)`,
|
|
2989
|
+
});
|
|
2990
|
+
}
|
|
2991
|
+
else {
|
|
2992
|
+
const refreshResult = await queuedRefresh(activeAccount.refreshToken);
|
|
2993
|
+
if (refreshResult.type === "success") {
|
|
2994
|
+
const refreshedEmail = sanitizeEmail(extractAccountEmail(refreshResult.access, refreshResult.idToken));
|
|
2995
|
+
const refreshedAccountId = extractAccountId(refreshResult.access);
|
|
2996
|
+
activeAccount.accessToken = refreshResult.access;
|
|
2997
|
+
activeAccount.refreshToken = refreshResult.refresh;
|
|
2998
|
+
activeAccount.expiresAt = refreshResult.expires;
|
|
2999
|
+
if (refreshedEmail)
|
|
3000
|
+
activeAccount.email = refreshedEmail;
|
|
3001
|
+
if (refreshedAccountId) {
|
|
3002
|
+
activeAccount.accountId = refreshedAccountId;
|
|
3003
|
+
activeAccount.accountIdSource = "token";
|
|
3004
|
+
}
|
|
3005
|
+
syncAccessToken = refreshResult.access;
|
|
3006
|
+
syncRefreshToken = refreshResult.refresh;
|
|
3007
|
+
syncExpiresAt = refreshResult.expires;
|
|
3008
|
+
syncIdToken = refreshResult.idToken;
|
|
3009
|
+
storageChangedFromDoctorSync = true;
|
|
3010
|
+
fixActions.push({
|
|
3011
|
+
key: "doctor-refresh",
|
|
3012
|
+
message: `Refreshed active account tokens for account ${activeIndex + 1}`,
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
else {
|
|
3016
|
+
addCheck({
|
|
3017
|
+
key: "doctor-refresh",
|
|
3018
|
+
severity: "warn",
|
|
3019
|
+
message: "Unable to refresh active account before Codex sync",
|
|
3020
|
+
details: normalizeFailureDetail(refreshResult.message, refreshResult.reason),
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
if (storageChangedFromDoctorSync) {
|
|
3026
|
+
fixChanged = true;
|
|
3027
|
+
if (!options.dryRun) {
|
|
3028
|
+
await saveAccounts(storage);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
if (!options.dryRun) {
|
|
3032
|
+
const synced = await setCodexCliActiveSelection({
|
|
3033
|
+
accountId: activeAccount.accountId,
|
|
3034
|
+
email: activeAccount.email,
|
|
3035
|
+
accessToken: syncAccessToken,
|
|
3036
|
+
refreshToken: syncRefreshToken,
|
|
3037
|
+
expiresAt: syncExpiresAt,
|
|
3038
|
+
...(syncIdToken ? { idToken: syncIdToken } : {}),
|
|
3039
|
+
});
|
|
3040
|
+
if (synced) {
|
|
3041
|
+
fixChanged = true;
|
|
3042
|
+
fixActions.push({
|
|
3043
|
+
key: "codex-active-sync",
|
|
3044
|
+
message: "Synced manager active account into Codex auth state",
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
else {
|
|
3048
|
+
addCheck({
|
|
3049
|
+
key: "codex-active-sync",
|
|
3050
|
+
severity: "warn",
|
|
3051
|
+
message: "Failed to sync manager active account into Codex auth state",
|
|
3052
|
+
});
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
else {
|
|
3056
|
+
fixActions.push({
|
|
3057
|
+
key: "codex-active-sync",
|
|
3058
|
+
message: "Prepared Codex active-account sync (dry-run)",
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
2860
3063
|
}
|
|
2861
3064
|
const summary = checks.reduce((acc, check) => {
|
|
2862
3065
|
acc[check.severity] += 1;
|
|
@@ -3099,7 +3302,7 @@ async function runSwitch(args) {
|
|
|
3099
3302
|
setStoragePath(null);
|
|
3100
3303
|
const indexArg = args[0];
|
|
3101
3304
|
if (!indexArg) {
|
|
3102
|
-
console.error("Missing index. Usage: codex
|
|
3305
|
+
console.error("Missing index. Usage: codex auth switch <index>");
|
|
3103
3306
|
return 1;
|
|
3104
3307
|
}
|
|
3105
3308
|
const parsed = Number.parseInt(indexArg, 10);
|
|
@@ -3131,23 +3334,122 @@ async function runSwitch(args) {
|
|
|
3131
3334
|
if (wasDisabled) {
|
|
3132
3335
|
account.enabled = true;
|
|
3133
3336
|
}
|
|
3134
|
-
|
|
3337
|
+
const switchNow = Date.now();
|
|
3338
|
+
let syncAccessToken = account.accessToken;
|
|
3339
|
+
let syncRefreshToken = account.refreshToken;
|
|
3340
|
+
let syncExpiresAt = account.expiresAt;
|
|
3341
|
+
let syncIdToken;
|
|
3342
|
+
if (!hasUsableAccessToken(account, switchNow)) {
|
|
3343
|
+
const refreshResult = await queuedRefresh(account.refreshToken);
|
|
3344
|
+
if (refreshResult.type === "success") {
|
|
3345
|
+
const tokenAccountId = extractAccountId(refreshResult.access);
|
|
3346
|
+
const nextEmail = sanitizeEmail(extractAccountEmail(refreshResult.access, refreshResult.idToken));
|
|
3347
|
+
if (account.refreshToken !== refreshResult.refresh) {
|
|
3348
|
+
account.refreshToken = refreshResult.refresh;
|
|
3349
|
+
}
|
|
3350
|
+
if (account.accessToken !== refreshResult.access) {
|
|
3351
|
+
account.accessToken = refreshResult.access;
|
|
3352
|
+
}
|
|
3353
|
+
if (account.expiresAt !== refreshResult.expires) {
|
|
3354
|
+
account.expiresAt = refreshResult.expires;
|
|
3355
|
+
}
|
|
3356
|
+
if (nextEmail && nextEmail !== account.email) {
|
|
3357
|
+
account.email = nextEmail;
|
|
3358
|
+
}
|
|
3359
|
+
if (tokenAccountId && tokenAccountId !== account.accountId) {
|
|
3360
|
+
account.accountId = tokenAccountId;
|
|
3361
|
+
account.accountIdSource = "token";
|
|
3362
|
+
}
|
|
3363
|
+
syncAccessToken = refreshResult.access;
|
|
3364
|
+
syncRefreshToken = refreshResult.refresh;
|
|
3365
|
+
syncExpiresAt = refreshResult.expires;
|
|
3366
|
+
syncIdToken = refreshResult.idToken;
|
|
3367
|
+
}
|
|
3368
|
+
else {
|
|
3369
|
+
console.warn(`Switch validation refresh failed for account ${parsed}: ${normalizeFailureDetail(refreshResult.message, refreshResult.reason)}.`);
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
account.lastUsed = switchNow;
|
|
3135
3373
|
account.lastSwitchReason = "rotation";
|
|
3136
3374
|
await saveAccounts(storage);
|
|
3137
3375
|
const synced = await setCodexCliActiveSelection({
|
|
3138
3376
|
accountId: account.accountId,
|
|
3139
3377
|
email: account.email,
|
|
3140
|
-
accessToken:
|
|
3141
|
-
refreshToken:
|
|
3142
|
-
expiresAt:
|
|
3378
|
+
accessToken: syncAccessToken,
|
|
3379
|
+
refreshToken: syncRefreshToken,
|
|
3380
|
+
expiresAt: syncExpiresAt,
|
|
3381
|
+
...(syncIdToken ? { idToken: syncIdToken } : {}),
|
|
3143
3382
|
});
|
|
3144
3383
|
if (!synced) {
|
|
3145
|
-
console.
|
|
3146
|
-
return 1;
|
|
3384
|
+
console.warn(`Switched account ${parsed} locally, but Codex auth sync did not complete. Multi-auth routing will still use this account.`);
|
|
3147
3385
|
}
|
|
3148
3386
|
console.log(`Switched to account ${parsed}: ${formatAccountLabel(account, targetIndex)}${wasDisabled ? " (re-enabled)" : ""}`);
|
|
3149
3387
|
return 0;
|
|
3150
3388
|
}
|
|
3389
|
+
export async function autoSyncActiveAccountToCodex() {
|
|
3390
|
+
setStoragePath(null);
|
|
3391
|
+
const storage = await loadAccounts();
|
|
3392
|
+
if (!storage || storage.accounts.length === 0) {
|
|
3393
|
+
return false;
|
|
3394
|
+
}
|
|
3395
|
+
const activeIndex = resolveActiveIndex(storage, "codex");
|
|
3396
|
+
if (activeIndex < 0 || activeIndex >= storage.accounts.length) {
|
|
3397
|
+
return false;
|
|
3398
|
+
}
|
|
3399
|
+
const account = storage.accounts[activeIndex];
|
|
3400
|
+
if (!account) {
|
|
3401
|
+
return false;
|
|
3402
|
+
}
|
|
3403
|
+
const now = Date.now();
|
|
3404
|
+
let syncAccessToken = account.accessToken;
|
|
3405
|
+
let syncRefreshToken = account.refreshToken;
|
|
3406
|
+
let syncExpiresAt = account.expiresAt;
|
|
3407
|
+
let syncIdToken;
|
|
3408
|
+
let changed = false;
|
|
3409
|
+
if (!hasUsableAccessToken(account, now)) {
|
|
3410
|
+
const refreshResult = await queuedRefresh(account.refreshToken);
|
|
3411
|
+
if (refreshResult.type === "success") {
|
|
3412
|
+
const tokenAccountId = extractAccountId(refreshResult.access);
|
|
3413
|
+
const nextEmail = sanitizeEmail(extractAccountEmail(refreshResult.access, refreshResult.idToken));
|
|
3414
|
+
if (account.refreshToken !== refreshResult.refresh) {
|
|
3415
|
+
account.refreshToken = refreshResult.refresh;
|
|
3416
|
+
changed = true;
|
|
3417
|
+
}
|
|
3418
|
+
if (account.accessToken !== refreshResult.access) {
|
|
3419
|
+
account.accessToken = refreshResult.access;
|
|
3420
|
+
changed = true;
|
|
3421
|
+
}
|
|
3422
|
+
if (account.expiresAt !== refreshResult.expires) {
|
|
3423
|
+
account.expiresAt = refreshResult.expires;
|
|
3424
|
+
changed = true;
|
|
3425
|
+
}
|
|
3426
|
+
if (nextEmail && nextEmail !== account.email) {
|
|
3427
|
+
account.email = nextEmail;
|
|
3428
|
+
changed = true;
|
|
3429
|
+
}
|
|
3430
|
+
if (tokenAccountId && tokenAccountId !== account.accountId) {
|
|
3431
|
+
account.accountId = tokenAccountId;
|
|
3432
|
+
account.accountIdSource = "token";
|
|
3433
|
+
changed = true;
|
|
3434
|
+
}
|
|
3435
|
+
syncAccessToken = refreshResult.access;
|
|
3436
|
+
syncRefreshToken = refreshResult.refresh;
|
|
3437
|
+
syncExpiresAt = refreshResult.expires;
|
|
3438
|
+
syncIdToken = refreshResult.idToken;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
if (changed) {
|
|
3442
|
+
await saveAccounts(storage);
|
|
3443
|
+
}
|
|
3444
|
+
return setCodexCliActiveSelection({
|
|
3445
|
+
accountId: account.accountId,
|
|
3446
|
+
email: account.email,
|
|
3447
|
+
accessToken: syncAccessToken,
|
|
3448
|
+
refreshToken: syncRefreshToken,
|
|
3449
|
+
expiresAt: syncExpiresAt,
|
|
3450
|
+
...(syncIdToken ? { idToken: syncIdToken } : {}),
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3151
3453
|
export async function runCodexMultiAuthCli(rawArgs) {
|
|
3152
3454
|
const startupDisplaySettings = await loadDashboardDisplaySettings();
|
|
3153
3455
|
applyUiThemeFromDashboardSettings(startupDisplaySettings);
|