diff --git a/src/discord/monitor.ts b/src/discord/monitor.ts index 5a542c7b2..1b3b95101 100644 --- a/src/discord/monitor.ts +++ b/src/discord/monitor.ts @@ -844,6 +844,58 @@ function resolveSlashPrompt( return undefined; } +async function ensureSlashCommand( + client: Client, + slashCommand: Required, + runtime: RuntimeEnv, +) { + try { + const appCommands = client.application?.commands; + if (!appCommands) { + runtime.error?.(danger("discord slash commands unavailable")); + return; + } + const existing = await appCommands.fetch(); + let hasCommand = false; + for (const entry of existing.values()) { + if (entry.name === slashCommand.name) { + hasCommand = true; + continue; + } + await entry.delete(); + } + if (hasCommand) return; + await appCommands.create({ + name: slashCommand.name, + description: "Ask Clawdis a question", + options: [ + { + name: "prompt", + description: "What should Clawdis help with?", + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }); + runtime.log?.(`registered discord slash command /${slashCommand.name}`); + } catch (err) { + const status = (err as { status?: number | string })?.status; + const code = (err as { code?: number | string })?.code; + const message = String(err); + const isRateLimit = + status === 429 || + code === 429 || + /rate ?limit/i.test(message); + const text = `discord slash command setup failed: ${message}`; + if (isRateLimit) { + logVerbose(text); + runtime.error?.(warn(text)); + } else { + runtime.error?.(danger(text)); + } + } +} + function findFirstStringOption( options: readonly CommandInteractionOption[], ): string | undefined {