Skip to content

Commit 0de3ee5

Browse files
fix: harden runtime shadow startup
Avoid copying optional generated Codex home directories into runtime shadow homes unless explicitly requested, keep app helpers pointed at the real multi-auth state, and skip already-indexed rollout logs during session index repair so real-home wrapper startup stays fast. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent b445c73 commit 0de3ee5

2 files changed

Lines changed: 281 additions & 6 deletions

File tree

scripts/codex.js

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ const RUNTIME_ROTATION_SHADOW_HOME_OMIT_STATE_FILES = new Set([
4242
"accounts.json",
4343
]);
4444
const RUNTIME_ROTATION_SHADOW_HOME_OMIT_ROOT_DIRS = new Set(["multi-auth"]);
45+
const RUNTIME_ROTATION_SHADOW_HOME_LINK_ONLY_ROOT_DIRS = new Set([
46+
".sandbox",
47+
".sandbox-bin",
48+
".sandbox-secrets",
49+
".tmp",
50+
"ambient-suggestions",
51+
"archived_sessions",
52+
"backups",
53+
"cache",
54+
"generated_images",
55+
"log",
56+
"sqlite",
57+
"tmp",
58+
"understand-anything",
59+
"vendor_imports",
60+
]);
4561
const SHADOW_HOME_STATE_FILE_SET = new Set(SHADOW_HOME_STATE_FILES);
4662
const SHADOW_HOME_CONFIG_FILE = "config.toml";
4763
const SHADOW_HOME_SYNC_LOCK_DIR = ".codex-multi-auth-shadow-sync.lock";
@@ -91,6 +107,7 @@ const shadowHomeCleanupRetryMarkerDir =
91107
let warnedInvalidRuntimeRotationProxyEnv = false;
92108
let warnedPendingAccountReadIdOverflow = false;
93109
let warnedShadowHomeSqliteLinkFailure = false;
110+
const warnedShadowHomeLinkOnlyDirectoryFailures = new Set();
94111
const warnedShadowHomeSqliteSidecarPlaceholderFailures = new Set();
95112

