85 lines
2.0 KiB
TypeScript
85 lines
2.0 KiB
TypeScript
import { ChildProcess, spawn, SpawnOptions } from "child_process";
|
|
import { OpenCodeProcess } from "./OpenCodeProcess";
|
|
|
|
export class WindowsProcess implements OpenCodeProcess {
|
|
start(
|
|
command: string,
|
|
args: string[],
|
|
options: SpawnOptions
|
|
): ChildProcess {
|
|
return spawn(command, args, {
|
|
...options,
|
|
shell: true,
|
|
windowsHide: true,
|
|
});
|
|
}
|
|
|
|
async stop(process: ChildProcess): Promise<void> {
|
|
const pid = process.pid;
|
|
if (!pid) {
|
|
return;
|
|
}
|
|
|
|
console.log("[OpenCode] Stopping server process tree, PID:", pid);
|
|
|
|
// Use taskkill with /T flag to kill process tree
|
|
await this.execAsync(`taskkill /T /F /PID ${pid}`);
|
|
|
|
// Wait for process to exit
|
|
await this.waitForExit(process, 5000);
|
|
}
|
|
|
|
async verifyCommand(command: string): Promise<string | null> {
|
|
// Use 'where' command to check if executable exists in PATH
|
|
try {
|
|
await this.execAsync(`where "${command}"`);
|
|
return null;
|
|
} catch {
|
|
return `Executable not found at '${command}'. Check Settings → OpenCode path, or click "Autodetect"`;
|
|
}
|
|
}
|
|
|
|
private async waitForExit(
|
|
process: ChildProcess,
|
|
timeoutMs: number
|
|
): Promise<void> {
|
|
if (process.exitCode !== null || process.signalCode !== null) {
|
|
return; // Already exited
|
|
}
|
|
|
|
return new Promise((resolve) => {
|
|
const timeout = setTimeout(() => {
|
|
cleanup();
|
|
resolve();
|
|
}, timeoutMs);
|
|
|
|
const onExit = () => {
|
|
cleanup();
|
|
resolve();
|
|
};
|
|
|
|
const cleanup = () => {
|
|
clearTimeout(timeout);
|
|
process.off("exit", onExit);
|
|
process.off("error", onExit);
|
|
};
|
|
|
|
process.once("exit", onExit);
|
|
process.once("error", onExit);
|
|
});
|
|
}
|
|
|
|
private execAsync(command: string): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const { exec } = require("child_process");
|
|
exec(command, (error: Error | null) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|