This commit is contained in:
Oleg Maslov
2026-09-02 10:14:22 +02:00
parent 0c3e2ead3b
commit b20b138fe4
771 changed files with 161561 additions and 9027 deletions

View File

@@ -8,6 +8,7 @@
import { describe, it, expect } from 'vitest';
import { SUPPORTED_TOOLS, type ToolId } from '@waggle/shared';
import {
defaultExecVersion,
detectInstalledTools,
selectPathLookupCandidate,
type ToolDetectionDeps,
@@ -15,7 +16,11 @@ import {
import { resolveToolCommandInvocation } from '../src/tool-command.js';
import type { ManifestLoaderDeps } from '../src/tool-manifest-loader.js';
type DetectOpts = ToolDetectionDeps & { manifestLoader?: ManifestLoaderDeps };
type WindowsAppExecutables = Readonly<Record<string, readonly string[]>>;
type DetectOpts = ToolDetectionDeps & {
manifestLoader?: ManifestLoaderDeps;
windowsAppExecutables?: () => WindowsAppExecutables | Promise<WindowsAppExecutables>;
};
/**
* Build a deps object that defaults to "nothing exists anywhere".
@@ -26,18 +31,118 @@ function makeDeps(overrides: Partial<DetectOpts> = {}): DetectOpts {
return {
platform: 'win32',
home: 'C:\\Users\\test',
env: {},
cwd: 'D:\\projects\\waggle-os',
exists: async () => false,
execVersion: async () => null,
readJson: async () => null,
pathFromEnv: () => null,
windowsAppExecutables: () => ({}),
// Hermetic: no third-party adapters unless a test injects them.
manifestLoader: { readDir: () => [] },
...overrides,
};
}
type ClaudeHookCommandBuilder = (basename: string, scriptPath: string) => string;
function activeClaudeHookSettings(
commandBuilder: ClaudeHookCommandBuilder = (_basename, scriptPath) => `node "${scriptPath}"`,
) {
const group = (basename: string) => [{
_hiveMindShim: '@hive-mind/claude-code-hooks',
hooks: [{
type: 'command',
command: commandBuilder(
basename,
`/opt/waggle/hive-mind-hooks-claude-code/dist/hooks/${basename}.js`,
),
}],
}];
return {
hooks: {
SessionStart: group('session-start'),
UserPromptSubmit: group('user-prompt-submit'),
Stop: group('stop'),
PreCompact: group('pre-compact'),
},
};
}
function markerStrippedClaudeHookSettings(
packageName = 'hive-mind-hooks-claude-code',
commandBuilder: ClaudeHookCommandBuilder = (_basename, scriptPath) => `node "${scriptPath}"`,
entryType = 'command',
) {
const group = (basename: string) => [{
hooks: [{
type: entryType,
command: commandBuilder(
basename,
`D:\\Waggle\\packages\\${packageName}\\dist\\hooks\\${basename}.js`,
),
}],
}];
return {
hooks: {
SessionStart: group('session-start'),
UserPromptSubmit: group('user-prompt-submit'),
Stop: group('stop'),
PreCompact: group('pre-compact'),
},
};
}
async function detectClaudeHookStatus(
settingsValue: unknown,
platform: NodeJS.Platform = 'win32',
): Promise<boolean | undefined> {
const windows = platform === 'win32';
const home = windows ? 'C:\\Users\\test' : '/Users/test';
const installed = windows ? `${home}\\AppData\\Roaming\\npm\\claude.cmd` : '/usr/local/bin/claude';
const pointer = windows ? `${home}\\.claude\\hive-mind-install.json` : `${home}/.claude/hive-mind-install.json`;
const backup = windows
? `${home}\\.claude\\settings.json.hive-mind-backup.X`
: `${home}/.claude/settings.json.hive-mind-backup.X`;
const settings = windows ? `${home}\\.claude\\settings.json` : `${home}/.claude/settings.json`;
const existsSet = new Set([installed, pointer, backup, settings]);
const result = await detectInstalledTools(makeDeps({
platform,
home,
exists: async (candidate) => existsSet.has(candidate),
pathFromEnv: () => installed,
execVersion: async () => 'claude 2.1.214',
readJson: async (candidate) => {
if (candidate === pointer) return { settings_backup: backup };
if (candidate === settings) return settingsValue;
return null;
},
}));
return result.tools.find((tool) => tool.id === 'claude-code')?.hooksInstalled;
}
describe('detectInstalledTools', () => {
it('does not expose ambient secrets to the production version probe', async () => {
const previousOpenAi = process.env.OPENAI_API_KEY;
const previousUnknown = process.env.WAGGLE_FUTURE_PROVIDER_SECRET;
process.env.OPENAI_API_KEY = 'must-not-reach-version-probe';
process.env.WAGGLE_FUTURE_PROVIDER_SECRET = 'must-also-be-denied';
try {
const result = await defaultExecVersion(process.execPath, [
'-e',
"process.stdout.write(JSON.stringify({ openai: process.env.OPENAI_API_KEY ?? null, unknown: process.env.WAGGLE_FUTURE_PROVIDER_SECRET ?? null, hasPath: Boolean(process.env.PATH) }))",
]);
expect(result).not.toBeNull();
expect(JSON.parse(result!)).toEqual({ openai: null, unknown: null, hasPath: true });
} finally {
if (previousOpenAi === undefined) delete process.env.OPENAI_API_KEY;
else process.env.OPENAI_API_KEY = previousOpenAi;
if (previousUnknown === undefined) delete process.env.WAGGLE_FUTURE_PROVIDER_SECRET;
else process.env.WAGGLE_FUTURE_PROVIDER_SECRET = previousUnknown;
}
});
it('returns an envelope covering every supported tool', async () => {
const result = await detectInstalledTools(makeDeps());
const ids = result.tools.map((t) => t.id);
@@ -97,10 +202,11 @@ describe('detectInstalledTools', () => {
expect(result.tools).toHaveLength(SUPPORTED_TOOLS.length + 1);
});
it('carries canonical task capabilities for headless and GUI-only built-ins', async () => {
it('carries canonical task capabilities and release status for built-ins', async () => {
const result = await detectInstalledTools(makeDeps());
const codex = result.tools.find((tool) => tool.id === 'codex');
const cursor = result.tools.find((tool) => tool.id === 'cursor');
const openclaw = result.tools.find((tool) => tool.id === 'openclaw');
expect(codex?.capabilities).toMatchObject({
interactiveLaunch: true,
@@ -116,6 +222,16 @@ describe('detectInstalledTools', () => {
resumable: false,
});
expect(cursor?.permissionModes).toEqual([]);
expect(cursor).toMatchObject({
releaseStatus: 'roadmap',
launchable: false,
hookCapable: false,
});
expect(openclaw).toMatchObject({
releaseStatus: 'roadmap',
launchable: false,
hookCapable: false,
});
});
it('reports platform and ISO detectedAt', async () => {
@@ -179,12 +295,13 @@ describe('claude-code detector', () => {
expect(t.version).toBe('1.2.3');
});
it('reports hooksInstalled=true when the hive-mind pointer file is present and references an existing backup', async () => {
it('reports hooksInstalled=true when the pointer, backup, and active Claude hooks are healthy', async () => {
const installed = '/usr/local/bin/claude';
const home = '/Users/test';
const pointer = '/Users/test/.claude/hive-mind-install.json';
const backup = '/Users/test/.claude/settings.json.hive-mind-backup.X';
const existsSet = new Set([installed, pointer, backup]);
const settings = '/Users/test/.claude/settings.json';
const existsSet = new Set([installed, pointer, backup, settings]);
const result = await detectInstalledTools(
makeDeps({
@@ -193,7 +310,11 @@ describe('claude-code detector', () => {
exists: async (p) => existsSet.has(p),
pathFromEnv: () => installed,
execVersion: async () => 'claude 1.2.3',
readJson: async (p) => (p === pointer ? { settings_backup: backup } : null),
readJson: async (p) => {
if (p === pointer) return { settings_backup: backup };
if (p === settings) return activeClaudeHookSettings();
return null;
},
}),
);
const t = result.tools.find((x) => x.id === 'claude-code')!;
@@ -201,6 +322,187 @@ describe('claude-code detector', () => {
expect(t.hookPointerPath).toBe(pointer);
});
it('keeps hooksInstalled=true after Claude strips private markers from Waggle hook groups', async () => {
const installed = 'C:\\Users\\test\\AppData\\Roaming\\npm\\claude.cmd';
const pointer = 'C:\\Users\\test\\.claude\\hive-mind-install.json';
const backup = 'C:\\Users\\test\\.claude\\settings.json.hive-mind-backup.X';
const settings = 'C:\\Users\\test\\.claude\\settings.json';
const existsSet = new Set([installed, pointer, backup, settings]);
const result = await detectInstalledTools(makeDeps({
exists: async (candidate) => existsSet.has(candidate),
pathFromEnv: () => installed,
execVersion: async () => 'claude 2.1.214',
readJson: async (candidate) => {
if (candidate === pointer) return { settings_backup: backup };
if (candidate === settings) return markerStrippedClaudeHookSettings();
return null;
},
}));
expect(result.tools.find((tool) => tool.id === 'claude-code')?.hooksInstalled).toBe(true);
});
it.each([
[
'a pinned mixed-case Node executable, hook path, and cli path',
(_basename: string, scriptPath: string) => {
const spacedPath = scriptPath.replace('D:\\Waggle', 'D:\\Program Files\\Waggle').toUpperCase();
return `"C:\\Program Files\\nodejs\\node.EXE" "${spacedPath}" --cli-path "D:\\Program Files\\Hive Mind\\cli.JS"`;
},
],
[
'safe unquoted absolute paths without spaces',
(_basename: string, scriptPath: string) => `C:\\Node\\node.exe ${scriptPath} --cli-path D:\\HiveMind\\cli.js`,
],
])('accepts marker-stripped hooks using %s', async (_label, commandBuilder) => {
expect(await detectClaudeHookStatus(
markerStrippedClaudeHookSettings('hive-mind-hooks-claude-code', commandBuilder),
)).toBe(true);
});
it('accepts a canonical marker-stripped POSIX command', async () => {
const settings = markerStrippedClaudeHookSettings(
'hive-mind-hooks-claude-code',
(basename) =>
`"/usr/local/bin/node" "/opt/waggle/hive-mind-hooks-claude-code/dist/hooks/${basename}.js" --cli-path "/opt/waggle/hive-mind-cli.js"`,
);
expect(await detectClaudeHookStatus(settings, 'linux')).toBe(true);
});
it('finds the canonical command entry when Claude preserves another entry first', async () => {
const settings = markerStrippedClaudeHookSettings();
for (const groups of Object.values(settings.hooks)) {
groups[0].hooks.unshift({ type: 'prompt', command: 'not executable' });
}
expect(await detectClaudeHookStatus(settings)).toBe(true);
});
it.each<Array<[string, ClaudeHookCommandBuilder]>>([
['echo text', (_basename, scriptPath) => `echo "${scriptPath}"`],
['a Node wrapper comment', (_basename, scriptPath) => `node "D:\\wrapper.js" --comment "${scriptPath}"`],
['a cmd wrapper', (_basename, scriptPath) => `cmd /c node "${scriptPath}"`],
['a PowerShell wrapper', (_basename, scriptPath) => `powershell -Command node "${scriptPath}"`],
['node -e text', (_basename, scriptPath) => `node -e "${scriptPath}"`],
['a backup extension', (_basename, scriptPath) => `node "${scriptPath}.bak"`],
['the wrong hook basename', (_basename, scriptPath) => `node "${scriptPath.replace(/[^\\]+\.js$/, 'other.js')}"`],
['an unknown argument', (_basename, scriptPath) => `node "${scriptPath}" --verbose`],
['a shell AND chain', (_basename, scriptPath) => `node "${scriptPath}" && echo done`],
['a shell semicolon chain', (_basename, scriptPath) => `node "${scriptPath}"; echo done`],
['a shell pipe', (_basename, scriptPath) => `node "${scriptPath}" | tee out`],
['a shell redirect', (_basename, scriptPath) => `node "${scriptPath}" > out`],
['a newline command', (_basename, scriptPath) => `node "${scriptPath}"\necho done`],
['an unmatched quote', (_basename, scriptPath) => `node "${scriptPath}`],
[
'an unquoted path with spaces',
(_basename, scriptPath) => `node ${scriptPath.replace('D:\\Waggle', 'D:\\Program Files\\Waggle')}`,
],
])('rejects marker-stripped hook commands containing %s', async (_label, commandBuilder) => {
expect(await detectClaudeHookStatus(
markerStrippedClaudeHookSettings('hive-mind-hooks-claude-code', commandBuilder),
)).toBe(false);
});
it('rejects a canonical-looking entry whose type is not command', async () => {
expect(await detectClaudeHookStatus(
markerStrippedClaudeHookSettings(
'hive-mind-hooks-claude-code',
(_basename, scriptPath) => `node "${scriptPath}"`,
'prompt',
),
)).toBe(false);
});
it('rejects an arbitrary same-basename script even when the Waggle marker is present', async () => {
const settings = activeClaudeHookSettings(
(basename) => `node "C:\\malware\\${basename}.js"`,
);
expect(await detectClaudeHookStatus(settings)).toBe(false);
});
it.each<Array<[string, ClaudeHookCommandBuilder]>>([
[
'quoted command substitution',
(basename) => `node "/tmp/$(echo owned)/hive-mind-hooks-claude-code/dist/hooks/${basename}.js"`,
],
[
'quoted backtick substitution',
(basename) => `node "/tmp/` + '`echo owned`' + `/hive-mind-hooks-claude-code/dist/hooks/${basename}.js"`,
],
[
'unquoted command substitution',
(basename) => `node /tmp/$(echo)/hive-mind-hooks-claude-code/dist/hooks/${basename}.js`,
],
[
'an unquoted glob',
(basename) => `node /opt/*/hive-mind-hooks-claude-code/dist/hooks/${basename}.js`,
],
])('rejects POSIX hook paths containing %s', async (_label, commandBuilder) => {
const settings = markerStrippedClaudeHookSettings(
'hive-mind-hooks-claude-code',
commandBuilder,
);
expect(await detectClaudeHookStatus(settings, 'linux')).toBe(false);
});
it('rejects node.exe as a POSIX hook executable', async () => {
const settings = markerStrippedClaudeHookSettings(
'hive-mind-hooks-claude-code',
(basename) =>
`/usr/local/bin/node.exe /opt/waggle/hive-mind-hooks-claude-code/dist/hooks/${basename}.js`,
);
expect(await detectClaudeHookStatus(settings, 'linux')).toBe(false);
});
it('rejects marker-stripped hook commands from a lookalike package', async () => {
const installed = 'C:\\Users\\test\\AppData\\Roaming\\npm\\claude.cmd';
const pointer = 'C:\\Users\\test\\.claude\\hive-mind-install.json';
const backup = 'C:\\Users\\test\\.claude\\settings.json.hive-mind-backup.X';
const settings = 'C:\\Users\\test\\.claude\\settings.json';
const existsSet = new Set([installed, pointer, backup, settings]);
const result = await detectInstalledTools(makeDeps({
exists: async (candidate) => existsSet.has(candidate),
pathFromEnv: () => installed,
execVersion: async () => 'claude 2.1.214',
readJson: async (candidate) => {
if (candidate === pointer) return { settings_backup: backup };
if (candidate === settings) {
return markerStrippedClaudeHookSettings('hive-mind-hooks-claude-code-copy');
}
return null;
},
}));
expect(result.tools.find((tool) => tool.id === 'claude-code')?.hooksInstalled).toBe(false);
});
it('reports hooksInstalled=false when a stale pointer survives but active Claude hooks are gone', async () => {
const installed = '/usr/local/bin/claude';
const pointer = '/Users/test/.claude/hive-mind-install.json';
const backup = '/Users/test/.claude/settings.json.hive-mind-backup.X';
const settings = '/Users/test/.claude/settings.json';
const existsSet = new Set([installed, pointer, backup, settings]);
const result = await detectInstalledTools(makeDeps({
platform: 'darwin',
home: '/Users/test',
exists: async (candidate) => existsSet.has(candidate),
pathFromEnv: () => installed,
execVersion: async () => 'claude 1.2.3',
readJson: async (candidate) => {
if (candidate === pointer) return { settings_backup: backup };
if (candidate === settings) return { hooks: {} };
return null;
},
}));
expect(result.tools.find((tool) => tool.id === 'claude-code')).toMatchObject({
hooksInstalled: false,
hookPointerPath: pointer,
});
});
it('reports hooksInstalled=false when the pointer exists but its backup is gone (partial rollback)', async () => {
const installed = '/usr/local/bin/claude';
const home = '/Users/test';
@@ -322,12 +624,43 @@ describe('claude-desktop detector', () => {
expect(t.installed).toBe(true);
expect(t.installedPath).toBe(installed);
});
it('detects Claude Desktop from its registered Windows AppX executable', async () => {
const installed =
'C:\\Program Files\\WindowsApps\\Claude_1.22209.0.0_x64__pzs8sxrjxfjjc\\app\\Claude.exe';
const result = await detectInstalledTools(
makeDeps({
platform: 'win32',
exists: async (p) => p === installed,
windowsAppExecutables: () => ({ 'claude-desktop': [installed] }),
}),
);
const t = result.tools.find((x) => x.id === 'claude-desktop')!;
expect(t.installed).toBe(true);
expect(t.installedPath).toBe(installed);
});
it('keeps conventional detection available when AppX discovery throws synchronously', async () => {
const installed =
'C:\\Users\\test\\AppData\\Local\\AnthropicClaude\\Claude.exe';
const result = await detectInstalledTools(
makeDeps({
platform: 'win32',
exists: async (p) => p === installed,
windowsAppExecutables: () => { throw new Error('AppX unavailable'); },
}),
);
expect(result.tools.find((tool) => tool.id === 'claude-desktop')).toMatchObject({
installed: true,
installedPath: installed,
});
});
});
describe('extended-cohort detectors (codex / codex-desktop / hermes / openclaw — Phase 4)', () => {
describe('extended-cohort detectors (Codex / Hermes / OpenClaw — Phase 4)', () => {
// Default makeDeps reports nothing installed — the envelope is still
// present per the stable-shape contract.
it.each<ToolId>(['codex', 'codex-desktop', 'hermes', 'openclaw'])(
it.each<ToolId>(['codex', 'codex-desktop', 'hermes', 'hermes-desktop', 'openclaw'])(
'reports %s as not installed on a clean machine',
async (id) => {
const result = await detectInstalledTools(makeDeps());
@@ -413,6 +746,166 @@ describe('extended-cohort detectors (codex / codex-desktop / hermes / openclaw
expect(t.version).toBe('0.2.1');
});
it('detects a healthy Hermes Windows fallback when PATH is empty', async () => {
const installed =
'C:\\Users\\test\\AppData\\Local\\hermes\\hermes-agent\\venv\\Scripts\\hermes.exe';
const result = await detectInstalledTools(
makeDeps({
exists: async (p) => p === installed,
execVersion: async (binary) => binary === installed ? '0.2.1' : null,
}),
);
expect(result.tools.find((tool) => tool.id === 'hermes')).toMatchObject({
installed: true,
installedPath: installed,
version: '0.2.1',
launchable: true,
});
});
it('uses the direct HERMES_HOME Windows executable fallback and hook pointer', async () => {
const hermesHome = 'D:\\Hermes Data';
const installed = `${hermesHome}\\hermes-agent\\venv\\Scripts\\hermes.exe`;
const pointer = `${hermesHome}\\hive-mind-install.json`;
const backup = `${hermesHome}\\config.yaml.hive-mind-backup.X`;
const existsSet = new Set([installed, pointer, backup]);
const result = await detectInstalledTools(makeDeps({
env: {
HERMES_HOME: hermesHome,
LOCALAPPDATA: 'C:\\Users\\test\\AppData\\Local',
},
exists: async (candidate) => existsSet.has(candidate),
execVersion: async (binary) => binary === installed ? '0.18.2' : null,
readJson: async (candidate) => candidate === pointer
? { settings_backup: backup }
: null,
}));
expect(result.tools.find((tool) => tool.id === 'hermes')).toMatchObject({
installed: true,
installedPath: installed,
version: '0.18.2',
hooksInstalled: true,
hookPointerPath: pointer,
});
});
it('uses redirected LOCALAPPDATA for the Windows CLI fallback and hook pointer', async () => {
const localAppData = 'E:\\Redirected\\Local';
const hermesHome = `${localAppData}\\hermes`;
const installed = `${hermesHome}\\hermes-agent\\venv\\Scripts\\hermes.exe`;
const pointer = `${hermesHome}\\hive-mind-install.json`;
const configPath = `${hermesHome}\\config.yaml`;
const existsSet = new Set([installed, pointer, configPath]);
const result = await detectInstalledTools(makeDeps({
env: { LOCALAPPDATA: localAppData },
exists: async (candidate) => existsSet.has(candidate),
execVersion: async (binary) => binary === installed ? '0.18.2' : null,
readJson: async (candidate) => candidate === pointer
? { settings_backup: null, created_by_us: true, config_path: configPath }
: null,
}));
expect(result.tools.find((tool) => tool.id === 'hermes')).toMatchObject({
installed: true,
installedPath: installed,
version: '0.18.2',
hooksInstalled: true,
hookPointerPath: pointer,
});
});
it('uses HERMES_HOME for the bundled Windows desktop app', async () => {
const hermesHome = 'D:\\Hermes Data';
const desktop = `${hermesHome}\\hermes-agent\\apps\\desktop\\release\\win-unpacked\\Hermes.exe`;
const result = await detectInstalledTools(makeDeps({
env: { HERMES_HOME: hermesHome },
exists: async (candidate) => candidate === desktop,
}));
expect(result.tools.find((tool) => tool.id === 'hermes-desktop')).toMatchObject({
installed: true,
installedPath: desktop,
launchable: true,
});
});
it('skips a broken PATH Hermes shim for a healthy direct Windows executable', async () => {
const broken = 'C:\\broken\\hermes.exe';
const healthy = 'C:\\Users\\test\\AppData\\Local\\hermes\\hermes-agent\\venv\\Scripts\\hermes.exe';
const result = await detectInstalledTools(
makeDeps({
exists: async (p) => p === broken || p === healthy,
pathFromEnv: (name) => name === 'hermes' ? broken : null,
execVersion: async (binary) => binary === healthy ? '0.2.1' : null,
}),
);
expect(result.tools.find((tool) => tool.id === 'hermes')).toMatchObject({
installed: true,
installedPath: healthy,
version: '0.2.1',
launchable: true,
});
});
it('reports an all-broken Hermes Windows install as unlaunchable', async () => {
const broken = 'C:\\broken\\hermes.exe';
const fallback =
'C:\\Users\\test\\AppData\\Local\\hermes\\hermes-agent\\venv\\Scripts\\hermes.exe';
const result = await detectInstalledTools(
makeDeps({
exists: async (p) => p === broken || p === fallback,
pathFromEnv: (name) => name === 'hermes' ? broken : null,
}),
);
const tool = result.tools.find((candidate) => candidate.id === 'hermes');
expect(tool).toMatchObject({
installed: true,
installedPath: broken,
version: null,
launchable: false,
});
expect(tool?.diagnostic).toMatch(/hermes doctor|reinstall Hermes/i);
});
it('separates an installed Hermes Desktop from a broken Hermes CLI', async () => {
const cli = 'C:\\Users\\test\\AppData\\Local\\hermes\\bin\\hermes.cmd';
const desktop =
'C:\\Users\\test\\AppData\\Local\\hermes\\hermes-agent\\apps\\desktop\\release\\win-unpacked\\Hermes.exe';
const versionProbes: string[] = [];
const result = await detectInstalledTools(
makeDeps({
exists: async (p) => p === cli || p === desktop,
pathFromEnv: (name) => name === 'hermes' ? cli : null,
execVersion: async (binary) => {
versionProbes.push(binary);
return null;
},
}),
);
expect(result.tools.find((tool) => tool.id === 'hermes')).toMatchObject({
installed: true,
installedPath: cli,
version: null,
launchable: false,
capabilities: { headlessTask: true },
});
expect(result.tools.find((tool) => tool.id === 'hermes-desktop')).toMatchObject({
installed: true,
installedPath: desktop,
version: null,
launchable: true,
hookCapable: false,
capabilities: { interactiveLaunch: true, headlessTask: false },
});
expect(versionProbes).toContain(cli);
expect(versionProbes).not.toContain(desktop);
});
it('detects openclaw CLI when present on PATH', async () => {
const installed = '/usr/local/bin/openclaw';
const result = await detectInstalledTools(
@@ -458,6 +951,62 @@ describe('extended-cohort detectors (codex / codex-desktop / hermes / openclaw
expect(t.installed).toBe(true);
expect(t.installedPath).toBe(installed);
});
it('derives Codex Desktop from the blocked Microsoft Store CLI resource', async () => {
const cli =
'C:\\Program Files\\WindowsApps\\OpenAI.Codex_26.707.12708.0_x64__2p2nqsd0c76g0\\app\\resources\\codex.exe';
const desktop =
'C:\\Program Files\\WindowsApps\\OpenAI.Codex_26.707.12708.0_x64__2p2nqsd0c76g0\\app\\ChatGPT.exe';
const result = await detectInstalledTools(
makeDeps({
exists: async (p) => p === cli || p === desktop,
pathFromEnv: (name) => name === 'codex' ? cli : null,
}),
);
expect(result.tools.find((tool) => tool.id === 'codex')).toMatchObject({
installed: true,
installedPath: cli,
launchable: false,
});
expect(result.tools.find((tool) => tool.id === 'codex-desktop')).toMatchObject({
installed: true,
installedPath: desktop,
launchable: true,
});
});
it('detects Codex Desktop AppX when a healthy npm Codex CLI shadows the Store resource', async () => {
const cli = 'C:\\Users\\test\\AppData\\Roaming\\npm\\codex.cmd';
const desktop =
'C:\\Program Files\\WindowsApps\\OpenAI.Codex_26.715.2305.0_x64__2p2nqsd0c76g0\\app\\ChatGPT.exe';
let appxQueries = 0;
const result = await detectInstalledTools(
makeDeps({
platform: 'win32',
exists: async (p) => p === cli || p === desktop,
pathFromEnv: (name) => name === 'codex' ? cli : null,
execVersion: async (binary) => binary === cli ? 'codex-cli 0.144.1' : null,
windowsAppExecutables: () => {
appxQueries++;
return { 'codex-desktop': [desktop] };
},
}),
);
expect(appxQueries).toBe(1);
expect(result.tools.find((tool) => tool.id === 'codex')).toMatchObject({
installed: true,
installedPath: cli,
version: 'codex-cli 0.144.1',
launchable: true,
});
expect(result.tools.find((tool) => tool.id === 'codex-desktop')).toMatchObject({
installed: true,
installedPath: desktop,
launchable: true,
});
});
});
describe('hermetic safety', () => {
@@ -526,18 +1075,12 @@ describe('resolveToolCommandInvocation', () => {
});
});
it('wraps non-npm Windows cmd shims through a quoted cmd.exe call', () => {
const invocation = resolveToolCommandInvocation(
it('rejects non-npm Windows batch shims instead of constructing a cmd.exe program', () => {
expect(() => resolveToolCommandInvocation(
'C:\\Tools\\custom.cmd',
['--version'],
['safe" & echo injected & rem'],
'win32',
{ readTextFile: () => null },
);
expect(invocation).toEqual({
binary: 'cmd.exe',
args: ['/d', '/v:off', '/s', '/c', 'call "C:\\Tools\\custom.cmd" "--version"'],
windowsVerbatimArguments: true,
});
)).toThrow(/UNSAFE_WINDOWS_BATCH_SHIM/);
});
});