Spaces:
Runtime error
Runtime error
File size: 2,156 Bytes
ed89324 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
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 });
} |