mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix: standalone mode — start HTTP server + auto-connect Discord Gateway
The bot now: 1. Starts an HTTP server on PORT (default 3001) for webhook callbacks 2. Auto-connects to Discord Gateway WebSocket 3. Gateway forwards messages to the local webhook server 4. Auto-restarts Gateway on disconnect (10 min cycle) Previously: bot started, said 'ready', did nothing.
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
/**
|
||||
* CoPilot Bot — Entry point.
|
||||
* CoPilot Bot — Entry point (standalone / long-running).
|
||||
*
|
||||
* Loads config, creates adapters, starts the bot.
|
||||
* For serverless deployment (Vercel), see src/api/ routes.
|
||||
* This file is for standalone / long-running deployment.
|
||||
* Starts an HTTP server for webhook handling and connects to
|
||||
* the Discord Gateway for receiving messages.
|
||||
*/
|
||||
|
||||
import { loadConfig } from "./config.js";
|
||||
import { createBot } from "./bot.js";
|
||||
|
||||
const PORT = parseInt(process.env.PORT ?? "3001", 10);
|
||||
|
||||
async function main() {
|
||||
console.log("🤖 CoPilot Bot starting...\n");
|
||||
|
||||
@@ -23,7 +24,8 @@ async function main() {
|
||||
|
||||
console.log(`📡 Adapters: ${enabled.join(", ") || "none"}`);
|
||||
console.log(`🔗 API: ${config.autogptApiUrl}`);
|
||||
console.log(`💾 State: ${config.redisUrl ? "Redis" : "In-memory"}\n`);
|
||||
console.log(`💾 State: ${config.redisUrl ? "Redis" : "In-memory"}`);
|
||||
console.log(`🌐 Port: ${PORT}\n`);
|
||||
|
||||
// Create state adapter
|
||||
let stateAdapter;
|
||||
@@ -35,23 +37,117 @@ async function main() {
|
||||
stateAdapter = createMemoryState();
|
||||
}
|
||||
|
||||
// Create and start the bot
|
||||
// Create the bot
|
||||
const bot = await createBot(config, stateAdapter);
|
||||
|
||||
console.log("✅ CoPilot Bot ready.\n");
|
||||
// Start HTTP server for webhooks
|
||||
await startNodeServer(bot, PORT);
|
||||
|
||||
// Keep the process alive
|
||||
// Start Discord Gateway if enabled
|
||||
if (config.discord) {
|
||||
await bot.initialize();
|
||||
const discord = bot.getAdapter("discord") as any;
|
||||
|
||||
if (discord?.startGatewayListener) {
|
||||
const webhookUrl = `http://localhost:${PORT}/api/webhooks/discord`;
|
||||
console.log(`🔌 Starting Discord Gateway → ${webhookUrl}`);
|
||||
|
||||
// Run gateway in background, restart on disconnect
|
||||
const runGateway = async () => {
|
||||
while (true) {
|
||||
try {
|
||||
await discord.startGatewayListener(
|
||||
{},
|
||||
10 * 60 * 1000, // 10 minutes
|
||||
undefined,
|
||||
webhookUrl
|
||||
);
|
||||
console.log("[gateway] Listener ended, restarting...");
|
||||
} catch (err) {
|
||||
console.error("[gateway] Error, restarting in 5s:", err);
|
||||
await new Promise((r) => setTimeout(r, 5000));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Don't await — run in background
|
||||
runGateway();
|
||||
}
|
||||
}
|
||||
|
||||
console.log("\n✅ CoPilot Bot ready.\n");
|
||||
|
||||
// Graceful shutdown
|
||||
process.on("SIGINT", () => {
|
||||
console.log("\n🛑 Shutting down...");
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on("SIGTERM", () => {
|
||||
console.log("\n🛑 Shutting down...");
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a simple HTTP server using Node's built-in http module.
|
||||
* Routes webhook requests to the Chat SDK bot.
|
||||
*/
|
||||
async function startNodeServer(bot: any, port: number) {
|
||||
const { createServer } = await import("http");
|
||||
|
||||
const server = createServer(async (req, res) => {
|
||||
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
||||
|
||||
// Collect body
|
||||
const chunks: Buffer[] = [];
|
||||
for await (const chunk of req) {
|
||||
chunks.push(chunk as Buffer);
|
||||
}
|
||||
const body = Buffer.concat(chunks);
|
||||
|
||||
// Build a standard Request object for Chat SDK
|
||||
const headers = new Headers();
|
||||
for (const [key, value] of Object.entries(req.headers)) {
|
||||
if (value) headers.set(key, Array.isArray(value) ? value[0] : value);
|
||||
}
|
||||
|
||||
const request = new Request(url.toString(), {
|
||||
method: req.method ?? "POST",
|
||||
headers,
|
||||
body: req.method !== "GET" && req.method !== "HEAD" ? body : undefined,
|
||||
});
|
||||
|
||||
// Route to the correct adapter webhook
|
||||
// URL: /api/webhooks/{platform}
|
||||
const parts = url.pathname.split("/");
|
||||
const platform = parts[parts.length - 1];
|
||||
const handler = platform ? (bot.webhooks as any)[platform] : undefined;
|
||||
|
||||
if (!handler) {
|
||||
res.writeHead(404);
|
||||
res.end("Not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response: Response = await handler(request);
|
||||
res.writeHead(response.status, Object.fromEntries(response.headers));
|
||||
const responseBody = await response.arrayBuffer();
|
||||
res.end(Buffer.from(responseBody));
|
||||
} catch (err) {
|
||||
console.error(`[http] Error handling ${url.pathname}:`, err);
|
||||
res.writeHead(500);
|
||||
res.end("Internal error");
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log(`🌐 HTTP server listening on http://localhost:${port}`);
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Fatal error:", err);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user