import express from "express"; import cors from "cors"; import { listTools, executeTool } from "./agent.js"; const app = express(); app.use(cors()); app.use(express.json({ limit: "1mb" })); // Health + welcome app.get("/", (_req, res) => { res.status(200).json({ status: "ok", service: "hf-ubuntu-agent-sse", tools: listTools().tools.map((t) => t.name) }); }); /** * SSE helper */ function openSSE(res) { res.setHeader("Content-Type", "text/event-stream"); res.setHeader("Cache-Control", "no-cache, no-transform"); res.setHeader("Connection", "keep-alive"); res.flushHeaders?.(); const send = (event, data) => { res.write(`event: ${event}\n`); res.write(`data: ${JSON.stringify(data)}\n\n`); }; const keepAlive = setInterval(() => { res.write(`event: ping\ndata: "ok"\n\n`); }, 15000); const close = () => clearInterval(keepAlive); return { send, close }; } /** * List available tools (simple JSON) */ app.get("/tools", (_req, res) => { res.json(listTools()); }); /** * MCP-like SSE execution endpoint: * GET /exec?tool=shell&command=ls%20-la * GET /exec?tool=python&code=print('hi') * * Body POST alternative also supported: { tool, args } */ app.get("/exec", (req, res) => { const { send, close } = openSSE(res); const tool = String(req.query.tool || ""); let args = {}; if (tool === "shell") { args = { command: String(req.query.command || "") }; } else if (tool === "python") { args = { code: String(req.query.code || "") }; } send("tools", listTools()); executeTool(tool, args, send); req.on("close", () => { close(); }); }); /** * JSON -> SSE execution (POST), useful for programmatic clients. * Body: { tool: "shell", args: { command: "ls -la" } } */ app.post("/run", (req, res) => { const { tool, args } = req.body || {}; const { send, close } = openSSE(res); send("tools", listTools()); executeTool(tool, args, send); req.on("close", () => { close(); }); }); // IMPORTANT: honor HF Spaces $PORT const PORT = process.env.PORT || 7860; app.listen(PORT, "0.0.0.0", () => { console.log(`Ubuntu agent running on http://0.0.0.0:${PORT}`); });