import {
  appendLog,
  createProcess,
  getLogsPaginated,
  getProcess,
  getSessionProcesses,
  removeProcess,
  startProcess,
  updateStatus
} from "./chunk-VRGRAQDG.js";

// src/server/tools/background-process/manager.ts
import { spawn } from "child_process";

// src/server/utils/platform.ts
import os from "os";
function getPlatformShell() {
  if (process.platform === "win32") {
    return { command: "cmd.exe", args: ["/c"] };
  }
  const userShell = os.userInfo().shell;
  if (userShell) {
    return { command: userShell, args: ["-c"] };
  }
  return { command: "sh", args: ["-c"] };
}
function getPathSeparator() {
  return process.platform === "win32" ? ";" : ":";
}
function isWindowsPath(path) {
  return /^[A-Za-z]:[/\\]/.test(path);
}
function isAbsolutePath(path) {
  return path.startsWith("/") || isWindowsPath(path);
}

// src/server/tools/background-process/manager.ts
var STOP_SIGNAL_TIMEOUT = 5e3;
var listeners = /* @__PURE__ */ new Set();
function onProcessEvent(callback) {
  listeners.add(callback);
  return () => {
    listeners.delete(callback);
  };
}
function emitProcessEvent(processId, msg) {
  for (const listener of listeners) {
    listener(processId, msg);
  }
}
function createProcess2(sessionId, name, command, cwd, timeout) {
  const process2 = createProcess(sessionId, name, command, cwd);
  if (!process2) return null;
  if (timeout && timeout > 0) {
    setTimeout(() => {
      const p = getProcess(process2.id, sessionId);
      if (p && p.status === "running") {
        stopProcess(process2.id, sessionId);
      }
    }, timeout);
  }
  return process2;
}
function startProcessCommand(processId, sessionId, command, cwd) {
  const proc = startProcess(processId, sessionId, 0);
  if (!proc) return null;
  const shell = getPlatformShell();
  const child = spawn(shell.command, [...shell.args, command], {
    cwd,
    env: { ...process.env, FORCE_COLOR: "1" },
    stdio: ["ignore", "pipe", "pipe"],
    detached: true
  });
  proc.pid = child.pid ?? null;
  updateStatus(processId, sessionId, "running");
  emitProcessEvent(processId, {
    type: "backgroundProcess.started",
    payload: { processId, name: proc.name, pid: child.pid ?? null, status: "running" },
    sessionId
  });
  child.stdout?.on("data", (chunk) => {
    const text = chunk.toString();
    appendLog(processId, text, "stdout");
    emitProcessEvent(processId, {
      type: "backgroundProcess.output",
      payload: { processId, stream: "stdout", content: text },
      sessionId
    });
  });
  child.stderr?.on("data", (chunk) => {
    const text = chunk.toString();
    appendLog(processId, text, "stderr");
    emitProcessEvent(processId, {
      type: "backgroundProcess.output",
      payload: { processId, stream: "stderr", content: text },
      sessionId
    });
  });
  child.on("exit", (code, signal) => {
    updateStatus(processId, sessionId, "exited", code ?? (signal ? 1 : null));
    emitProcessEvent(processId, {
      type: "backgroundProcess.exited",
      payload: { processId, exitCode: code ?? (signal ? 1 : null) },
      sessionId
    });
  });
  child.on("error", (err) => {
    appendLog(processId, `Error: ${err.message}
`, "stderr");
    updateStatus(processId, sessionId, "exited", 1);
    emitProcessEvent(processId, {
      type: "backgroundProcess.exited",
      payload: { processId, exitCode: 1 },
      sessionId
    });
  });
  return child.pid ?? null;
}
async function stopProcess(processId, sessionId) {
  const proc = getProcess(processId, sessionId);
  if (!proc || proc.status !== "running" || !proc.pid) {
    return;
  }
  updateStatus(processId, sessionId, "stopping");
  const pid = proc.pid;
  try {
    try {
      process.kill(-pid, "SIGTERM");
    } catch {
      process.kill(pid, "SIGTERM");
    }
    await new Promise((resolve) => {
      setTimeout(() => {
        try {
          process.kill(-pid, "SIGKILL");
        } catch {
          try {
            process.kill(pid, "SIGKILL");
          } catch {
          }
        }
        resolve();
      }, STOP_SIGNAL_TIMEOUT);
    });
    updateStatus(processId, sessionId, "exited", null);
    emitProcessEvent(processId, {
      type: "backgroundProcess.removed",
      payload: { processId },
      sessionId
    });
    removeProcess(processId, sessionId);
  } catch {
    updateStatus(processId, sessionId, "exited", 1);
    emitProcessEvent(processId, {
      type: "backgroundProcess.removed",
      payload: { processId },
      sessionId
    });
    removeProcess(processId, sessionId);
  }
}
function getProcessStatus(processId, sessionId) {
  return getProcess(processId, sessionId);
}
function getSessionProcesses2(sessionId) {
  return getSessionProcesses(sessionId);
}
function getProcessLogs(processId, since = 0, maxLines) {
  return getLogsPaginated(processId, since, maxLines);
}

export {
  getPlatformShell,
  getPathSeparator,
  isAbsolutePath,
  onProcessEvent,
  createProcess2 as createProcess,
  startProcessCommand,
  stopProcess,
  getProcessStatus,
  getSessionProcesses2 as getSessionProcesses,
  getProcessLogs
};
//# sourceMappingURL=chunk-PBGOZMVY.js.map