mirror of
https://github.com/volcengine/OpenViking.git
synced 2026-09-28 19:53:23 +08:00
* fix(plugins): honor cloud recall compression across harnesses * chore(plugins): bump versions for cloud recall support * fix(dsh): align runtime and package versions * test(plugins): derive installed version from the manifest * refactor(plugins): route Codex recall through the shared pipeline
91 lines
2.6 KiB
JavaScript
91 lines
2.6 KiB
JavaScript
import { spawn } from "node:child_process";
|
|
import { accessSync, constants, existsSync } from "node:fs";
|
|
import { delimiter, join, win32 } from "node:path";
|
|
|
|
function stripPathQuotes(value) {
|
|
const entry = String(value || "").trim();
|
|
if (entry.length >= 2 && entry.startsWith('"') && entry.endsWith('"')) {
|
|
return entry.slice(1, -1);
|
|
}
|
|
return entry;
|
|
}
|
|
|
|
/**
|
|
* Resolve a launch target for the Codex CLI.
|
|
*
|
|
* npm installs on Windows put a POSIX `codex` shim, `codex.cmd`, and the
|
|
* package's JavaScript entry point beside each other. `spawn("codex")` may
|
|
* select the POSIX shim and fail with EPERM, so prefer an executable or launch
|
|
* the JavaScript entry point directly through the current Node runtime.
|
|
*/
|
|
export function resolveCodexLaunch({
|
|
platform = process.platform,
|
|
pathValue = process.env.PATH || "",
|
|
execPath = process.execPath,
|
|
pathExists = existsSync,
|
|
} = {}) {
|
|
if (platform !== "win32") {
|
|
return { command: "codex", argsPrefix: [] };
|
|
}
|
|
|
|
const entries = pathValue
|
|
.split(";")
|
|
.map(stripPathQuotes)
|
|
.filter(Boolean);
|
|
|
|
for (const entry of entries) {
|
|
const executable = win32.join(entry, "codex.exe");
|
|
if (pathExists(executable)) {
|
|
return { command: executable, argsPrefix: [] };
|
|
}
|
|
|
|
const npmEntryPoint = win32.join(
|
|
entry,
|
|
"node_modules",
|
|
"@openai",
|
|
"codex",
|
|
"bin",
|
|
"codex.js",
|
|
);
|
|
if (pathExists(npmEntryPoint)) {
|
|
return { command: execPath, argsPrefix: [npmEntryPoint] };
|
|
}
|
|
}
|
|
|
|
// Keep the normal lookup as a last resort. The caller treats either a
|
|
// synchronous throw or the child's asynchronous error as a compressor
|
|
// runtime failure and preserves the deterministic recall fallback.
|
|
return { command: "codex", argsPrefix: [] };
|
|
}
|
|
|
|
export function trySpawnCodex(args, options, {
|
|
spawnImpl = spawn,
|
|
resolveLaunch = resolveCodexLaunch,
|
|
} = {}) {
|
|
const launch = resolveLaunch();
|
|
try {
|
|
return {
|
|
...launch,
|
|
child: spawnImpl(launch.command, [...launch.argsPrefix, ...args], options),
|
|
error: null,
|
|
};
|
|
} catch (error) {
|
|
return { ...launch, child: null, error };
|
|
}
|
|
}
|
|
|
|
/** Check the executable without starting a model or a CLI subprocess. */
|
|
export function isCodexAvailable({
|
|
platform = process.platform,
|
|
pathValue = process.env.PATH || "",
|
|
canExecute = (path) => {
|
|
try { accessSync(path, constants.X_OK); return true; } catch { return false; }
|
|
},
|
|
pathExists = existsSync,
|
|
} = {}) {
|
|
if (platform === "win32") {
|
|
return resolveCodexLaunch({ platform, pathValue, pathExists }).command !== "codex";
|
|
}
|
|
return pathValue.split(delimiter).some((entry) => canExecute(join(entry || ".", "codex")));
|
|
}
|