diff --git a/apps/macos/Sources/Clawdis/ConnectionsSettings.swift b/apps/macos/Sources/Clawdis/ConnectionsSettings.swift index 97292bbdf..0b95c849c 100644 --- a/apps/macos/Sources/Clawdis/ConnectionsSettings.swift +++ b/apps/macos/Sources/Clawdis/ConnectionsSettings.swift @@ -310,12 +310,6 @@ struct ConnectionsSettings: View { TextField("20", text: self.$store.discordHistoryLimit) .textFieldStyle(.roundedBorder) } - GridRow { - self.gridLabel("Reactions") - Toggle("", isOn: self.$store.discordEnableReactions) - .labelsHidden() - .toggleStyle(.checkbox) - } GridRow { self.gridLabel("Slash command") Toggle("", isOn: self.$store.discordSlashEnabled) diff --git a/apps/macos/Sources/Clawdis/ConnectionsStore.swift b/apps/macos/Sources/Clawdis/ConnectionsStore.swift index 9269ee590..ef676179b 100644 --- a/apps/macos/Sources/Clawdis/ConnectionsStore.swift +++ b/apps/macos/Sources/Clawdis/ConnectionsStore.swift @@ -174,7 +174,6 @@ final class ConnectionsStore { var discordGroupChannels: String = "" var discordMediaMaxMb: String = "" var discordHistoryLimit: String = "" - var discordEnableReactions = true var discordSlashEnabled = false var discordSlashName: String = "" var discordSlashSessionPrefix: String = "" @@ -420,7 +419,6 @@ final class ConnectionsStore { } else { self.discordHistoryLimit = "" } - self.discordEnableReactions = discord?["enableReactions"]?.boolValue ?? true let slash = discord?["slashCommand"]?.dictionaryValue self.discordSlashEnabled = slash?["enabled"]?.boolValue ?? false self.discordSlashName = slash?["name"]?.stringValue ?? "" @@ -644,12 +642,6 @@ final class ConnectionsStore { discord.removeValue(forKey: "historyLimit") } - if self.discordEnableReactions { - discord.removeValue(forKey: "enableReactions") - } else { - discord["enableReactions"] = false - } - var slash: [String: Any] = (discord["slashCommand"] as? [String: Any]) ?? [:] if self.discordSlashEnabled { slash["enabled"] = true diff --git a/docs/configuration.md b/docs/configuration.md index 512ce0972..4b618621d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -221,7 +221,6 @@ Configure the Discord bot by setting the bot token and optional gating: enabled: true, token: "your-bot-token", mediaMaxMb: 8, // clamp inbound media size - enableReactions: true, // allow agent-triggered reactions actions: { // tool action gates (false disables) reactions: true, stickers: true, diff --git a/docs/discord.md b/docs/discord.md index 47a6d4420..4228bb9be 100644 --- a/docs/discord.md +++ b/docs/discord.md @@ -27,7 +27,7 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa 8. Optional guild rules: set `discord.guilds` keyed by guild id (preferred) or slug, with per-channel rules. 9. Optional slash commands: enable `discord.slashCommand` to accept user-installed app commands (ephemeral replies). Slash invocations respect the same DM/guild allowlists. 10. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable. -11. Reactions: the agent can trigger reactions via the `discord` tool (gated by `discord.enableReactions`). +11. Reactions: the agent can trigger reactions via the `discord` tool (gated by `discord.actions.*`). 12. Slash commands use isolated session keys (`${sessionPrefix}:${userId}`) rather than the shared `main` session. Note: Discord does not provide a simple username → id lookup without extra guild context, so prefer ids or `<@id>` mentions for DM delivery targets. @@ -50,7 +50,6 @@ Note: Guild context `[from:]` lines include `author.tag` + `id` to make ping-rea enabled: true, token: "abc.123", mediaMaxMb: 8, - enableReactions: true, actions: { reactions: true, stickers: true, @@ -110,7 +109,6 @@ Note: Guild context `[from:]` lines include `author.tag` + `id` to make ping-rea - `slashCommand`: optional config for user-installed slash commands (ephemeral responses). - `mediaMaxMb`: clamp inbound media saved to disk. - `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20, `0` disables). -- `enableReactions`: allow agent-triggered reactions via the `discord` tool (default `true`). - `actions`: per-action tool gates; omit to allow all (set `false` to disable). - `reactions` (covers react + read reactions) - `stickers`, `polls`, `permissions`, `messages`, `threads`, `pins`, `search` diff --git a/docs/tools.md b/docs/tools.md index 49bcf6cd7..b59b84d83 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -141,8 +141,7 @@ Notes: - `to` accepts `channel:` or `user:`. - Polls require 2–10 answers and default to 24 hours. - `reactions` returns per-emoji user lists (limited to 100 per reaction). -- Reactions respect `discord.enableReactions` (default `true`). -- `discord.actions.roles` + `discord.actions.moderation` default to `false`. +- `discord.actions.*` gates Discord tool actions; `roles` + `moderation` default to `false`. - `searchMessages` follows the Discord preview spec (limit max 25, channel/author filters accept arrays). ## Parameters (common) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b7455c6b..39d27856c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3755,11 +3755,11 @@ snapshots: - utf-8-validate - vite - '@vitest/browser-preview@4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16)': + '@vitest/browser-preview@4.0.16(vite@8.0.0-beta.3(@types/node@25.0.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16)': dependencies: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/browser': 4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) + '@vitest/browser': 4.0.16(vite@8.0.0-beta.3(@types/node@25.0.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(@vitest/browser-preview@4.0.16)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - bufferutil @@ -5522,8 +5522,8 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.0.3 - '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) - '@vitest/browser-preview': 4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) + '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@8.0.0-beta.3(@types/node@25.0.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) + '@vitest/browser-preview': 4.0.16(vite@8.0.0-beta.3(@types/node@25.0.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16) transitivePeerDependencies: - jiti - less diff --git a/skills/discord/SKILL.md b/skills/discord/SKILL.md index 3594f607e..90e923cc1 100644 --- a/skills/discord/SKILL.md +++ b/skills/discord/SKILL.md @@ -1,13 +1,13 @@ --- name: discord -description: Use when you need to control Discord from Clawdis via the discord tool: add reactions, send stickers, or create polls in Discord DMs or channels. Trigger for tasks like reacting to a message, posting a sticker, or running a quick poll for a decision. +description: Use when you need to control Discord from Clawdis via the discord tool: send messages, react, post stickers, run polls, manage threads/pins/search, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels. --- # Discord Actions ## Overview -Use `discord` to manage messages, reactions, threads, and moderation. Reactions are gated by `discord.enableReactions` (default `true`). You can disable groups via `discord.actions.*`. The tool uses the bot token configured for Clawdis. +Use `discord` to manage messages, reactions, threads, polls, and moderation. You can disable groups via `discord.actions.*` (defaults to enabled, except roles/moderation). The tool uses the bot token configured for Clawdis. ## Inputs to collect @@ -91,7 +91,7 @@ Message context lines include `discord message id` and `channel` fields you can ## Action gating Use `discord.actions.*` to disable action groups: -- `reactions` (react + reactions list) +- `reactions` (react + reactions list + emojiList) - `stickers`, `polls`, `permissions`, `messages`, `threads`, `pins`, `search` - `memberInfo`, `roleInfo`, `channelInfo`, `voiceStatus`, `events` - `roles` (role add/remove, default `false`) diff --git a/src/agents/clawdis-tools.ts b/src/agents/clawdis-tools.ts index dd07c7879..fb987ff3d 100644 --- a/src/agents/clawdis-tools.ts +++ b/src/agents/clawdis-tools.ts @@ -1758,11 +1758,6 @@ function createDiscordTool(): AnyAgentTool { if (!isActionEnabled("reactions")) { throw new Error("Discord reactions are disabled."); } - if (cfg.discord?.enableReactions === false) { - throw new Error( - "Discord reactions are disabled (set discord.enableReactions=true).", - ); - } const channelId = readStringParam(params, "channelId", { required: true, }); diff --git a/src/config/config.ts b/src/config/config.ts index 75dd3c03f..c7103ac94 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -247,8 +247,6 @@ export type DiscordConfig = { textChunkLimit?: number; mediaMaxMb?: number; historyLimit?: number; - /** Allow agent-triggered Discord reactions (default: true). */ - enableReactions?: boolean; /** Per-action tool gating (default: true for all). */ actions?: DiscordActionConfig; /** Control reply threading when reply tags are present (off|first|all). */ @@ -1052,7 +1050,6 @@ const ClawdisSchema = z.object({ .optional(), mediaMaxMb: z.number().positive().optional(), historyLimit: z.number().int().min(0).optional(), - enableReactions: z.boolean().optional(), actions: z .object({ reactions: z.boolean().optional(), diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 721eda703..1bcd91be4 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -143,7 +143,6 @@ export class ClawdisApp extends LitElement { groupChannels: "", mediaMaxMb: "", historyLimit: "", - enableReactions: true, slashEnabled: false, slashName: "", slashSessionPrefix: "", diff --git a/ui/src/ui/controllers/config.ts b/ui/src/ui/controllers/config.ts index 4b4023650..5582900f3 100644 --- a/ui/src/ui/controllers/config.ts +++ b/ui/src/ui/controllers/config.ts @@ -99,8 +99,6 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot typeof discord.mediaMaxMb === "number" ? String(discord.mediaMaxMb) : "", historyLimit: typeof discord.historyLimit === "number" ? String(discord.historyLimit) : "", - enableReactions: - typeof discord.enableReactions === "boolean" ? discord.enableReactions : true, slashEnabled: typeof slash.enabled === "boolean" ? slash.enabled : false, slashName: typeof slash.name === "string" ? slash.name : "", slashSessionPrefix: diff --git a/ui/src/ui/controllers/connections.ts b/ui/src/ui/controllers/connections.ts index 3791dbdac..afd977058 100644 --- a/ui/src/ui/controllers/connections.ts +++ b/ui/src/ui/controllers/connections.ts @@ -246,12 +246,6 @@ export async function saveDiscordConfig(state: ConnectionsState) { } } - if (form.enableReactions) { - delete discord.enableReactions; - } else { - discord.enableReactions = false; - } - const slash = { ...(discord.slashCommand ?? {}) } as Record; if (form.slashEnabled) { slash.enabled = true; diff --git a/ui/src/ui/ui-types.ts b/ui/src/ui/ui-types.ts index ca83a8934..08f8edf9c 100644 --- a/ui/src/ui/ui-types.ts +++ b/ui/src/ui/ui-types.ts @@ -16,7 +16,6 @@ export type DiscordForm = { groupChannels: string; mediaMaxMb: string; historyLimit: string; - enableReactions: boolean; slashEnabled: boolean; slashName: string; slashSessionPrefix: string; diff --git a/ui/src/ui/views/connections.ts b/ui/src/ui/views/connections.ts index ea3485406..6a627b67b 100644 --- a/ui/src/ui/views/connections.ts +++ b/ui/src/ui/views/connections.ts @@ -522,19 +522,6 @@ function renderProvider( placeholder="20" /> -