refactor: pilot discord threading ownership

This commit is contained in:
Tak Hoffman 2026-03-18 14:19:25 -05:00
parent 679271f757
commit b744aaccf3
No known key found for this signature in database
4 changed files with 37 additions and 30 deletions

View File

@ -5,11 +5,6 @@ export type {
InspectedDiscordAccount,
ResolvedDiscordAccount,
} from "../../../extensions/discord/api.js";
export type {
ThreadBindingManager,
ThreadBindingRecord,
ThreadBindingTargetKind,
} from "../../../extensions/discord/runtime-api.js";
export {
collectDiscordStatusIssues,
@ -29,7 +24,6 @@ export {
export {
addRoleDiscord,
auditDiscordChannelPermissions,
autoBindSpawnedDiscordSubagent,
banMemberDiscord,
collectDiscordAuditChannelIds,
createChannelDiscord,
@ -51,7 +45,6 @@ export {
fetchVoiceStatusDiscord,
getGateway,
getPresence,
getThreadBindingManager,
hasAnyGuildPermissionDiscord,
kickMemberDiscord,
listDiscordDirectoryGroupsLive,
@ -60,7 +53,6 @@ export {
listGuildEmojisDiscord,
listPinsDiscord,
listScheduledEventsDiscord,
listThreadBindingsBySessionKey,
listThreadsDiscord,
monitorDiscordProvider,
moveChannelDiscord,
@ -74,10 +66,6 @@ export {
removeRoleDiscord,
resolveDiscordChannelAllowlist,
resolveDiscordUserAllowlist,
resolveThreadBindingIdleTimeoutMs,
resolveThreadBindingInactivityExpiresAt,
resolveThreadBindingMaxAgeExpiresAt,
resolveThreadBindingMaxAgeMs,
searchMessagesDiscord,
sendDiscordComponentMessage,
sendMessageDiscord,
@ -86,15 +74,11 @@ export {
sendTypingDiscord,
sendVoiceMessageDiscord,
setChannelPermissionDiscord,
setThreadBindingIdleTimeoutBySessionKey,
setThreadBindingMaxAgeBySessionKey,
timeoutMemberDiscord,
unbindThreadBindingsBySessionKey,
unpinMessageDiscord,
uploadEmojiDiscord,
uploadStickerDiscord,
} from "../../../extensions/discord/runtime-api.js";
export { normalizeExplicitDiscordSessionKey } from "../../../extensions/discord/session-key-api.js";
export {
listDiscordDirectoryGroupsFromConfig,
listDiscordDirectoryPeersFromConfig,

View File

@ -352,6 +352,22 @@ function expectNoSiblingExtensionPrivateSrcImports(file: string, imports: string
}
describe("channel import guardrails", () => {
it("keeps Discord threading 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(?:ThreadBindingManager|ThreadBindingRecord|ThreadBindingTargetKind)\b/,
);
expect(bridgeImports).not.toMatch(
/\b(?:autoBindSpawnedDiscordSubagent|getThreadBindingManager|listThreadBindingsBySessionKey|resolveThreadBindingIdleTimeoutMs|resolveThreadBindingInactivityExpiresAt|resolveThreadBindingMaxAgeExpiresAt|resolveThreadBindingMaxAgeMs|setThreadBindingIdleTimeoutBySessionKey|setThreadBindingMaxAgeBySessionKey|unbindThreadBindingsBySessionKey)\b/,
);
expect(text).toMatch(/from\s+"..\/..\/extensions\/discord\/runtime-api\.js";/);
expect(text).toMatch(/from\s+"..\/..\/extensions\/discord\/session-key-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);

View File

@ -1,12 +1,27 @@
import type {
ThreadBindingManager,
ThreadBindingRecord,
ThreadBindingTargetKind,
} from "../../extensions/discord/runtime-api.js";
import {
autoBindSpawnedDiscordSubagent,
getThreadBindingManager,
listThreadBindingsBySessionKey,
resolveThreadBindingIdleTimeoutMs,
resolveThreadBindingInactivityExpiresAt,
resolveThreadBindingMaxAgeExpiresAt,
resolveThreadBindingMaxAgeMs,
setThreadBindingIdleTimeoutBySessionKey,
setThreadBindingMaxAgeBySessionKey,
unbindThreadBindingsBySessionKey,
} from "../../extensions/discord/runtime-api.js";
import { normalizeExplicitDiscordSessionKey } from "../../extensions/discord/session-key-api.js";
import type {
DiscordPluralKitConfig,
DiscordSendComponents,
DiscordSendEmbeds,
InspectedDiscordAccount,
ResolvedDiscordAccount,
ThreadBindingManager,
ThreadBindingRecord,
ThreadBindingTargetKind,
} from "../channels/discord/plugin-sdk-bridge.js";
import {
collectDiscordStatusIssues,
@ -25,7 +40,6 @@ import {
import {
addRoleDiscord,
auditDiscordChannelPermissions,
autoBindSpawnedDiscordSubagent,
banMemberDiscord,
collectDiscordAuditChannelIds,
createChannelDiscord,
@ -47,7 +61,6 @@ import {
fetchVoiceStatusDiscord,
getGateway,
getPresence,
getThreadBindingManager,
hasAnyGuildPermissionDiscord,
kickMemberDiscord,
listDiscordDirectoryGroupsLive,
@ -56,7 +69,6 @@ import {
listGuildEmojisDiscord,
listPinsDiscord,
listScheduledEventsDiscord,
listThreadBindingsBySessionKey,
listThreadsDiscord,
monitorDiscordProvider,
moveChannelDiscord,
@ -70,10 +82,6 @@ import {
removeRoleDiscord,
resolveDiscordChannelAllowlist,
resolveDiscordUserAllowlist,
resolveThreadBindingIdleTimeoutMs,
resolveThreadBindingInactivityExpiresAt,
resolveThreadBindingMaxAgeExpiresAt,
resolveThreadBindingMaxAgeMs,
searchMessagesDiscord,
sendDiscordComponentMessage,
sendMessageDiscord,
@ -82,16 +90,12 @@ import {
sendTypingDiscord,
sendVoiceMessageDiscord,
setChannelPermissionDiscord,
setThreadBindingIdleTimeoutBySessionKey,
setThreadBindingMaxAgeBySessionKey,
timeoutMemberDiscord,
unbindThreadBindingsBySessionKey,
unpinMessageDiscord,
uploadEmojiDiscord,
uploadStickerDiscord,
listDiscordDirectoryGroupsFromConfig,
listDiscordDirectoryPeersFromConfig,
normalizeExplicitDiscordSessionKey,
} from "../channels/discord/plugin-sdk-bridge.js";
export type {

View File

@ -266,6 +266,9 @@ describe("plugin-sdk subpath exports", () => {
it("exports Discord helpers", () => {
expect(typeof discordSdk.buildChannelConfigSchema).toBe("function");
expect(typeof discordSdk.DiscordConfigSchema).toBe("object");
expect(typeof discordSdk.getThreadBindingManager).toBe("function");
expect(typeof discordSdk.listThreadBindingsBySessionKey).toBe("function");
expect(typeof discordSdk.normalizeExplicitDiscordSessionKey).toBe("function");
expect(typeof discordSdk.projectCredentialSnapshotFields).toBe("function");
expect("resolveDiscordAccount" in asExports(discordSdk)).toBe(false);
});