morphbox
Version:
Docker-based AI sandbox for development with Claude integration
95 lines (92 loc) • 2.73 kB
JavaScript
import { spawn } from 'child_process';
import { EventEmitter } from 'events';
import { W as WORKSPACE_DIR } from './workspace-CcQOwpY7.js';
class TaskManager extends EventEmitter {
tasks = /* @__PURE__ */ new Map();
runTask(taskId, command) {
if (this.tasks.has(taskId)) {
const existing = this.tasks.get(taskId);
if (existing.running) {
throw new Error("Task is already running");
}
}
const [cmd, ...args] = command.split(" ");
const task = {
id: taskId,
command,
output: [],
running: true,
startTime: /* @__PURE__ */ new Date()
};
const proc = spawn(cmd, args, {
shell: true,
cwd: WORKSPACE_DIR,
env: { ...process.env }
});
task.process = proc;
task.pid = proc.pid;
this.tasks.set(taskId, task);
proc.stdout.on("data", (data) => {
const lines = data.toString().split("\n").filter((line) => line);
task.output.push(...lines);
this.emit("output", taskId, lines);
});
proc.stderr.on("data", (data) => {
const lines = data.toString().split("\n").filter((line) => line);
task.output.push(...lines);
this.emit("output", taskId, lines);
});
proc.on("close", (code) => {
task.running = false;
task.endTime = /* @__PURE__ */ new Date();
task.exitCode = code;
delete task.process;
this.emit("completed", taskId, code);
});
proc.on("error", (error) => {
task.running = false;
task.endTime = /* @__PURE__ */ new Date();
task.exitCode = 1;
task.output.push(`Error: ${error.message}`);
delete task.process;
this.emit("error", taskId, error);
});
return proc.pid || null;
}
stopTask(pid) {
const task = Array.from(this.tasks.values()).find((t) => t.pid === pid);
if (!task || !task.process) {
throw new Error("Task not found or not running");
}
task.process.kill("SIGTERM");
setTimeout(() => {
if (task.process && task.running) {
task.process.kill("SIGKILL");
}
}, 2e3);
}
getTaskOutput(taskId, fromLine = 0) {
const task = this.tasks.get(taskId);
if (!task) {
return { output: [], completed: true };
}
return {
output: task.output.slice(fromLine),
completed: !task.running,
exitCode: task.exitCode
};
}
clearTask(taskId) {
const task = this.tasks.get(taskId);
if (task && task.running && task.process) {
task.process.kill("SIGKILL");
}
this.tasks.delete(taskId);
}
getAllTasks() {
return Array.from(this.tasks.values());
}
}
const taskManager = new TaskManager();
export { taskManager as t };
//# sourceMappingURL=task-manager-CrRO35wb.js.map