- Status reactions on messages: 👀 on enqueue, ✅ on success, ❌ on any error - Typing interval raised from 5s to 8s - src/discord/send-response.ts: text >4000 chars sent as response.md attachment - src/discord/attachment-inbox.ts: downloads Discord attachments into .disclaw-inbox/, cleanupInbox() removes files older than 24h - src/router.ts: input limit guard at 4000 chars (⚠️ reaction + hint message), processAttachments hints injected into prompt - Unit tests: send-response.test.ts, attachment-inbox.test.ts (107 tests, all green) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
1,023 B
TypeScript
39 lines
1,023 B
TypeScript
import { TextChannel, Message, AttachmentBuilder } from "discord.js";
|
|
import { splitForDiscord } from "./split.js";
|
|
import { childLogger } from "../runtime/logger.js";
|
|
|
|
const log = childLogger("send-response");
|
|
|
|
const FILE_THRESHOLD = 4000;
|
|
|
|
/**
|
|
* Sends an agent response to a Discord channel.
|
|
* - Text > 4000 chars is sent as a Markdown file attachment.
|
|
* - Text <= 4000 chars is split with splitForDiscord and sent as plain messages.
|
|
*/
|
|
export async function sendResponse(
|
|
channel: TextChannel,
|
|
text: string,
|
|
_triggerMessage: Message
|
|
): Promise<void> {
|
|
if (text.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (text.length > FILE_THRESHOLD) {
|
|
log.debug({ length: text.length }, "Response exceeds threshold — sending as file");
|
|
await channel.send({
|
|
files: [
|
|
new AttachmentBuilder(Buffer.from(text, "utf-8"), {
|
|
name: "response.md",
|
|
}),
|
|
],
|
|
});
|
|
return;
|
|
}
|
|
|
|
const chunks = splitForDiscord(text);
|
|
for (const chunk of chunks) {
|
|
await channel.send(chunk);
|
|
}
|
|
}
|