Merge pull request #2719 from Yeachan-Heo/fix/issue-2715-hud-npm-cmd-einval

Fix Windows HUD npm.cmd EINVAL fallback
This commit is contained in:
Bellman
2026-04-18 18:29:39 +09:00
committed by GitHub
7 changed files with 40 additions and 3 deletions

8
dist/__tests__/hud-windows.test.js generated vendored
View File

@@ -53,6 +53,14 @@ describe('HUD Windows Compatibility', () => {
const content = readFileSync(templatePath, 'utf-8');
expect(content).toContain('pathToFileURL(pluginPath).href');
});
it('shared HUD wrapper template uses shell:true only for Windows npm root discovery', () => {
const templatePath = join(packageRoot, 'scripts', 'lib', 'hud-wrapper-template.txt');
const content = readFileSync(templatePath, 'utf-8');
expect(content).toContain('const isWin = process.platform === "win32";');
expect(content).toContain('const npmCommand = isWin ? "npm.cmd" : "npm";');
expect(content).toContain('shell: isWin');
expect(content).not.toContain('shell: true');
});
it('pathToFileURL should correctly convert Unix paths', () => {
const unixPath = '/home/user/test.js';
expect(pathToFileURL(unixPath).href).toBe(process.platform === 'win32'

File diff suppressed because one or more lines are too long

View File

@@ -229,6 +229,13 @@ describe('HUD wrapper — OMC_PLUGIN_ROOT resolution', () => {
expect(txt).not.toContain('Workspace/oh-my-claudecode');
expect(txt).not.toContain('projects/oh-my-claudecode');
});
it('uses shell:true only for Windows npm root discovery', () => {
const txt = readFileSync(TEMPLATE_TXT, 'utf8');
expect(txt).toContain('const isWin = process.platform === "win32";');
expect(txt).toContain('const npmCommand = isWin ? "npm.cmd" : "npm";');
expect(txt).toContain('shell: isWin');
expect(txt).not.toContain('shell: true');
});
});
describe('HUD wrapper — fixture sanity', () => {
it('the template txt file exists in the repo', () => {

File diff suppressed because one or more lines are too long

View File

@@ -46,11 +46,15 @@ function getGlobalNodeModuleRoots() {
}
try {
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
const isWin = process.platform === "win32";
const npmCommand = isWin ? "npm.cmd" : "npm";
const npmRoot = String(execFileSync(npmCommand, ["root", "-g"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
timeout: 1500,
// Node 20.12+ rejects direct .cmd/.bat spawns without a shell on Windows.
// Keep non-Windows behavior unchanged by only enabling shell there.
shell: isWin,
})).trim();
if (npmRoot) roots.unshift(npmRoot);
} catch { /* continue */ }

View File

@@ -63,6 +63,15 @@ describe('HUD Windows Compatibility', () => {
expect(content).toContain('pathToFileURL(pluginPath).href');
});
it('shared HUD wrapper template uses shell:true only for Windows npm root discovery', () => {
const templatePath = join(packageRoot, 'scripts', 'lib', 'hud-wrapper-template.txt');
const content = readFileSync(templatePath, 'utf-8');
expect(content).toContain('const isWin = process.platform === "win32";');
expect(content).toContain('const npmCommand = isWin ? "npm.cmd" : "npm";');
expect(content).toContain('shell: isWin');
expect(content).not.toContain('shell: true');
});
it('pathToFileURL should correctly convert Unix paths', () => {
const unixPath = '/home/user/test.js';
expect(pathToFileURL(unixPath).href).toBe(

View File

@@ -302,6 +302,15 @@ describe('HUD wrapper — OMC_PLUGIN_ROOT resolution', () => {
expect(txt).not.toContain('Workspace/oh-my-claudecode');
expect(txt).not.toContain('projects/oh-my-claudecode');
});
it('uses shell:true only for Windows npm root discovery', () => {
const txt = readFileSync(TEMPLATE_TXT, 'utf8');
expect(txt).toContain('const isWin = process.platform === "win32";');
expect(txt).toContain('const npmCommand = isWin ? "npm.cmd" : "npm";');
expect(txt).toContain('shell: isWin');
expect(txt).not.toContain('shell: true');
});
});
describe('HUD wrapper — fixture sanity', () => {