Add splitForDiscord() in src/discord/split.ts. Fences are properly closed and reopened across chunk boundaries. Router uses splitForDiscord instead of internal splitMessage(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
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<boolean> {
|
|
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;
|
|
}
|