codex-multi-auth 2.7.1 → 2.8.1
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 +2 -1
- package/dist/lib/codex-cli/writer.d.ts +51 -0
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +89 -8
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +57 -8
- package/dist/lib/runtime/first-run.d.ts +12 -6
- package/dist/lib/runtime/first-run.d.ts.map +1 -1
- package/dist/lib/runtime/first-run.js +140 -9
- package/package.json +198 -196
- package/scripts/codex.js +195 -22
package/scripts/codex.js
CHANGED
|
@@ -74,6 +74,10 @@ const APP_RUNTIME_HELPER_OWNER_PID_ENV =
|
|
|
74
74
|
"CODEX_MULTI_AUTH_APP_ROTATION_OWNER_PID";
|
|
75
75
|
const APP_RUNTIME_HELPER_REAL_CODEX_HOME_ENV =
|
|
76
76
|
"CODEX_MULTI_AUTH_REAL_CODEX_HOME";
|
|
77
|
+
const APP_RUNTIME_HELPER_USE_CANONICAL_HOME_ENV =
|
|
78
|
+
"CODEX_MULTI_AUTH_APP_ROTATION_USE_CANONICAL_HOME";
|
|
79
|
+
const APP_SERVER_CONFIG_ARGS_ENV =
|
|
80
|
+
"CODEX_MULTI_AUTH_APP_SERVER_CONFIG_ARGS_JSON";
|
|
77
81
|
const APP_RUNTIME_HELPER_STATUS_FILE =
|
|
78
82
|
RUNTIME_CONSTANTS.APP_RUNTIME_HELPER_STATUS_FILE;
|
|
79
83
|
const DEFAULT_APP_RUNTIME_HELPER_IDLE_MS = 12 * 60 * 60 * 1000;
|
|
@@ -1083,6 +1087,34 @@ async function loadRuntimeConfigTomlModule() {
|
|
|
1083
1087
|
}
|
|
1084
1088
|
}
|
|
1085
1089
|
|
|
1090
|
+
// Reconciles the persisted `cli_auth_credentials_store` in ~/.codex/config.toml
|
|
1091
|
+
// to "file" before forwarding.
|
|
1092
|
+
//
|
|
1093
|
+
// `buildForwardArgs` already appends `-c cli_auth_credentials_store="file"`, but
|
|
1094
|
+
// that only covers the process this wrapper spawns. Third-party front-ends
|
|
1095
|
+
// (CodexBar and friends) exec the official binary directly and read config.toml
|
|
1096
|
+
// instead, so a config still pointing at "keychain" keeps producing macOS login
|
|
1097
|
+
// keychain prompts (issue #641). Running the reconcile here self-heals a config
|
|
1098
|
+
// that something else flipped back — e.g. a fresh official `codex login`.
|
|
1099
|
+
//
|
|
1100
|
+
// Idempotent: the lib helper returns without writing when the value is already
|
|
1101
|
+
// "file", so this adds no write amplification on the common path.
|
|
1102
|
+
async function ensurePersistedCodexFileAuthStore() {
|
|
1103
|
+
const forceFileAuthStore = (process.env.CODEX_MULTI_AUTH_FORCE_FILE_AUTH_STORE ?? "1").trim() !== "0";
|
|
1104
|
+
if (!forceFileAuthStore) return;
|
|
1105
|
+
|
|
1106
|
+
try {
|
|
1107
|
+
const mod = await import("../dist/lib/codex-cli/writer.js");
|
|
1108
|
+
if (typeof mod.ensureCodexCliFileAuthStore !== "function") return;
|
|
1109
|
+
await mod.ensureCodexCliFileAuthStore();
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
if (isModuleNotFoundError(error)) return;
|
|
1112
|
+
// Best effort only. A read-only or locked config.toml (Windows
|
|
1113
|
+
// EPERM/EBUSY) must never block the wrapped command: the per-invocation
|
|
1114
|
+
// `-c` override still protects this run.
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1086
1118
|
async function autoSyncManagerActiveSelectionIfEnabled() {
|
|
1087
1119
|
const enabled = (process.env.CODEX_MULTI_AUTH_AUTO_SYNC_ON_STARTUP ?? "1").trim() !== "0";
|
|
1088
1120
|
if (!enabled) return;
|
|
@@ -3490,6 +3522,38 @@ function createRuntimeRotationProxyCodexHome(
|
|
|
3490
3522
|
};
|
|
3491
3523
|
}
|
|
3492
3524
|
|
|
3525
|
+
function createRuntimeRotationProxyCanonicalCodexHome(
|
|
3526
|
+
baseEnv,
|
|
3527
|
+
proxyBaseUrl,
|
|
3528
|
+
clientApiKey,
|
|
3529
|
+
configTomlModule,
|
|
3530
|
+
) {
|
|
3531
|
+
const originalCodexHome = resolveRuntimeRotationProxyOriginalCodexHome(baseEnv);
|
|
3532
|
+
const providerTable = `model_providers.${RUNTIME_ROTATION_PROXY_PROVIDER_ID}`;
|
|
3533
|
+
const configArgs = [
|
|
3534
|
+
`${providerTable}.name=${configTomlModule.tomlStringLiteral(APP_SERVER_ACCOUNT_DISPLAY_NAME)}`,
|
|
3535
|
+
`${providerTable}.base_url=${configTomlModule.tomlStringLiteral(proxyBaseUrl)}`,
|
|
3536
|
+
`${providerTable}.env_key=${configTomlModule.tomlStringLiteral("OPENAI_API_KEY")}`,
|
|
3537
|
+
`${providerTable}.requires_openai_auth=false`,
|
|
3538
|
+
`${providerTable}.wire_api=${configTomlModule.tomlStringLiteral("responses")}`,
|
|
3539
|
+
"disable_response_storage=false",
|
|
3540
|
+
].flatMap((assignment) => ["-c", assignment]);
|
|
3541
|
+
|
|
3542
|
+
return {
|
|
3543
|
+
args: configArgs,
|
|
3544
|
+
env: {
|
|
3545
|
+
...baseEnv,
|
|
3546
|
+
CODEX_HOME: originalCodexHome,
|
|
3547
|
+
OPENAI_API_KEY: clientApiKey,
|
|
3548
|
+
CODEX_MULTI_AUTH_DIR: resolveRuntimeRotationOriginalMultiAuthDir(
|
|
3549
|
+
originalCodexHome,
|
|
3550
|
+
baseEnv,
|
|
3551
|
+
),
|
|
3552
|
+
},
|
|
3553
|
+
cleanup: () => {},
|
|
3554
|
+
};
|
|
3555
|
+
}
|
|
3556
|
+
|
|
3493
3557
|
function appendNodeImportOption(nodeOptions, preloadPath) {
|
|
3494
3558
|
const importOption = `--import=${pathToFileURL(preloadPath).href}`;
|
|
3495
3559
|
const trimmed = (nodeOptions ?? "").trim();
|
|
@@ -3504,15 +3568,26 @@ function createRuntimeRotationAppServerPreloadSource(wrapperScriptPath) {
|
|
|
3504
3568
|
"",
|
|
3505
3569
|
`const wrapperScriptPath = ${JSON.stringify(wrapperScriptPath)};`,
|
|
3506
3570
|
`const accountLabelEnv = ${JSON.stringify(APP_SERVER_ACCOUNT_LABEL_ENV)};`,
|
|
3571
|
+
`const configArgsEnv = ${JSON.stringify(APP_SERVER_CONFIG_ARGS_ENV)};`,
|
|
3572
|
+
"let configArgs = [];",
|
|
3573
|
+
"try {",
|
|
3574
|
+
' const parsed = JSON.parse(process.env[configArgsEnv] ?? "[]");',
|
|
3575
|
+
" if (Array.isArray(parsed)) {",
|
|
3576
|
+
' configArgs = parsed.filter((arg) => typeof arg === "string");',
|
|
3577
|
+
" }",
|
|
3578
|
+
"} catch {",
|
|
3579
|
+
" // Ignore malformed internal metadata and preserve app-server startup.",
|
|
3580
|
+
"}",
|
|
3507
3581
|
"const rawArgs = process.argv.slice(1);",
|
|
3508
3582
|
"const firstArg = rawArgs[0] ?? \"\";",
|
|
3509
3583
|
'if (basename(firstArg).toLowerCase() === "app-server") {',
|
|
3510
|
-
' const args = ["app-server", ...rawArgs.slice(1)];',
|
|
3584
|
+
' const args = ["app-server", ...rawArgs.slice(1), ...configArgs];',
|
|
3511
3585
|
" const env = {",
|
|
3512
3586
|
" ...process.env,",
|
|
3513
3587
|
' CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY: "0",',
|
|
3514
3588
|
" [accountLabelEnv]: \"1\",",
|
|
3515
3589
|
" };",
|
|
3590
|
+
" delete env[configArgsEnv];",
|
|
3516
3591
|
" const child = spawn(process.execPath, [wrapperScriptPath, ...args], {",
|
|
3517
3592
|
" stdio: \"inherit\",",
|
|
3518
3593
|
" env,",
|
|
@@ -3558,7 +3633,7 @@ function sweepStaleRuntimeRotationAppServerShimDirs(shimRootDir) {
|
|
|
3558
3633
|
}
|
|
3559
3634
|
}
|
|
3560
3635
|
|
|
3561
|
-
function installRuntimeRotationAppServerCliShim(forwardedEnv) {
|
|
3636
|
+
function installRuntimeRotationAppServerCliShim(forwardedEnv, configArgs = []) {
|
|
3562
3637
|
const shadowCodexHome = forwardedEnv.CODEX_HOME;
|
|
3563
3638
|
if (!shadowCodexHome) {
|
|
3564
3639
|
throw new Error("runtime app-server shim requires CODEX_HOME");
|
|
@@ -3615,6 +3690,11 @@ function installRuntimeRotationAppServerCliShim(forwardedEnv) {
|
|
|
3615
3690
|
);
|
|
3616
3691
|
forwardedEnv.CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY = "0";
|
|
3617
3692
|
forwardedEnv[APP_SERVER_ACCOUNT_LABEL_ENV] = "1";
|
|
3693
|
+
if (configArgs.length > 0) {
|
|
3694
|
+
forwardedEnv[APP_SERVER_CONFIG_ARGS_ENV] = JSON.stringify(configArgs);
|
|
3695
|
+
} else {
|
|
3696
|
+
delete forwardedEnv[APP_SERVER_CONFIG_ARGS_ENV];
|
|
3697
|
+
}
|
|
3618
3698
|
return shimDir;
|
|
3619
3699
|
}
|
|
3620
3700
|
|
|
@@ -3715,6 +3795,7 @@ function pickRuntimeRotationAppHelperEnv(env) {
|
|
|
3715
3795
|
"CODEX_MULTI_AUTH_REAL_CODEX_BIN",
|
|
3716
3796
|
"CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY",
|
|
3717
3797
|
APP_SERVER_ACCOUNT_LABEL_ENV,
|
|
3798
|
+
APP_SERVER_CONFIG_ARGS_ENV,
|
|
3718
3799
|
]) {
|
|
3719
3800
|
if (env[name]) {
|
|
3720
3801
|
picked[name] = env[name];
|
|
@@ -3776,7 +3857,7 @@ function createRuntimeRotationAppHelperStatus({
|
|
|
3776
3857
|
|
|
3777
3858
|
async function runRuntimeRotationAppHelper() {
|
|
3778
3859
|
let proxyServer = null;
|
|
3779
|
-
let
|
|
3860
|
+
let runtimeContext = null;
|
|
3780
3861
|
let appServerShimDir = null;
|
|
3781
3862
|
let statusTimer = null;
|
|
3782
3863
|
let closing = false;
|
|
@@ -3813,7 +3894,7 @@ async function runRuntimeRotationAppHelper() {
|
|
|
3813
3894
|
}
|
|
3814
3895
|
appServerShimDir = null;
|
|
3815
3896
|
}
|
|
3816
|
-
|
|
3897
|
+
runtimeContext?.cleanup?.();
|
|
3817
3898
|
} finally {
|
|
3818
3899
|
try {
|
|
3819
3900
|
await proxyServer?.close?.();
|
|
@@ -3844,13 +3925,33 @@ async function runRuntimeRotationAppHelper() {
|
|
|
3844
3925
|
}
|
|
3845
3926
|
const clientApiKey = createRuntimeRotationProxyClientApiKey();
|
|
3846
3927
|
proxyServer = await proxyModule.startRuntimeRotationProxy({ clientApiKey });
|
|
3847
|
-
|
|
3848
|
-
process.env
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3928
|
+
const useCanonicalHome =
|
|
3929
|
+
(process.env[APP_RUNTIME_HELPER_USE_CANONICAL_HOME_ENV] ?? "").trim() ===
|
|
3930
|
+
"1";
|
|
3931
|
+
runtimeContext = useCanonicalHome
|
|
3932
|
+
? createRuntimeRotationProxyCanonicalCodexHome(
|
|
3933
|
+
process.env,
|
|
3934
|
+
proxyServer.baseUrl,
|
|
3935
|
+
clientApiKey,
|
|
3936
|
+
configTomlModule,
|
|
3937
|
+
)
|
|
3938
|
+
: createRuntimeRotationProxyCodexHome(
|
|
3939
|
+
process.env,
|
|
3940
|
+
proxyServer.baseUrl,
|
|
3941
|
+
clientApiKey,
|
|
3942
|
+
configTomlModule,
|
|
3943
|
+
);
|
|
3944
|
+
const appServerConfigArgs = useCanonicalHome
|
|
3945
|
+
? [
|
|
3946
|
+
...(runtimeContext.args ?? []),
|
|
3947
|
+
"-c",
|
|
3948
|
+
`model_provider=${configTomlModule.tomlStringLiteral(RUNTIME_ROTATION_PROXY_PROVIDER_ID)}`,
|
|
3949
|
+
]
|
|
3950
|
+
: [];
|
|
3951
|
+
appServerShimDir = installRuntimeRotationAppServerCliShim(
|
|
3952
|
+
runtimeContext.env,
|
|
3953
|
+
appServerConfigArgs,
|
|
3852
3954
|
);
|
|
3853
|
-
appServerShimDir = installRuntimeRotationAppServerCliShim(shadowContext.env);
|
|
3854
3955
|
lastRequestCount = proxyServer.getStatus?.().totalRequests ?? 0;
|
|
3855
3956
|
publishStatus("running");
|
|
3856
3957
|
process.stdout.write(
|
|
@@ -3859,7 +3960,8 @@ async function runRuntimeRotationAppHelper() {
|
|
|
3859
3960
|
pid: process.pid,
|
|
3860
3961
|
baseUrl: proxyServer.baseUrl,
|
|
3861
3962
|
statusPath: resolveRuntimeRotationAppHelperStatusPath(),
|
|
3862
|
-
|
|
3963
|
+
args: runtimeContext.args ?? [],
|
|
3964
|
+
env: pickRuntimeRotationAppHelperEnv(runtimeContext.env),
|
|
3863
3965
|
})}\n`,
|
|
3864
3966
|
);
|
|
3865
3967
|
|
|
@@ -3901,6 +4003,9 @@ function waitForRuntimeRotationAppHelperExit(helper, timeoutMs = 2_000) {
|
|
|
3901
4003
|
if (settled) return;
|
|
3902
4004
|
settled = true;
|
|
3903
4005
|
if (timer) clearTimeout(timer);
|
|
4006
|
+
// Drop the listener when the timeout wins, so a helper that outlives the
|
|
4007
|
+
// graceful window does not keep a live reference back into this process.
|
|
4008
|
+
helper.off?.("close", finish);
|
|
3904
4009
|
resolve();
|
|
3905
4010
|
};
|
|
3906
4011
|
timer = setTimeout(finish, timeoutMs);
|
|
@@ -3908,19 +4013,52 @@ function waitForRuntimeRotationAppHelperExit(helper, timeoutMs = 2_000) {
|
|
|
3908
4013
|
});
|
|
3909
4014
|
}
|
|
3910
4015
|
|
|
3911
|
-
function
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
4016
|
+
function hasRuntimeRotationAppHelperExited(helper) {
|
|
4017
|
+
return helper.exitCode !== null || helper.signalCode !== null;
|
|
4018
|
+
}
|
|
4019
|
+
|
|
4020
|
+
// Releases every handle the helper still holds in this process. The helper is
|
|
4021
|
+
// spawned with piped stdio, so those pipes keep the parent event loop alive on
|
|
4022
|
+
// their own — destroying and unref-ing them is what actually lets `mcodex` return
|
|
4023
|
+
// to the shell when the child ignores or outlives SIGTERM (#647).
|
|
4024
|
+
function releaseRuntimeRotationAppHelperResources(helper) {
|
|
4025
|
+
helper.stdout?.destroy();
|
|
4026
|
+
helper.stderr?.destroy();
|
|
3915
4027
|
try {
|
|
3916
|
-
helper.
|
|
4028
|
+
helper.unref();
|
|
3917
4029
|
} catch {
|
|
3918
|
-
|
|
4030
|
+
// Best-effort only.
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
async function stopRuntimeRotationAppHelper(helper) {
|
|
4035
|
+
if (!helper) {
|
|
4036
|
+
return;
|
|
4037
|
+
}
|
|
4038
|
+
if (hasRuntimeRotationAppHelperExited(helper)) {
|
|
4039
|
+
releaseRuntimeRotationAppHelperResources(helper);
|
|
4040
|
+
return;
|
|
4041
|
+
}
|
|
4042
|
+
if (!helper.killed) {
|
|
4043
|
+
try {
|
|
4044
|
+
helper.kill("SIGTERM");
|
|
4045
|
+
} catch {
|
|
4046
|
+
releaseRuntimeRotationAppHelperResources(helper);
|
|
4047
|
+
return;
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
await waitForRuntimeRotationAppHelperExit(helper);
|
|
4051
|
+
if (!hasRuntimeRotationAppHelperExited(helper)) {
|
|
4052
|
+
try {
|
|
4053
|
+
helper.kill("SIGKILL");
|
|
4054
|
+
} catch {
|
|
4055
|
+
// Best-effort force-stop once the graceful shutdown window has elapsed.
|
|
4056
|
+
}
|
|
3919
4057
|
}
|
|
3920
|
-
|
|
4058
|
+
releaseRuntimeRotationAppHelperResources(helper);
|
|
3921
4059
|
}
|
|
3922
4060
|
|
|
3923
|
-
function startRuntimeRotationAppHelper(baseContext) {
|
|
4061
|
+
function startRuntimeRotationAppHelper(baseContext, options = {}) {
|
|
3924
4062
|
const realCodexHome =
|
|
3925
4063
|
baseContext.originalCodexHome ??
|
|
3926
4064
|
resolveRuntimeRotationProxyOriginalCodexHome(baseContext.env);
|
|
@@ -3940,6 +4078,8 @@ function startRuntimeRotationAppHelper(baseContext) {
|
|
|
3940
4078
|
),
|
|
3941
4079
|
[APP_RUNTIME_HELPER_OWNER_PID_ENV]: String(process.pid),
|
|
3942
4080
|
[APP_RUNTIME_HELPER_REAL_CODEX_HOME_ENV]: realCodexHome,
|
|
4081
|
+
[APP_RUNTIME_HELPER_USE_CANONICAL_HOME_ENV]:
|
|
4082
|
+
options.useCanonicalHome === true ? "1" : "0",
|
|
3943
4083
|
},
|
|
3944
4084
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3945
4085
|
detached: true,
|
|
@@ -4005,8 +4145,14 @@ async function createRuntimeRotationAppHelperContext(
|
|
|
4005
4145
|
options = {},
|
|
4006
4146
|
) {
|
|
4007
4147
|
const startedAt = Date.now();
|
|
4008
|
-
const { helper, message } = await startRuntimeRotationAppHelper(
|
|
4148
|
+
const { helper, message } = await startRuntimeRotationAppHelper(
|
|
4149
|
+
baseContext,
|
|
4150
|
+
options,
|
|
4151
|
+
);
|
|
4009
4152
|
const helperEnv = message.env ?? {};
|
|
4153
|
+
const helperArgs = Array.isArray(message.args)
|
|
4154
|
+
? message.args.filter((arg) => typeof arg === "string")
|
|
4155
|
+
: [];
|
|
4010
4156
|
const detachGraceMs = resolveRuntimeRotationAppHelperDetachGraceMs(baseContext.env);
|
|
4011
4157
|
|
|
4012
4158
|
const cleanup = async ({ exitCode } = {}) => {
|
|
@@ -4023,6 +4169,7 @@ async function createRuntimeRotationAppHelperContext(
|
|
|
4023
4169
|
return {
|
|
4024
4170
|
args: [
|
|
4025
4171
|
...baseContext.args,
|
|
4172
|
+
...helperArgs,
|
|
4026
4173
|
"-c",
|
|
4027
4174
|
`model_provider=${configTomlModule.tomlStringLiteral(RUNTIME_ROTATION_PROXY_PROVIDER_ID)}`,
|
|
4028
4175
|
],
|
|
@@ -4060,9 +4207,13 @@ async function createRuntimeRotationProxyContextIfEnabled(
|
|
|
4060
4207
|
if (isCodexAppCommand(rawArgs)) {
|
|
4061
4208
|
return createRuntimeRotationAppHelperContext(baseContext, configTomlModule);
|
|
4062
4209
|
}
|
|
4063
|
-
if (
|
|
4210
|
+
if (
|
|
4211
|
+
isCodexInteractiveTuiCommand(rawArgs) ||
|
|
4212
|
+
isCodexInteractiveResumeCommand(rawArgs)
|
|
4213
|
+
) {
|
|
4064
4214
|
return createRuntimeRotationAppHelperContext(baseContext, configTomlModule, {
|
|
4065
4215
|
detachOnExit: true,
|
|
4216
|
+
useCanonicalHome: true,
|
|
4066
4217
|
});
|
|
4067
4218
|
}
|
|
4068
4219
|
|
|
@@ -4263,6 +4414,17 @@ function isCodexInteractiveTuiCommand(rawArgs) {
|
|
|
4263
4414
|
return findForwardedCommand(rawArgs) === null;
|
|
4264
4415
|
}
|
|
4265
4416
|
|
|
4417
|
+
// `resume` and `fork` are interactive TUI entry points that happen to carry a
|
|
4418
|
+
// forwarded subcommand, so the bare-invocation predicate above misses them. They
|
|
4419
|
+
// must not take the shadow-home transport: the shadow mirror deliberately omits the
|
|
4420
|
+
// runtime SQLite state (`isRuntimeRotationShadowHomeOmittedEntry`), so the requested
|
|
4421
|
+
// thread is absent from the shadow session index and the resumed TUI hangs on a
|
|
4422
|
+
// blank screen (#647).
|
|
4423
|
+
function isCodexInteractiveResumeCommand(rawArgs) {
|
|
4424
|
+
const command = findForwardedCommand(rawArgs)?.command;
|
|
4425
|
+
return command === "resume" || command === "fork";
|
|
4426
|
+
}
|
|
4427
|
+
|
|
4266
4428
|
function shouldUseRuntimeRoutingForForwardedArgs(rawArgs) {
|
|
4267
4429
|
if (!Array.isArray(rawArgs) || rawArgs.length === 0) {
|
|
4268
4430
|
return true;
|
|
@@ -4302,7 +4464,17 @@ function shouldUseRuntimeRoutingForForwardedArgs(rawArgs) {
|
|
|
4302
4464
|
);
|
|
4303
4465
|
}
|
|
4304
4466
|
|
|
4305
|
-
|
|
4467
|
+
// Request commands still print their help without making a single model
|
|
4468
|
+
// request, so the help form skips the transport entirely: no proxy, no shadow
|
|
4469
|
+
// home, no detached helper. This matters most for the interactive commands,
|
|
4470
|
+
// which detach their helper on a clean exit — help always exits clean, so
|
|
4471
|
+
// `resume --help` would otherwise strand a helper until its idle timeout. It is
|
|
4472
|
+
// keyed off the help flag rather than the command, so a real run still routes
|
|
4473
|
+
// through rotation, and it matches how `app-server` help is handled above (#647).
|
|
4474
|
+
if (
|
|
4475
|
+
requestCommands.has(command.command) &&
|
|
4476
|
+
hasHelpFlagAfterCommand(rawArgs, command.index)
|
|
4477
|
+
) {
|
|
4306
4478
|
return false;
|
|
4307
4479
|
}
|
|
4308
4480
|
if (requestCommands.has(command.command)) {
|
|
@@ -5045,6 +5217,7 @@ async function main() {
|
|
|
5045
5217
|
}
|
|
5046
5218
|
const forwardArgs = forcedAccount.forwardArgs;
|
|
5047
5219
|
|
|
5220
|
+
await ensurePersistedCodexFileAuthStore();
|
|
5048
5221
|
await autoSyncManagerActiveSelectionIfEnabled();
|
|
5049
5222
|
await maybePrintForwardStatusLine(forwardArgs);
|
|
5050
5223
|
maybeRefreshQuotaCacheInBackground();
|