openclaw/extensions/kiro-auth/cli-detector.ts

90 lines
2.3 KiB
TypeScript

import { existsSync, accessSync, constants } from "node:fs";
import { delimiter, join } from "node:path";
/**
* Binary names to search for in PATH.
* kiro-cli is the primary name, q is an alias.
*/
const CLI_BINARY_NAMES = ["kiro-cli", "q"];
/**
* Windows executable extensions to check.
* Empty string is included to check the bare name first.
*/
const WINDOWS_EXTENSIONS = ["", ".cmd", ".bat", ".exe"];
/**
* Checks if a file exists and is executable.
* On Windows, existence is sufficient (no X_OK check needed).
* @param filePath Path to check
* @returns true if file exists and is executable
*/
function isExecutable(filePath: string): boolean {
try {
if (process.platform === "win32") {
return existsSync(filePath);
}
accessSync(filePath, constants.X_OK);
return true;
} catch {
return false;
}
}
/**
* Searches for kiro-cli in the system PATH.
* On Windows, also checks .cmd, .bat, .exe extensions.
* @returns Full path to kiro-cli binary, or null if not found
*
* @example
* ```ts
* const cliPath = findKiroCli();
* if (cliPath) {
* console.log(`Found kiro-cli at: ${cliPath}`);
* } else {
* console.log("kiro-cli not found");
* }
* ```
*/
export function findKiroCli(): string | null {
const pathEnv = process.env.PATH ?? "";
if (!pathEnv) return null;
const pathEntries = pathEnv.split(delimiter).filter(Boolean);
const extensions = process.platform === "win32" ? WINDOWS_EXTENSIONS : [""];
for (const name of CLI_BINARY_NAMES) {
for (const dir of pathEntries) {
for (const ext of extensions) {
const candidate = join(dir, name + ext);
if (isExecutable(candidate)) {
return candidate;
}
}
}
}
return null;
}
/**
* Checks if the current environment is WSL2.
* Reads /proc/version on Linux to detect WSL2.
* @returns true if running in WSL2
*/
export function isWSL2(): boolean {
if (process.platform !== "linux") return false;
try {
const { readFileSync } = require("node:fs") as typeof import("node:fs");
const version = readFileSync("/proc/version", "utf8");
// WSL2 includes "microsoft" and "WSL2" in /proc/version
return (
version.toLowerCase().includes("microsoft") &&
version.toLowerCase().includes("wsl2")
);
} catch {
return false;
}
}