import * as os from "os"; import { Message, TextChannel } from "discord.js"; import { DisclawDatabase } from "./db/database"; import { DisclawConfig } from "./config/loader"; import { runAgent } from "./agent/runner"; import { splitForDiscord } from "./discord/split"; import { sanitizeForDiscord } from "./runtime/sanitize"; import { ChannelQueue } from "./runtime/channel-queue"; import type { RunResult } from "./agent/types"; const channelQueue = new ChannelQueue(); /** * Routes a Discord message to the correct agent based on channel_id. * Returns true if the message was handled, false if the channel is not * mapped to any agent. */ export async function routeMessage( message: Message, db: DisclawDatabase, config: DisclawConfig, managementChannelId: string | null ): Promise { const channelId = message.channelId; if (channelId === managementChannelId) { return false; } const workspace = db.getWorkspaceByChannelId(channelId); if (!workspace) { return false; } const channel = message.channel as TextChannel; const sanitizeOpts = { repoRoot: workspace.workspace_path, home: os.homedir(), }; await channelQueue.enqueue(channelId, async () => { const typingInterval = setInterval(() => { channel.sendTyping().catch(() => {}); }, 5000); await channel.sendTyping().catch(() => {}); try { const history = db.getConversationHistory(workspace.id, 30); const result: RunResult = await runAgent({ workspacePath: workspace.workspace_path, channelName: channel.name, userMessage: message.content, conversationHistory: history, }); if (result.status === "success") { db.addConversation( workspace.id, message.id, "user", message.content, message.author.username ); const sanitizedResponse = sanitizeForDiscord(result.text, sanitizeOpts); const chunks = splitForDiscord(sanitizedResponse); let firstMsgId: string | null = null; for (const chunk of chunks) { const sent = await channel.send(chunk); if (!firstMsgId) { firstMsgId = sent.id; } } if (firstMsgId) { db.addConversation( workspace.id, firstMsgId, "assistant", sanitizedResponse, null ); } } else if (result.status === "timeout") { await channel .send(`⏱️ Agent-Timeout nach ${result.timeoutMs / 1000}s`) .catch(() => {}); } else if (result.status === "cli-error") { await channel .send(sanitizeForDiscord(`❌ CLI-Fehler: ${result.message}`, sanitizeOpts)) .catch(() => {}); } else if (result.status === "parse-error") { await channel .send(`⚠️ Antwort konnte nicht gelesen werden`) .catch(() => {}); } } catch (error) { const msg = error instanceof Error ? error.message : "Unbekannter Fehler"; await channel .send(sanitizeForDiscord(`Fehler bei der Verarbeitung: ${msg}`, sanitizeOpts)) .catch(() => {}); } finally { clearInterval(typingInterval); } }); return true; }