diff --git a/src/channels/discord/plugin-sdk-bridge.ts b/src/channels/discord/plugin-sdk-bridge.ts index 0125a9d2c98..60bfac1ab4e 100644 --- a/src/channels/discord/plugin-sdk-bridge.ts +++ b/src/channels/discord/plugin-sdk-bridge.ts @@ -10,12 +10,8 @@ export { collectDiscordStatusIssues, inspectDiscordAccount, listDiscordAccountIds, - looksLikeDiscordTargetId, - normalizeDiscordMessagingTarget, - normalizeDiscordOutboundTarget, resolveDiscordAccount, resolveDefaultDiscordAccountId, - resolveDiscordChannelId, resolveDiscordGroupRequireMention, resolveDiscordGroupToolPolicy, } from "../../../extensions/discord/api.js"; @@ -37,8 +33,5 @@ export { probeDiscord, readMessagesDiscord, searchMessagesDiscord, - sendMessageDiscord, - sendTypingDiscord, - sendVoiceMessageDiscord, unpinMessageDiscord, } from "../../../extensions/discord/runtime-api.js"; diff --git a/src/plugin-sdk/channel-import-guardrails.test.ts b/src/plugin-sdk/channel-import-guardrails.test.ts index c886f7518e8..ad6b0c453d5 100644 --- a/src/plugin-sdk/channel-import-guardrails.test.ts +++ b/src/plugin-sdk/channel-import-guardrails.test.ts @@ -394,6 +394,19 @@ describe("channel import guardrails", () => { expect(text).toMatch(/from\s+"..\/..\/extensions\/discord\/runtime-api\.js";/); }); + it("keeps Discord outbound ownership on extension public seams", () => { + const text = readSource("src/plugin-sdk/discord.ts"); + const bridgeImports = [...text.matchAll(/import(?: type)?\s*\{[\s\S]*?\}\s*from\s+"[^"]+";/g)] + .map((match) => match[0]) + .filter((statement) => statement.includes("../channels/discord/plugin-sdk-bridge.js")) + .join("\n"); + expect(bridgeImports).not.toMatch( + /\b(?:looksLikeDiscordTargetId|normalizeDiscordMessagingTarget|normalizeDiscordOutboundTarget|resolveDiscordChannelId|sendMessageDiscord|sendTypingDiscord|sendVoiceMessageDiscord)\b/, + ); + expect(text).toMatch(/from\s+"..\/..\/extensions\/discord\/api\.js";/); + expect(text).toMatch(/from\s+"..\/..\/extensions\/discord\/runtime-api\.js";/); + }); + it("keeps channel helper modules off their own SDK barrels", () => { for (const source of SAME_CHANNEL_SDK_GUARDS) { const text = readSource(source.path); diff --git a/src/plugin-sdk/discord.ts b/src/plugin-sdk/discord.ts index 2b4bbc3350a..a2e4af6daf0 100644 --- a/src/plugin-sdk/discord.ts +++ b/src/plugin-sdk/discord.ts @@ -2,7 +2,11 @@ import { createDiscordActionGate, listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig, + looksLikeDiscordTargetId, + normalizeDiscordMessagingTarget, + normalizeDiscordOutboundTarget, readDiscordComponentSpec, + resolveDiscordChannelId, } from "../../extensions/discord/api.js"; import type { ThreadBindingManager, @@ -45,9 +49,12 @@ import { resolveThreadBindingInactivityExpiresAt, resolveThreadBindingMaxAgeExpiresAt, resolveThreadBindingMaxAgeMs, + sendMessageDiscord, sendDiscordComponentMessage, sendPollDiscord, + sendTypingDiscord, sendStickerDiscord, + sendVoiceMessageDiscord, setThreadBindingIdleTimeoutBySessionKey, setThreadBindingMaxAgeBySessionKey, setChannelPermissionDiscord, @@ -68,11 +75,7 @@ import { collectDiscordStatusIssues, inspectDiscordAccount, listDiscordAccountIds, - looksLikeDiscordTargetId, - normalizeDiscordMessagingTarget, - normalizeDiscordOutboundTarget, resolveDefaultDiscordAccountId, - resolveDiscordChannelId, resolveDiscordGroupRequireMention, resolveDiscordGroupToolPolicy, } from "../channels/discord/plugin-sdk-bridge.js"; @@ -94,9 +97,6 @@ import { probeDiscord, readMessagesDiscord, searchMessagesDiscord, - sendMessageDiscord, - sendTypingDiscord, - sendVoiceMessageDiscord, unpinMessageDiscord, } from "../channels/discord/plugin-sdk-bridge.js"; diff --git a/src/plugin-sdk/subpaths.test.ts b/src/plugin-sdk/subpaths.test.ts index 633d2e45117..3c81596e942 100644 --- a/src/plugin-sdk/subpaths.test.ts +++ b/src/plugin-sdk/subpaths.test.ts @@ -272,6 +272,9 @@ describe("plugin-sdk subpath exports", () => { expect(typeof discordSdk.listDiscordDirectoryPeersFromConfig).toBe("function"); expect(typeof discordSdk.listDiscordDirectoryGroupsLive).toBe("function"); expect(typeof discordSdk.listDiscordDirectoryPeersLive).toBe("function"); + expect(typeof discordSdk.normalizeDiscordOutboundTarget).toBe("function"); + expect(typeof discordSdk.resolveDiscordChannelId).toBe("function"); + expect(typeof discordSdk.sendMessageDiscord).toBe("function"); expect(typeof discordSdk.getThreadBindingManager).toBe("function"); expect(typeof discordSdk.listThreadBindingsBySessionKey).toBe("function"); expect(typeof discordSdk.normalizeExplicitDiscordSessionKey).toBe("function");