From 3646625dc16ac11ec36c1686f35f714c5e0d83d8 Mon Sep 17 00:00:00 2001 From: Shadow Date: Mon, 16 Feb 2026 13:53:00 -0600 Subject: [PATCH] Infra: skip Discord text exec approvals --- CHANGELOG.md | 1 + src/infra/exec-approval-forwarder.test.ts | 11 +---------- src/infra/exec-approval-forwarder.ts | 15 +++++---------- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950befeaa73..6569dd03056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,7 @@ Docs: https://docs.openclaw.ai - Discord: preserve channel session continuity when runtime payloads omit `message.channelId` by falling back to event/raw `channel_id` values for routing/session keys, so same-channel messages keep history across turns/restarts. Also align diagnostics so active Discord runs no longer appear as `sessionKey=unknown`. (#17622) Thanks @shakkernerd. - Discord: dedupe native skill commands by skill name in multi-agent setups to prevent duplicated slash commands with `_2` suffixes. (#17365) Thanks @seewhyme. - Discord: ensure role allowlist matching uses raw role IDs for message routing authorization. Thanks @xinhuagu. +- Discord: skip text-based exec approval forwarding in favor of Discord's component-based approval UI. Thanks @thewilloftheshadow. - Web UI/Agents: hide `BOOTSTRAP.md` in the Agents Files list after onboarding is completed, avoiding confusing missing-file warnings for completed workspaces. (#17491) Thanks @gumadeiras. - Memory/QMD: scope managed collection names per agent and precreate glob-backed collection directories before registration, preventing cross-agent collection clobbering and startup ENOENT failures in fresh workspaces. (#17194) Thanks @jonathanadams96. - Gateway/Memory: initialize QMD startup sync for every configured agent (not just the default agent), so `memory.qmd.update.onBoot` is effective across multi-agent setups. (#17663) Thanks @HenryLoenwind. diff --git a/src/infra/exec-approval-forwarder.test.ts b/src/infra/exec-approval-forwarder.test.ts index ca495a9eaa3..83c322d3b41 100644 --- a/src/infra/exec-approval-forwarder.test.ts +++ b/src/infra/exec-approval-forwarder.test.ts @@ -111,19 +111,10 @@ describe("exec approval forwarder", () => { expect(getFirstDeliveryText(deliver)).toContain("Command:\n```\necho `uname`\necho done\n```"); }); - it("skips discord forwarding when discord exec approvals target channel", async () => { + it("skips discord forwarding targets", async () => { vi.useFakeTimers(); const cfg = { approvals: { exec: { enabled: true, mode: "session" } }, - channels: { - discord: { - execApprovals: { - enabled: true, - target: "channel", - approvers: ["123"], - }, - }, - }, } as OpenClawConfig; const { deliver, forwarder } = createForwarder({ diff --git a/src/infra/exec-approval-forwarder.ts b/src/infra/exec-approval-forwarder.ts index a72938132aa..7db87370703 100644 --- a/src/infra/exec-approval-forwarder.ts +++ b/src/infra/exec-approval-forwarder.ts @@ -98,13 +98,10 @@ function buildTargetKey(target: ExecApprovalForwardTarget): string { return [channel, target.to, accountId, threadId].join(":"); } -function shouldSkipDiscordForwarding(cfg: OpenClawConfig): boolean { - const discordConfig = cfg.channels?.discord?.execApprovals; - if (!discordConfig?.enabled) { - return false; - } - const target = discordConfig.target ?? "dm"; - return target === "channel" || target === "both"; +// Discord has component-based exec approvals; skip the text fallback there. +function shouldSkipDiscordForwarding(target: ExecApprovalForwardTarget): boolean { + const channel = normalizeMessageChannel(target.channel) ?? target.channel; + return channel === "discord"; } function formatApprovalCommand(command: string): { inline: boolean; text: string } { @@ -274,9 +271,7 @@ export function createExecApprovalForwarder( } } - const filteredTargets = shouldSkipDiscordForwarding(cfg) - ? targets.filter((target) => normalizeMessageChannel(target.channel) !== "discord") - : targets; + const filteredTargets = targets.filter((target) => !shouldSkipDiscordForwarding(target)); if (filteredTargets.length === 0) { return;