Skip to content

Commit c253628

Browse files
committed
fix(discord): route credential actions through gateway
1 parent 5671e6d commit c253628

3 files changed

Lines changed: 43 additions & 12 deletions

File tree

extensions/discord/src/channel-actions.test.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -356,21 +356,27 @@ describe("discordMessageActions", () => {
356356
expect(discovery?.schema).toBeUndefined();
357357
});
358358

359-
it.each(["read", "search"])("routes %s actions through gateway execution mode", (action) => {
360-
expect(discordMessageActions.resolveExecutionMode?.({ action: action as never })).toBe(
361-
"gateway",
362-
);
363-
});
364-
365-
it.each(["send", "upload-file", "edit", "delete", "react", "pin", "poll"])(
366-
"routes %s actions through local execution mode",
359+
it.each(["read", "search", "edit", "delete", "react", "pin", "poll", "channel-info"])(
360+
"routes %s actions through gateway execution mode",
367361
(action) => {
368362
expect(discordMessageActions.resolveExecutionMode?.({ action: action as never })).toBe(
369-
"local",
363+
"gateway",
370364
);
371365
},
372366
);
373367

368+
it.each([
369+
"send",
370+
"upload-file",
371+
"thread-reply",
372+
"sticker",
373+
"emoji-upload",
374+
"sticker-upload",
375+
"event-create",
376+
])("keeps %s on local execution mode", (action) => {
377+
expect(discordMessageActions.resolveExecutionMode?.({ action: action as never })).toBe("local");
378+
});
379+
374380
it("extracts send targets for message and thread reply actions", () => {
375381
expect(
376382
discordMessageActions.extractToolSend?.({

extensions/discord/src/channel-actions.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ const trustedRequesterGuildAdminActions = new Set<ChannelMessageActionName>([
2727
"event-create",
2828
]);
2929

30+
const localExecutionActions = new Set<ChannelMessageActionName>([
31+
"send",
32+
"upload-file",
33+
"thread-reply",
34+
"sticker",
35+
"emoji-upload",
36+
"sticker-upload",
37+
"event-create",
38+
]);
39+
40+
function resolveDiscordActionExecutionMode({ action }: { action: ChannelMessageActionName }) {
41+
return localExecutionActions.has(action) ? "local" : "gateway";
42+
}
43+
3044
let discordChannelActionsRuntimePromise:
3145
| Promise<typeof import("./channel-actions.runtime.js")>
3246
| undefined;
@@ -178,8 +192,10 @@ function describeDiscordMessageTool({
178192
}
179193

180194
export const discordMessageActions: ChannelMessageActionAdapter = {
181-
resolveExecutionMode: ({ action }) =>
182-
action === "read" || action === "search" ? "gateway" : "local",
195+
// Credential-only Discord actions run in the gateway when one is available.
196+
// Send/file-style actions stay local because core owns their thread, media,
197+
// component, and client-local payload semantics.
198+
resolveExecutionMode: resolveDiscordActionExecutionMode,
183199
describeMessageTool: describeDiscordMessageTool,
184200
requiresTrustedRequesterSender: ({ action, toolContext }) =>
185201
normalizeOptionalString(toolContext?.currentChannelProvider)?.toLowerCase() === "discord" &&

extensions/discord/src/channel.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ describe("discordPlugin outbound", () => {
180180
expect(discordPlugin.outbound?.preferFinalAssistantVisibleText).toBe(true);
181181
});
182182

183-
it("routes read and search actions through the gateway", () => {
183+
it("routes Discord message actions through the gateway", () => {
184184
expect(discordPlugin.actions?.resolveExecutionMode?.({ action: "read" as never })).toBe(
185185
"gateway",
186186
);
@@ -190,6 +190,15 @@ describe("discordPlugin outbound", () => {
190190
expect(discordPlugin.actions?.resolveExecutionMode?.({ action: "send" as never })).toBe(
191191
"local",
192192
);
193+
expect(discordPlugin.actions?.resolveExecutionMode?.({ action: "upload-file" as never })).toBe(
194+
"local",
195+
);
196+
expect(discordPlugin.actions?.resolveExecutionMode?.({ action: "thread-reply" as never })).toBe(
197+
"local",
198+
);
199+
expect(discordPlugin.actions?.resolveExecutionMode?.({ action: "channel-info" as never })).toBe(
200+
"gateway",
201+
);
193202
});
194203

195204
it("adds Discord mention formatting to agent prompt hints", () => {

0 commit comments

Comments
 (0)