UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

37 lines (36 loc) • 1.53 kB
import { execFileSync } from "child_process"; import * as fs from "fs"; const real = { run: (file, args, env) => { execFileSync(file, args, { env, stdio: "ignore", timeout: 15_000 }); }, processes: () => { try { return execFileSync("ps", ["-Aww", "-o", "pid=,command="], { encoding: "utf8", maxBuffer: 8_388_608 }).split("\n").flatMap(line => { const match = /^\s*(\d+)\s+(.*)$/.exec(line); return match ? [{ pid: Number(match[1]), command: match[2] }] : []; }); } catch { return []; } }, kill: pid => { try { process.kill(pid, "SIGKILL"); } catch { /* already gone */ } }, }; /** Codex 0.158 leaves a detached `app-server --managed-daemon` (and its * `pid-update-loop`) per HOME, reparented to init. Stop whatever a run left * under `home`, then delete it. `codex app-server daemon stop` is the * graceful path; processes whose command line names the home are the net. */ export function removeSandboxHome(home, deps = real) { const env = { ...process.env, HOME: home, USERPROFILE: home, CODEX_HOME: undefined }; try { deps.run("codex", ["app-server", "daemon", "stop"], env); } catch { /* no codex, or no daemon */ } for (const { pid, command } of deps.processes()) { if (pid !== process.pid && command.includes(home) && /app-server|pid-update-loop/.test(command)) deps.kill(pid); } fs.rmSync(home, { recursive: true, force: true }); }