mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix(platform): detect Windows fnm CLI shims under GUI-launched PATH (#3062)
Scan %LOCALAPPDATA%\fnm\node-versions, fnm_multishells session dirs, and %APPDATA%\npm when building wellKnownUserToolchainBins on Windows so packaged Open Design finds Codex and other npm globals installed via fnm even when launched from Start Menu without an initialized shell PATH.
This commit is contained in:
parent
a6a56099ca
commit
814beb40d3
3 changed files with 77 additions and 0 deletions
|
|
@ -363,6 +363,30 @@ test('resolveAgentExecutable accepts Windows CODEX_BIN overrides with executable
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('resolveAgentExecutable searches Windows fnm multishell shims under a minimal GUI PATH (#3062)', () => {
|
||||||
|
const home = mkdtempSync(join(tmpdir(), 'od-agent-fnm-multishell-'));
|
||||||
|
const localAppData = join(home, 'AppData', 'Local');
|
||||||
|
const fnmMultishell = join(localAppData, 'fnm_multishells', '12345-abcd');
|
||||||
|
try {
|
||||||
|
return withEnvSnapshot(['PATH', 'PATHEXT', 'OD_AGENT_HOME', 'LOCALAPPDATA'], () => {
|
||||||
|
mkdirSync(fnmMultishell, { recursive: true });
|
||||||
|
writeFileSync(join(fnmMultishell, 'codex.CMD'), '@echo off\r\nexit /b 0\r\n');
|
||||||
|
process.env.OD_AGENT_HOME = home;
|
||||||
|
process.env.LOCALAPPDATA = localAppData;
|
||||||
|
process.env.PATH = '';
|
||||||
|
process.env.PATHEXT = '.EXE;.CMD;.BAT';
|
||||||
|
|
||||||
|
const resolved = withPlatform('win32', () =>
|
||||||
|
resolveAgentExecutable(minimalAgentDef({ id: 'codex', bin: 'codex' })),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(resolved, join(fnmMultishell, 'codex.CMD'));
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
rmSync(home, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('detectAgents applies configured env while probing the CLI', async () => {
|
test('detectAgents applies configured env while probing the CLI', async () => {
|
||||||
const dir = mkdtempSync(join(tmpdir(), 'od-agent-env-'));
|
const dir = mkdtempSync(join(tmpdir(), 'od-agent-env-'));
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -625,6 +625,28 @@ export function wellKnownUserToolchainBins(
|
||||||
dirs.push(dir);
|
dirs.push(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
const localAppData =
|
||||||
|
resolveUserScopedHome(env.LOCALAPPDATA, home) ?? join(home, "AppData", "Local");
|
||||||
|
const appData =
|
||||||
|
resolveUserScopedHome(env.APPDATA, home) ?? join(home, "AppData", "Roaming");
|
||||||
|
dirs.push(join(appData, "npm"));
|
||||||
|
const fnmDir = typeof env.FNM_DIR === "string" ? env.FNM_DIR.trim() : "";
|
||||||
|
for (const root of [
|
||||||
|
join(localAppData, "fnm", "node-versions"),
|
||||||
|
...(fnmDir.length > 0 ? [join(fnmDir, "node-versions")] : []),
|
||||||
|
]) {
|
||||||
|
for (const dir of existingChildBinDirs(root, ["installation", "bin"])) {
|
||||||
|
dirs.push(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fnm exposes npm-global CLIs via per-shell shims under fnm_multishells
|
||||||
|
// after `fnm env`. GUI-launched Electron inherits a stripped PATH without
|
||||||
|
// those ephemeral dirs (issue #3062).
|
||||||
|
for (const dir of existingChildBinDirs(join(localAppData, "fnm_multishells"), [])) {
|
||||||
|
dirs.push(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -669,4 +669,35 @@ describe("wellKnownUserToolchainBins", () => {
|
||||||
rmSync(home, { recursive: true, force: true });
|
rmSync(home, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("includes Windows fnm node installs, multishell shims, and npm globals (#3062)", () => {
|
||||||
|
const originalPlatform = process.platform;
|
||||||
|
Object.defineProperty(process, "platform", { configurable: true, value: "win32" });
|
||||||
|
const home = mkdtempSync(join(tmpdir(), "wkutb-win-fnm-"));
|
||||||
|
const localAppData = join(home, "AppData", "Local");
|
||||||
|
const appData = join(home, "AppData", "Roaming");
|
||||||
|
const fnmNodeBin = join(localAppData, "fnm", "node-versions", "v20.20.2", "installation", "bin");
|
||||||
|
const fnmMultishell = join(localAppData, "fnm_multishells", "12345-abcd");
|
||||||
|
const npmGlobal = join(appData, "npm");
|
||||||
|
try {
|
||||||
|
mkdirSync(fnmNodeBin, { recursive: true });
|
||||||
|
mkdirSync(fnmMultishell, { recursive: true });
|
||||||
|
mkdirSync(npmGlobal, { recursive: true });
|
||||||
|
writeFileSync(join(fnmNodeBin, "marker"), "");
|
||||||
|
writeFileSync(join(fnmMultishell, "marker"), "");
|
||||||
|
writeFileSync(join(npmGlobal, "marker"), "");
|
||||||
|
|
||||||
|
const dirs = wellKnownUserToolchainBins({
|
||||||
|
home,
|
||||||
|
env: { LOCALAPPDATA: localAppData, APPDATA: appData },
|
||||||
|
includeSystemBins: false,
|
||||||
|
});
|
||||||
|
expect(dirs).toContain(fnmNodeBin);
|
||||||
|
expect(dirs).toContain(fnmMultishell);
|
||||||
|
expect(dirs).toContain(npmGlobal);
|
||||||
|
} finally {
|
||||||
|
Object.defineProperty(process, "platform", { configurable: true, value: originalPlatform });
|
||||||
|
rmSync(home, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue