426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
386 lines
11 KiB
TypeScript
386 lines
11 KiB
TypeScript
/**
|
|
* Plugin definition and public barrel for `@elizaos/plugin-discord`. `init`
|
|
* registers the connector account provider, reads the Discord env vars, and
|
|
* prints the startup banner; the exported `Plugin` wires the `services` and
|
|
* `routes` arrays that make up this connector's surface. No actions or
|
|
* providers are registered — all behavior flows through services and
|
|
* `DiscordEventTypes` events.
|
|
*/
|
|
import {
|
|
getConnectorAccountManager,
|
|
type IAgentRuntime,
|
|
logger,
|
|
type Plugin,
|
|
} from "@elizaos/core";
|
|
import { printBanner } from "./banner";
|
|
import { createDiscordConnectorAccountProvider } from "./connector-account-provider";
|
|
import { DISCORD_SERVICE_NAME } from "./constants";
|
|
import { discordDataRoutes } from "./data-routes";
|
|
import { registerDiscordTargetSource } from "./discord-target-source";
|
|
import { DiscordOwnerPairingServiceImpl } from "./owner-pairing-service";
|
|
import { getPermissionValues } from "./permissions";
|
|
import { registerDiscordDmSensitiveRequestAdapter } from "./sensitive-request-adapter";
|
|
import { DiscordService } from "./service";
|
|
import { discordSetupRoutes } from "./setup-routes";
|
|
import { DiscordTestSuite } from "./tests";
|
|
import { registerDiscordTriageAdapter } from "./triage-adapter";
|
|
import { DiscordUserAccountScraperImpl } from "./user-account-scraper/service";
|
|
|
|
const discordPlugin: Plugin = {
|
|
name: "discord",
|
|
description:
|
|
"Discord service plugin for integration with Discord servers and channels",
|
|
connectorSources: [
|
|
{
|
|
source: "discord",
|
|
aliases: ["discord", "discord-local"],
|
|
sourceKind: "passive",
|
|
isPassive: true,
|
|
},
|
|
],
|
|
services: [
|
|
DiscordService,
|
|
DiscordOwnerPairingServiceImpl,
|
|
DiscordUserAccountScraperImpl,
|
|
],
|
|
routes: [...discordSetupRoutes, ...discordDataRoutes],
|
|
actions: [],
|
|
providers: [],
|
|
tests: [new DiscordTestSuite()],
|
|
autoEnable: {
|
|
connectorKeys: ["discord"],
|
|
},
|
|
init: async (_config: Record<string, string>, runtime: IAgentRuntime) => {
|
|
try {
|
|
const manager = getConnectorAccountManager(runtime);
|
|
manager.registerProvider(createDiscordConnectorAccountProvider(runtime));
|
|
} catch (err) {
|
|
logger.warn(
|
|
{
|
|
src: "plugin:discord",
|
|
err: err instanceof Error ? err.message : String(err),
|
|
},
|
|
"Failed to register Discord provider with ConnectorAccountManager",
|
|
);
|
|
}
|
|
|
|
registerDiscordDmSensitiveRequestAdapter(runtime);
|
|
|
|
// Register the cross-connector triage adapter for the "discord" source.
|
|
registerDiscordTriageAdapter();
|
|
|
|
// Register the Discord target-source enumerator so the host's
|
|
// connector-target-catalog can surface guild/channel quick-picks.
|
|
registerDiscordTargetSource(runtime);
|
|
|
|
const token = runtime.getSetting("DISCORD_API_TOKEN") as string;
|
|
const botTokens = runtime.getSetting("DISCORD_BOT_TOKENS") as string;
|
|
const applicationId = runtime.getSetting(
|
|
"DISCORD_APPLICATION_ID",
|
|
) as string;
|
|
const voiceChannelId = runtime.getSetting(
|
|
"DISCORD_VOICE_CHANNEL_ID",
|
|
) as string;
|
|
const channelIds = runtime.getSetting("CHANNEL_IDS") as string;
|
|
const listenChannelIds = runtime.getSetting(
|
|
"DISCORD_LISTEN_CHANNEL_IDS",
|
|
) as string;
|
|
const ignoreBotMessages = runtime.getSetting(
|
|
"DISCORD_SHOULD_IGNORE_BOT_MESSAGES",
|
|
) as string;
|
|
const ignoreDirectMessages = runtime.getSetting(
|
|
"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES",
|
|
) as string;
|
|
const respondOnlyToMentions = runtime.getSetting(
|
|
"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS",
|
|
) as string;
|
|
|
|
printBanner({
|
|
pluginName: "plugin-discord",
|
|
description: "Discord bot integration for servers and channels",
|
|
applicationId: applicationId || undefined,
|
|
discordPermissions: applicationId ? getPermissionValues() : undefined,
|
|
settings: [
|
|
{
|
|
name: "DISCORD_API_TOKEN",
|
|
value: token,
|
|
sensitive: true,
|
|
required: true,
|
|
},
|
|
{
|
|
name: "DISCORD_APPLICATION_ID",
|
|
value: applicationId,
|
|
},
|
|
{
|
|
name: "DISCORD_BOT_TOKENS",
|
|
value: botTokens,
|
|
sensitive: true,
|
|
},
|
|
{
|
|
name: "DISCORD_VOICE_CHANNEL_ID",
|
|
value: voiceChannelId,
|
|
},
|
|
{
|
|
name: "CHANNEL_IDS",
|
|
value: channelIds,
|
|
},
|
|
{
|
|
name: "DISCORD_LISTEN_CHANNEL_IDS",
|
|
value: listenChannelIds,
|
|
},
|
|
{
|
|
name: "DISCORD_SHOULD_IGNORE_BOT_MESSAGES",
|
|
value: ignoreBotMessages,
|
|
defaultValue: "true",
|
|
},
|
|
{
|
|
name: "DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES",
|
|
value: ignoreDirectMessages,
|
|
defaultValue: "true",
|
|
},
|
|
{
|
|
name: "DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS",
|
|
value: respondOnlyToMentions,
|
|
defaultValue: "true",
|
|
},
|
|
],
|
|
runtime,
|
|
});
|
|
|
|
if (
|
|
(!token || token.trim() === "") &&
|
|
(!botTokens || botTokens.trim() === "")
|
|
) {
|
|
logger.warn(
|
|
"Discord bot token not provided - Discord plugin is loaded but will not be functional",
|
|
);
|
|
logger.warn(
|
|
"To enable Discord functionality, provide DISCORD_API_TOKEN or DISCORD_BOT_TOKENS in your .env file",
|
|
);
|
|
}
|
|
},
|
|
async dispose(runtime: IAgentRuntime) {
|
|
const svc = runtime.getService<DiscordService>(DISCORD_SERVICE_NAME);
|
|
await svc?.stop();
|
|
},
|
|
};
|
|
|
|
export default discordPlugin;
|
|
|
|
// Account management exports (runtime utilities)
|
|
export {
|
|
DEFAULT_ACCOUNT_ID,
|
|
type DiscordMultiAccountConfig,
|
|
type DiscordTokenResolution,
|
|
type DiscordTokenSource,
|
|
isMultiAccountEnabled,
|
|
listDiscordAccountIds,
|
|
listEnabledDiscordAccounts,
|
|
normalizeAccountId,
|
|
normalizeDiscordToken,
|
|
type ResolvedDiscordAccount,
|
|
resolveDefaultDiscordAccountId,
|
|
resolveDiscordAccount,
|
|
resolveDiscordToken,
|
|
} from "./accounts";
|
|
// Allowlist exports
|
|
export {
|
|
type AllowListMatchSource,
|
|
allowListMatches,
|
|
type ChannelMatchSource,
|
|
type DiscordAllowList,
|
|
type DiscordAllowListMatch,
|
|
type DiscordChannelConfigResolved,
|
|
formatDiscordUserTag,
|
|
isDiscordAutoThreadOwnedByBot,
|
|
isDiscordGroupAllowedByPolicy,
|
|
normalizeDiscordAllowList,
|
|
normalizeDiscordSlug,
|
|
resolveDiscordAllowListMatch,
|
|
resolveDiscordChannelConfig,
|
|
resolveDiscordChannelConfigWithFallback,
|
|
resolveDiscordCommandAuthorized,
|
|
resolveDiscordGuildEntry,
|
|
resolveDiscordShouldRequireMention,
|
|
resolveDiscordUserAllowed,
|
|
resolveGroupDmAllow,
|
|
shouldEmitDiscordReactionNotification,
|
|
validateMessageAllowed,
|
|
} from "./allowlist";
|
|
export {
|
|
DEFAULT_DISCORD_AUDIO_LANES,
|
|
DISCORD_AUDIO_LANE_AMBIENT,
|
|
DISCORD_AUDIO_LANE_MUSIC,
|
|
DISCORD_AUDIO_LANE_SFX,
|
|
DISCORD_AUDIO_LANE_TTS,
|
|
type DiscordAudioLane,
|
|
type DiscordAudioLaneConfig,
|
|
getDiscordAudioLaneConfig,
|
|
normalizeDiscordAudioLane,
|
|
} from "./audio-lanes";
|
|
export type {
|
|
DiscordAudioPlaybackHandle,
|
|
DiscordAudioSinkPlayOptions,
|
|
DiscordAudioSinkStatus,
|
|
IDiscordAudioSink,
|
|
} from "./audio-sink";
|
|
// Channel configuration types (comprehensive config schema)
|
|
// Re-export config types that were in accounts.ts for backward compatibility
|
|
export type {
|
|
DiscordAccountConfig,
|
|
DiscordActionConfig,
|
|
DiscordChannelConfig,
|
|
DiscordConfig,
|
|
DiscordDmConfig,
|
|
DiscordExecApprovalConfig,
|
|
DiscordGuildChannelConfig,
|
|
DiscordGuildEntry,
|
|
DiscordIntentsConfig,
|
|
DiscordPluralKitConfig,
|
|
DiscordReactionNotificationMode,
|
|
} from "./config";
|
|
export { DISCORD_SERVICE_NAME } from "./constants";
|
|
export { discordDataRoutes } from "./data-routes";
|
|
export {
|
|
buildDiscordAvatarCacheFileName,
|
|
cacheDiscordAvatarUrl,
|
|
getDiscordAvatarCacheDir,
|
|
getDiscordAvatarCachePath,
|
|
getDiscordAvatarPublicPath,
|
|
isDiscordAvatarUrl,
|
|
} from "./discord-avatar-cache";
|
|
// Discord local IPC service + setup routes
|
|
export {
|
|
DISCORD_LOCAL_PLUGIN_NAME,
|
|
DISCORD_LOCAL_SERVICE_NAME,
|
|
DiscordLocalService,
|
|
default as discordLocalPlugin,
|
|
} from "./discord-local-service";
|
|
export {
|
|
cacheDiscordAvatarForRuntime,
|
|
isCanonicalDiscordSource,
|
|
resolveDiscordMessageAuthorProfile,
|
|
resolveDiscordRoomProfile,
|
|
resolveDiscordUserProfile,
|
|
resolveStoredDiscordEntityProfile,
|
|
} from "./discord-profiles";
|
|
// Messaging utilities exports
|
|
export {
|
|
buildChannelLink,
|
|
buildMessageLink,
|
|
type ChunkDiscordTextOpts,
|
|
chunkDiscordText,
|
|
chunkDiscordTextWithMode,
|
|
escapeDiscordMarkdown,
|
|
extractAllChannelMentions,
|
|
extractAllRoleMentions,
|
|
extractAllUserMentions,
|
|
extractChannelIdFromMention,
|
|
extractRoleIdFromMention,
|
|
extractUserIdFromMention,
|
|
formatDiscordChannelMention,
|
|
formatDiscordReactionEmoji,
|
|
formatDiscordRoleMention,
|
|
formatDiscordTimestamp,
|
|
formatDiscordUserMention,
|
|
formatMessageReactionEmoji,
|
|
messageContainsMention,
|
|
parseMessageLink,
|
|
resolveDiscordSystemLocation,
|
|
resolveTimestampMs,
|
|
sanitizeThreadName,
|
|
stripDiscordFormatting,
|
|
truncateText,
|
|
truncateUtf16Safe,
|
|
} from "./messaging";
|
|
// Native commands utilities exports
|
|
export {
|
|
type BuiltCommandOption,
|
|
buildCommandArgCustomId,
|
|
buildCommandArgMenu,
|
|
buildCommandText,
|
|
buildDiscordCommandOptions,
|
|
buildDiscordSlashCommand,
|
|
COMMAND_ARG_CUSTOM_ID_KEY,
|
|
type CommandArgButton,
|
|
type CommandArgButtonRow,
|
|
type CommandArgDefinition,
|
|
type CommandArgMenu,
|
|
type CommandArgs,
|
|
type CommandArgValues,
|
|
createCommandArgs,
|
|
decodeCommandArgValue,
|
|
encodeCommandArgValue,
|
|
isUnknownInteractionError,
|
|
type NativeCommandSpec,
|
|
parseCommandArgCustomId,
|
|
safeInteractionCall,
|
|
serializeCommandArgs,
|
|
} from "./native-commands";
|
|
export {
|
|
DISCORD_OWNER_PAIRING_SERVICE_TYPE,
|
|
type DiscordOwnerPairingService,
|
|
DiscordOwnerPairingServiceImpl,
|
|
} from "./owner-pairing-service";
|
|
export {
|
|
ELEVATED_PERMISSIONS,
|
|
hasElevatedPermissions,
|
|
isElevatedRole,
|
|
} from "./permissionEvents";
|
|
export {
|
|
type DiscordPermissionTier,
|
|
DiscordPermissionTiers,
|
|
type DiscordPermissionValues,
|
|
generateAllInviteUrls,
|
|
generateInviteUrl,
|
|
getPermissionValues,
|
|
} from "./permissions";
|
|
export type { DiscordService as IDiscordService } from "./service";
|
|
export { DiscordService } from "./service";
|
|
export { discordSetupRoutes } from "./setup-routes";
|
|
// Message-triage adapter (registered at init; exported for tests/consumers)
|
|
export { DiscordTriageAdapter, mapDiscordMemoryToRef } from "./triage-adapter";
|
|
export type {
|
|
AuditInfo,
|
|
ChannelPermissionsChangedPayload,
|
|
MemberRolesChangedPayload,
|
|
PermissionDiff,
|
|
PermissionState,
|
|
RoleLifecyclePayload,
|
|
RolePermissionsChangedPayload,
|
|
} from "./types";
|
|
export { DiscordEventTypes } from "./types";
|
|
export {
|
|
buildDiscordProbeScript,
|
|
captureDiscordDeliveryStatus,
|
|
closeDiscordTab,
|
|
DISCORD_APP_URL,
|
|
DISCORD_PROVIDER_ID,
|
|
DISCORD_USER_ACCOUNT_SCRAPER_SERVICE_TYPE,
|
|
type DiscordDesktopCdpStatus,
|
|
type DiscordDmInboxProbe,
|
|
type DiscordMessageSearchResult,
|
|
type DiscordTabIdentity,
|
|
type DiscordTabProbe,
|
|
type DiscordUserAccountScraper,
|
|
DiscordUserAccountScraperImpl,
|
|
type DiscordVisibleDmPreview,
|
|
discordBrowserWorkspaceAvailable,
|
|
discordUserAccountPartitionFor,
|
|
emptyDiscordDmInboxProbe,
|
|
ensureDiscordTab,
|
|
getDiscordDesktopCdpStatus,
|
|
navigateDiscordTabToHome,
|
|
probeDiscordCapturedPage,
|
|
probeDiscordDocumentState,
|
|
probeDiscordTab,
|
|
relaunchDiscordDesktopForCdp,
|
|
searchDiscordMessages,
|
|
sendDiscordViaDesktopCdp,
|
|
} from "./user-account-scraper";
|
|
export type {
|
|
DiscordVoicePlaybackOptions,
|
|
DiscordVoiceTarget,
|
|
DiscordVoiceTargetRegistration,
|
|
} from "./voice-target-registry";
|