Spaces:
Runtime error
Runtime error
| 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 }); | |
| } |