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"; /** * 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; // Ignore messages in the management channel (commands only) if (channelId === managementChannelId) { return false; } // Look up workspace for this channel const workspace = db.getWorkspaceByChannelId(channelId); if (!workspace) { return false; } const channel = message.channel as TextChannel; // Show typing indicator while the agent works const typingInterval = setInterval(() => { channel.sendTyping().catch(() => {}); }, 5000); // Send immediately as well await channel.sendTyping().catch(() => {}); try { // Load recent conversation history for context const history = db.getConversationHistory(workspace.id, 30); // Run the agent const response = await runAgent({ workspacePath: workspace.workspace_path, channelName: channel.name, userMessage: message.content, conversationHistory: history, }); // Store user message db.addConversation( workspace.id, message.id, "user", message.content, message.author.username ); // Split and send response const chunks = splitForDiscord(response); let firstMsgId: string | null = null; for (const chunk of chunks) { const sent = await channel.send(chunk); if (!firstMsgId) { firstMsgId = sent.id; } } // Store assistant response (use first message id for dedup) if (firstMsgId) { db.addConversation( workspace.id, firstMsgId, "assistant", response, null ); } } catch (error) { const msg = error instanceof Error ? error.message : "Unbekannter Fehler"; await channel.send(`Fehler bei der Verarbeitung: ${msg}`).catch(() => {}); } finally { clearInterval(typingInterval); } return true; }