Files
openclaw/src/infra/executable-path.ts
2026-03-02 12:55:47 +00:00

76 lines
2.1 KiB
TypeScript

import fs from "node:fs";
import path from "node:path";
import { expandHomePrefix } from "./home-dir.js";
function resolveWindowsExecutableExtensions(
executable: string,
env: NodeJS.ProcessEnv | undefined,
): string[] {
if (process.platform !== "win32") {
return [""];
}
if (path.extname(executable).length > 0) {
return [""];
}
return (
env?.PATHEXT ??
env?.Pathext ??
process.env.PATHEXT ??
process.env.Pathext ??
".EXE;.CMD;.BAT;.COM"
)
.split(";")
.map((ext) => ext.toLowerCase());
}
export function isExecutableFile(filePath: string): boolean {
try {
const stat = fs.statSync(filePath);
if (!stat.isFile()) {
return false;
}
if (process.platform !== "win32") {
fs.accessSync(filePath, fs.constants.X_OK);
}
return true;
} catch {
return false;
}
}
export function resolveExecutableFromPathEnv(
executable: string,
pathEnv: string,
env?: NodeJS.ProcessEnv,
): string | undefined {
const entries = pathEnv.split(path.delimiter).filter(Boolean);
const extensions = resolveWindowsExecutableExtensions(executable, env);
for (const entry of entries) {
for (const ext of extensions) {
const candidate = path.join(entry, executable + ext);
if (isExecutableFile(candidate)) {
return candidate;
}
}
}
return undefined;
}
export function resolveExecutablePath(
rawExecutable: string,
options?: { cwd?: string; env?: NodeJS.ProcessEnv },
): string | undefined {
const expanded = rawExecutable.startsWith("~") ? expandHomePrefix(rawExecutable) : rawExecutable;
if (expanded.includes("/") || expanded.includes("\\")) {
if (path.isAbsolute(expanded)) {
return isExecutableFile(expanded) ? expanded : undefined;
}
const base = options?.cwd && options.cwd.trim() ? options.cwd.trim() : process.cwd();
const candidate = path.resolve(base, expanded);
return isExecutableFile(candidate) ? candidate : undefined;
}
const envPath =
options?.env?.PATH ?? options?.env?.Path ?? process.env.PATH ?? process.env.Path ?? "";
return resolveExecutableFromPathEnv(expanded, envPath, options?.env);
}