ubuntu / agent.js
likhonsheikh's picture
Create agent.js
ed89324 verified
import { spawn } from "child_process";
import fs from "fs";
let toolSpec;
export function listTools() {
if (!toolSpec) {
toolSpec = JSON.parse(fs.readFileSync("tools.json", "utf-8"));
}
return toolSpec;
}
/**
* Stream a child process over SSE.
* send(eventType, payload) writes to the SSE connection.
*/
function streamProcess(cmd, args, options, send) {
const child = spawn(cmd, args, { shell: false, ...options });
child.stdout.on("data", (chunk) => {
send("output", { data: chunk.toString() });
});
child.stderr.on("data", (chunk) => {
send("error", { data: chunk.toString() });
});
child.on("close", (code) => {
send("done", { code });
});
child.on("error", (err) => {
send("error", { data: String(err) });
send("done", { code: -1 });
});
return child;
}
/**
* Execute a tool call and stream results.
* tool: "shell" | "python"
* args: { command } | { code }
*/
export function executeTool(tool, args, send) {
if (tool === "shell") {
if (!args?.command || typeof args.command !== "string") {
send("error", { data: "Missing 'command' string." });
return send("done", { code: 2 });
}
// Use /bin/bash -lc to enable pipes, redirects, env, etc.
return streamProcess("/bin/bash", ["-lc", args.command], {}, send);
}
if (tool === "python") {
if (!args?.code || typeof args.code !== "string") {
send("error", { data: "Missing 'code' string." });
return send("done", { code: 2 });
}
// Run python inline, escape newlines safely by passing as stdin
const child = spawn("python3", ["-"], { stdio: ["pipe", "pipe", "pipe"] });
child.stdin.write(args.code);
child.stdin.end();
child.stdout.on("data", (chunk) => send("output", { data: chunk.toString() }));
child.stderr.on("data", (chunk) => send("error", { data: chunk.toString() }));
child.on("close", (code) => send("done", { code }));
child.on("error", (err) => {
send("error", { data: String(err) });
send("done", { code: -1 });
});
return child;
}
send("error", { data: `Unknown tool '${tool}'.` });
send("done", { code: 2 });
}