Initial commit: Discord-Claude Gateway with event-driven agent runtime

This commit is contained in:
2026-02-22 13:59:57 -05:00
parent b4f340b610
commit f2247ea3ac
28 changed files with 2056 additions and 205 deletions

View File

@@ -8,6 +8,7 @@ import {
type Message,
type TextChannel,
} from "discord.js";
import { logger } from "./logger.js";
export interface Prompt {
text: string;
@@ -46,13 +47,12 @@ export class DiscordBot {
return new Promise<void>((resolve, reject) => {
this.client.once("ready", () => {
const user = this.client.user;
console.log(`Bot logged in as ${user?.tag ?? "unknown"}`);
console.log(`Connected to ${this.client.guilds.cache.size} guild(s)`);
logger.info({ tag: user?.tag ?? "unknown" }, "Bot logged in");
logger.info({ guildCount: this.client.guilds.cache.size }, "Connected to guilds");
this.setupMessageHandler();
this.setupInteractionHandler();
// Debug: confirm we're listening for messages
console.log(`[DEBUG] Message intent enabled, listening for messageCreate events`);
logger.debug("Message intent enabled, listening for messageCreate events");
resolve();
});
@@ -85,7 +85,7 @@ export class DiscordBot {
const rest = new REST({ version: "10" }).setToken(this.client.token!);
await rest.put(Routes.applicationCommands(clientId), { body: commands });
console.log("Registered /claude and /claude-reset slash commands");
logger.info("Registered /claude and /claude-reset slash commands");
}
async sendMessage(channelId: string, content: string): Promise<void> {
@@ -95,9 +95,9 @@ export class DiscordBot {
await (channel as TextChannel).send(content);
}
} catch (error) {
console.error(
`Failed to send message to channel ${channelId} (content length: ${content.length}):`,
error
logger.error(
{ channelId, contentLength: content.length, err: error },
"Failed to send message to channel",
);
}
}
@@ -127,32 +127,32 @@ export class DiscordBot {
private setupMessageHandler(): void {
this.client.on("messageCreate", (message: Message) => {
console.log(`[DEBUG] Message received: "${message.content}" from ${message.author.tag} (bot: ${message.author.bot})`);
logger.debug({ content: message.content, author: message.author.tag, bot: message.author.bot }, "Message received");
if (shouldIgnoreMessage(message)) {
console.log("[DEBUG] Ignoring bot message");
logger.debug("Ignoring bot message");
return;
}
const botUser = this.client.user;
if (!botUser) {
console.log("[DEBUG] No bot user available");
logger.debug("No bot user available");
return;
}
if (!message.mentions.has(botUser)) {
console.log("[DEBUG] Message does not mention the bot");
logger.debug("Message does not mention the bot");
return;
}
const text = extractPromptFromMention(message.content, botUser.id);
console.log(`[DEBUG] Extracted prompt: "${text}"`);
logger.debug({ text }, "Extracted prompt");
if (!text) {
console.log("[DEBUG] Empty prompt after extraction, ignoring");
logger.debug("Empty prompt after extraction, ignoring");
return;
}
console.log(`[DEBUG] Forwarding prompt to handler: "${text}" from channel ${message.channelId}`);
logger.debug({ text, channelId: message.channelId }, "Forwarding prompt to handler");
this.promptHandler?.({
text,
channelId: message.channelId,