96113
async function loadRuntimeConstants() {
@@ -1868,6 +1885,41 @@ function mirrorDirectoryIntoShadowHome(sourcePath, destinationPath) {
18681885
return "copied";
18691886
}
18701887

1888+
function linkDirectoryIntoShadowHome(sourcePath, destinationPath) {
1889+
try {
1890+
if ((process.env.CODEX_MULTI_AUTH_TEST_FORCE_SHADOW_DIR_COPY ?? "").trim() === "1") {
1891+
throw new Error("simulated directory link failure");
1892+
}
1893+
symlinkSync(
1894+
sourcePath,
1895+
destinationPath,
1896+
process.platform === "win32" ? "junction" : "dir",
1897+
);
1898+
return true;
1899+
} catch {
1900+
return false;
1901+
}
1902+
}
1903+
1904+
function warnSkippedLinkOnlyShadowHomeDirectory(name) {
1905+
if (warnedShadowHomeLinkOnlyDirectoryFailures.has(name)) {
1906+
return;
1907+
}
1908+
warnedShadowHomeLinkOnlyDirectoryFailures.add(name);
1909+
console.error(
1910+
`codex-multi-auth: skipped optional shadow-home directory ${name} because linking failed; refusing to copy generated runtime data.`,
1911+
);
1912+
}
1913+
1914+
function shouldCopyRuntimeGeneratedShadowHomeDirectoryFallback() {
1915+
const normalized = (
1916+
process.env.CODEX_MULTI_AUTH_RUNTIME_SHADOW_COPY_GENERATED_DIRS ?? ""
1917+
)
1918+
.trim()
1919+
.toLowerCase();
1920+
return normalized === "1" || normalized === "true" || normalized === "yes";
1921+
}
1922+
18711923
function linkFileIntoShadowHome(sourcePath, destinationPath) {
18721924
try {
18731925
symlinkSync(sourcePath, destinationPath, "file");
@@ -1913,8 +1965,11 @@ function isCodexRuntimeLocalSqliteFile(name) {
19131965

19141966
function isCodexRuntimeTransientStateFile(name) {
19151967
const normalizedName = normalizeRuntimeShadowHomeEntryName(name);
1916-
return /^(?:auth|accounts)\.json\.\d+\.[a-z0-9]+\.tmp$/.test(
1917-
normalizedName,
1968+
return (
1969+
/^(?:auth|accounts)\.json\.\d+\.[a-z0-9]+\.tmp$/.test(
1970+
normalizedName,
1971+
) ||
1972+
/^\.codex-global-state\.json\.tmp-[a-z0-9-]+$/.test(normalizedName)
19181973
);
19191974
}
19201975

@@ -1927,6 +1982,11 @@ function isRuntimeRotationShadowHomeOmittedEntry(name) {
19271982
);
19281983
}
19291984

1985+
function isRuntimeRotationShadowHomeLinkOnlyDirectory(name) {
1986+
const normalizedName = normalizeRuntimeShadowHomeEntryName(name);
1987+
return RUNTIME_ROTATION_SHADOW_HOME_LINK_ONLY_ROOT_DIRS.has(normalizedName);
1988+
}
1989+
19301990
function shouldMaterializeFileIntoShadowHome(name) {
19311991
return isSqliteMainFile(name) || isSqliteSidecarFile(name);
19321992
}
@@ -2154,6 +2214,8 @@ function createShadowHomeMirror(
21542214
const skipSyncBackNames = new Set(options.skipSyncBackNames ?? []);
21552215
const skipMirrorPredicate = options.skipMirrorPredicate ?? (() => false);
21562216
const skipSyncBackPredicate = options.skipSyncBackPredicate ?? (() => false);
2217+
const linkOnlyDirectoryPredicate =
2218+
options.linkOnlyDirectoryPredicate ?? (() => false);
21572219
const originalFileStates = new Map();
21582220
const copiedDirectoryNames = new Set();
21592221
const rememberSyncFile = (name) => {
@@ -2200,6 +2262,15 @@ function createShadowHomeMirror(
22002262
throw new Error(`Expected ${name} to be a file`);
22012263
}
22022264
if (directoryLike) {
2265+
if (
2266+
linkOnlyDirectoryPredicate(name) &&
2267+
!shouldCopyRuntimeGeneratedShadowHomeDirectoryFallback()
2268+
) {
2269+
if (!linkDirectoryIntoShadowHome(sourcePath, destinationPath)) {
2270+
warnSkippedLinkOnlyShadowHomeDirectory(name);
2271+
}
2272+
continue;
2273+
}
22032274
if (mirrorDirectoryIntoShadowHome(sourcePath, destinationPath) === "copied") {
22042275
copiedDirectoryNames.add(name);
22052276
}
@@ -2309,6 +2380,10 @@ function resolveOriginalMultiAuthDir(env) {
23092380
return undefined;
23102381
}
23112382

2383+
function resolveRuntimeRotationOriginalMultiAuthDir(originalCodexHome, env) {
2384+
return resolveOriginalMultiAuthDir(env) ?? join(originalCodexHome, "multi-auth");
2385+
}
2386+
23122387
function parseRuntimeRotationProxyEnv(value) {
23132388
if (value === undefined) return undefined;
23142389
const normalized = value.trim().toLowerCase();
@@ -2421,6 +2496,7 @@ function createRuntimeRotationProxyCodexHome(
24212496
skipMirrorPredicate: isRuntimeRotationShadowHomeOmittedEntry,
24222497
skipSyncBackNames: RUNTIME_ROTATION_SHADOW_HOME_OMIT_STATE_FILES,
24232498
skipSyncBackPredicate: isRuntimeRotationShadowHomeOmittedEntry,
2499+
linkOnlyDirectoryPredicate: isRuntimeRotationShadowHomeLinkOnlyDirectory,
24242500
},
24252501
);
24262502
omitRuntimeRotationShadowHomeStateFiles(shadowCodexHome);
@@ -2445,11 +2521,11 @@ function createRuntimeRotationProxyCodexHome(
24452521
...baseEnv,
24462522
CODEX_HOME: shadowCodexHome,
24472523
OPENAI_API_KEY: clientApiKey,
2524+
CODEX_MULTI_AUTH_DIR: resolveRuntimeRotationOriginalMultiAuthDir(
2525+
originalCodexHome,
2526+
baseEnv,
2527+
),
24482528
};
2449-
const originalMultiAuthDir = resolveOriginalMultiAuthDir(baseEnv);
2450-
if (originalMultiAuthDir) {
2451-
forwardedEnv.CODEX_MULTI_AUTH_DIR = originalMultiAuthDir;
2452-
}
24532529

24542530
return {
24552531
env: forwardedEnv,
@@ -2904,6 +2980,10 @@ function startRuntimeRotationAppHelper(baseContext) {
29042980
{
29052981
env: {
29062982
...baseContext.env,
2983+
CODEX_MULTI_AUTH_DIR: resolveRuntimeRotationOriginalMultiAuthDir(
2984+
realCodexHome,
2985+
baseContext.env,
2986+
),
29072987
[APP_RUNTIME_HELPER_OWNER_PID_ENV]: String(process.pid),
29082988
[APP_RUNTIME_HELPER_REAL_CODEX_HOME_ENV]: realCodexHome,
29092989
},
@@ -3632,6 +3712,8 @@ function repairCodexSessionIndex(codexHome) {
36323712

36333713
const additions = [];
36343714
for (const rolloutPath of collectRolloutFiles(sessionsDir)) {
3715+
const idFromName = extractRolloutIdFromFilename(basename(rolloutPath));
3716+
if (idFromName && seen.has(idFromName)) continue;
36353717
const entry = parseRolloutIndexEntry(rolloutPath);
36363718
if (!entry || seen.has(entry.id)) continue;
36373719
seen.add(entry.id);

0 commit comments

Comments
 (0)