@elizaos/plugin-discord 2.0.0-alpha.1 → 2.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accounts.d.ts +164 -0
- package/dist/accounts.d.ts.map +1 -0
- package/dist/actions/chatWithAttachments.d.ts +4 -0
- package/dist/actions/chatWithAttachments.d.ts.map +1 -0
- package/dist/actions/createPoll.d.ts +4 -0
- package/dist/actions/createPoll.d.ts.map +1 -0
- package/dist/actions/deleteMessage.d.ts +4 -0
- package/dist/actions/deleteMessage.d.ts.map +1 -0
- package/dist/actions/downloadMedia.d.ts +4 -0
- package/dist/actions/downloadMedia.d.ts.map +1 -0
- package/dist/actions/editMessage.d.ts +4 -0
- package/dist/actions/editMessage.d.ts.map +1 -0
- package/dist/actions/getUserInfo.d.ts +4 -0
- package/dist/actions/getUserInfo.d.ts.map +1 -0
- package/dist/actions/joinChannel.d.ts +4 -0
- package/dist/actions/joinChannel.d.ts.map +1 -0
- package/dist/actions/leaveChannel.d.ts +4 -0
- package/dist/actions/leaveChannel.d.ts.map +1 -0
- package/dist/actions/listChannels.d.ts +4 -0
- package/dist/actions/listChannels.d.ts.map +1 -0
- package/dist/actions/pinMessage.d.ts +4 -0
- package/dist/actions/pinMessage.d.ts.map +1 -0
- package/dist/actions/reactToMessage.d.ts +4 -0
- package/dist/actions/reactToMessage.d.ts.map +1 -0
- package/dist/actions/readChannel.d.ts +4 -0
- package/dist/actions/readChannel.d.ts.map +1 -0
- package/dist/actions/searchMessages.d.ts +4 -0
- package/dist/actions/searchMessages.d.ts.map +1 -0
- package/dist/actions/sendDM.d.ts +4 -0
- package/dist/actions/sendDM.d.ts.map +1 -0
- package/dist/actions/sendMessage.d.ts +4 -0
- package/dist/actions/sendMessage.d.ts.map +1 -0
- package/dist/actions/serverInfo.d.ts +4 -0
- package/dist/actions/serverInfo.d.ts.map +1 -0
- package/dist/actions/summarizeConversation.d.ts +4 -0
- package/dist/actions/summarizeConversation.d.ts.map +1 -0
- package/dist/actions/transcribeMedia.d.ts +4 -0
- package/dist/actions/transcribeMedia.d.ts.map +1 -0
- package/dist/actions/unpinMessage.d.ts +4 -0
- package/dist/actions/unpinMessage.d.ts.map +1 -0
- package/dist/allowlist.d.ts +198 -0
- package/dist/allowlist.d.ts.map +1 -0
- package/dist/attachments.d.ts +92 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/banner.d.ts +39 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/compat.d.ts +56 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/config.d.ts +156 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/environment.d.ts +22 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/generated/prompts/typescript/prompts.d.ts +44 -0
- package/dist/generated/prompts/typescript/prompts.d.ts.map +1 -0
- package/dist/generated/specs/spec-helpers.d.ts +49 -0
- package/dist/generated/specs/spec-helpers.d.ts.map +1 -0
- package/dist/generated/specs/specs.d.ts +87 -0
- package/dist/generated/specs/specs.d.ts.map +1 -0
- package/dist/identity.d.ts +4 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.browser.d.ts +34 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14175 -0
- package/dist/index.js.map +133 -0
- package/dist/messages.d.ts +55 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messaging.d.ts +129 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/native-commands.d.ts +142 -0
- package/dist/native-commands.d.ts.map +1 -0
- package/dist/permissionEvents.d.ts +42 -0
- package/dist/permissionEvents.d.ts.map +1 -0
- package/dist/permissions.d.ts +36 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/providers/channelState.d.ts +14 -0
- package/dist/providers/channelState.d.ts.map +1 -0
- package/dist/providers/guildInfo.d.ts +15 -0
- package/dist/providers/guildInfo.d.ts.map +1 -0
- package/dist/providers/voiceState.d.ts +12 -0
- package/dist/providers/voiceState.d.ts.map +1 -0
- package/dist/service.d.ts +403 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/test-setup.d.ts +1 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/tests.d.ts +123 -0
- package/dist/tests.d.ts.map +1 -0
- package/dist/types.d.ts +315 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/voice.d.ts +230 -0
- package/dist/voice.d.ts.map +1 -0
- package/package.json +134 -124
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { ChannelType, type Character, type Content, type IAgentRuntime, type Media, type Memory, Service, type TargetInfo } from "@elizaos/core";
|
|
2
|
+
/**
|
|
3
|
+
* IMPORTANT: Discord ID Handling - Why stringToUuid() instead of asUUID()
|
|
4
|
+
*
|
|
5
|
+
* Discord uses "snowflake" IDs - large 64-bit integers represented as strings
|
|
6
|
+
* (e.g., "1253563208833433701"). These are NOT valid UUIDs.
|
|
7
|
+
*
|
|
8
|
+
* UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12 hex digits with dashes)
|
|
9
|
+
* Discord ID: 1253563208833433701 (plain number string)
|
|
10
|
+
*
|
|
11
|
+
* The two UUID-related functions behave differently:
|
|
12
|
+
*
|
|
13
|
+
* - `asUUID(str)` - VALIDATES that the string is already a valid UUID format.
|
|
14
|
+
* If not, it throws: "Error: Invalid UUID format: 1253563208833433701"
|
|
15
|
+
* Use only when you're certain the input is already a valid UUID.
|
|
16
|
+
*
|
|
17
|
+
* - `stringToUuid(str)` - CONVERTS any string into a deterministic UUID by hashing it.
|
|
18
|
+
* Always succeeds. The same input always produces the same UUID output.
|
|
19
|
+
* Use this for Discord snowflake IDs.
|
|
20
|
+
*
|
|
21
|
+
* When working with Discord IDs in ElizaOS:
|
|
22
|
+
*
|
|
23
|
+
* 1. `stringToUuid(discordId)` - For storing Discord IDs in UUID fields (e.g., `messageServerId`).
|
|
24
|
+
*
|
|
25
|
+
* 2. `createUniqueUuid(runtime, discordId)` - For `worldId` and `roomId`. This adds the agent's
|
|
26
|
+
* ID to the hash, ensuring each agent has its own unique namespace for the same Discord server.
|
|
27
|
+
*
|
|
28
|
+
* 3. `messageServerId` - The correct property name for server IDs on Room and World objects.
|
|
29
|
+
*
|
|
30
|
+
* 4. Discord-specific events (e.g., DiscordEventTypes.VOICE_STATE_UPDATE) are not in core's
|
|
31
|
+
* EventPayloadMap. When emitting these events, cast to `string[]` and payload to `any`
|
|
32
|
+
* to use the generic emitEvent overload.
|
|
33
|
+
*/
|
|
34
|
+
import { type Channel, Client as DiscordJsClient, type Message } from "discord.js";
|
|
35
|
+
import { type ICompatRuntime } from "./compat";
|
|
36
|
+
import { MessageManager } from "./messages";
|
|
37
|
+
import { type ChannelHistoryOptions, type ChannelHistoryResult, type IDiscordService } from "./types";
|
|
38
|
+
import { VoiceManager } from "./voice";
|
|
39
|
+
/**
|
|
40
|
+
* DiscordService class representing a service for interacting with Discord.
|
|
41
|
+
* @extends Service
|
|
42
|
+
* @implements IDiscordService
|
|
43
|
+
* @property {string} serviceType - The type of service, set to DISCORD_SERVICE_NAME.
|
|
44
|
+
* @property {string} capabilityDescription - A description of the service's capabilities.
|
|
45
|
+
* @property {DiscordJsClient} client - The DiscordJsClient used for communication.
|
|
46
|
+
* @property {Character} character - The character associated with the service.
|
|
47
|
+
* @property {MessageManager} messageManager - The manager for handling messages.
|
|
48
|
+
* @property {VoiceManager} voiceManager - The manager for handling voice communication.
|
|
49
|
+
*/
|
|
50
|
+
export declare class DiscordService extends Service implements IDiscordService {
|
|
51
|
+
protected runtime: ICompatRuntime;
|
|
52
|
+
static serviceType: string;
|
|
53
|
+
capabilityDescription: string;
|
|
54
|
+
client: DiscordJsClient | null;
|
|
55
|
+
character: Character;
|
|
56
|
+
messageManager?: MessageManager;
|
|
57
|
+
voiceManager?: VoiceManager;
|
|
58
|
+
private discordSettings;
|
|
59
|
+
private userSelections;
|
|
60
|
+
private timeouts;
|
|
61
|
+
clientReadyPromise: Promise<void> | null;
|
|
62
|
+
private slashCommands;
|
|
63
|
+
private commandRegistrationQueue;
|
|
64
|
+
/**
|
|
65
|
+
* Slash command names that should bypass allowed channel restrictions.
|
|
66
|
+
*/
|
|
67
|
+
private allowAllSlashCommands;
|
|
68
|
+
/**
|
|
69
|
+
* List of allowed channel IDs (parsed from CHANNEL_IDS env var).
|
|
70
|
+
* If undefined, all channels are allowed.
|
|
71
|
+
*/
|
|
72
|
+
private allowedChannelIds?;
|
|
73
|
+
/**
|
|
74
|
+
* Set of dynamically added channel IDs through joinChannel action.
|
|
75
|
+
* These are merged with allowedChannelIds for runtime channel management.
|
|
76
|
+
*/
|
|
77
|
+
private dynamicChannelIds;
|
|
78
|
+
/**
|
|
79
|
+
* Constructor for Discord client.
|
|
80
|
+
* Initializes the Discord client with specified intents and partials,
|
|
81
|
+
* sets up event listeners, and ensures all servers exist.
|
|
82
|
+
*
|
|
83
|
+
* @param {IAgentRuntime} runtime - The AgentRuntime instance
|
|
84
|
+
*/
|
|
85
|
+
constructor(runtime: IAgentRuntime);
|
|
86
|
+
static start(runtime: IAgentRuntime): Promise<DiscordService>;
|
|
87
|
+
/**
|
|
88
|
+
* The SendHandlerFunction implementation for Discord.
|
|
89
|
+
* @param {IAgentRuntime} runtime - The runtime instance.
|
|
90
|
+
* @param {TargetInfo} target - The target information for the message.
|
|
91
|
+
* @param {Content} content - The content of the message to send.
|
|
92
|
+
* @returns {Promise<void>} A promise that resolves when the message is sent or rejects on error.
|
|
93
|
+
* @throws {Error} If the client is not ready, target is invalid, or sending fails.
|
|
94
|
+
*/
|
|
95
|
+
handleSendMessage(runtime: IAgentRuntime, target: TargetInfo, content: Content): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Set up event listeners for the client.
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
private setupEventListeners;
|
|
101
|
+
/**
|
|
102
|
+
* Handles the event when a new member joins a guild.
|
|
103
|
+
*
|
|
104
|
+
* **Event Design Note:**
|
|
105
|
+
* We intentionally do NOT emit the standardized `EventType.ENTITY_JOINED` here.
|
|
106
|
+
* In ElizaOS's abstraction model:
|
|
107
|
+
* - A Discord "guild" maps to a "world" (the server/community)
|
|
108
|
+
* - A Discord "channel" maps to a "room" (a specific conversation space)
|
|
109
|
+
*
|
|
110
|
+
* `EventType.ENTITY_JOINED` requires a `roomId` because the bootstrap plugin's
|
|
111
|
+
* handler calls `syncSingleUser()` to sync the entity to a specific room. When
|
|
112
|
+
* a member joins a guild, they've joined the "world" but haven't joined any
|
|
113
|
+
* specific "room" yet - they're just a potential participant.
|
|
114
|
+
*
|
|
115
|
+
* The entity will be properly synced to rooms when they first interact:
|
|
116
|
+
* - First message in a channel → message handler calls `ensureConnection()`
|
|
117
|
+
* - Joining a voice channel → voice handler syncs them to that room
|
|
118
|
+
*
|
|
119
|
+
* We still emit the Discord-specific `DiscordEventTypes.ENTITY_JOINED` so that
|
|
120
|
+
* Discord-aware plugins can react to guild member joins (e.g., welcome messages,
|
|
121
|
+
* role assignment, moderation checks).
|
|
122
|
+
*
|
|
123
|
+
* @param {GuildMember} member - The GuildMember object representing the new member.
|
|
124
|
+
* @returns {Promise<void>} - A Promise that resolves once the event handling is complete.
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
private handleGuildMemberAdd;
|
|
128
|
+
/**
|
|
129
|
+
* Registers slash commands with Discord.
|
|
130
|
+
*
|
|
131
|
+
* This method uses a hybrid permission system that combines:
|
|
132
|
+
* 1. Discord's native permission features (default_member_permissions, contexts)
|
|
133
|
+
* 2. ElizaOS channel whitelist bypass (bypassChannelWhitelist flag)
|
|
134
|
+
* 3. Custom validation functions (validator callback)
|
|
135
|
+
*
|
|
136
|
+
* ## Design Decisions
|
|
137
|
+
*
|
|
138
|
+
* ### Why Hybrid Approach?
|
|
139
|
+
* - Discord's native permissions are powerful but limited to role-based access
|
|
140
|
+
* - ElizaOS needs programmatic control for channel restrictions and custom logic
|
|
141
|
+
* - Combining both gives developers the best of both worlds
|
|
142
|
+
*
|
|
143
|
+
* ### Why Transform Simple Flags?
|
|
144
|
+
* - Developer experience: `guildOnly: true` is clearer than `contexts: [0]`
|
|
145
|
+
* - Abstraction: Shields developers from Discord API changes
|
|
146
|
+
* - Sensible defaults: Zero config should "just work"
|
|
147
|
+
*
|
|
148
|
+
* ### Why Three Registration Categories?
|
|
149
|
+
*
|
|
150
|
+
* Commands are categorized based on where they should be available:
|
|
151
|
+
*
|
|
152
|
+
* 1. **Global commands** (no guildOnly, no guildIds):
|
|
153
|
+
* - Registered globally via `application.commands.set()` for DM access
|
|
154
|
+
* - ALSO registered per-guild for instant availability in guilds
|
|
155
|
+
* - Guild version overrides global (no duplicates shown in Discord)
|
|
156
|
+
* - Best of both worlds: instant in guilds + works in DMs
|
|
157
|
+
*
|
|
158
|
+
* 2. **Guild-only commands** (guildOnly: true or contexts: [0]):
|
|
159
|
+
* - Registered per-guild via `application.commands.set(cmds, guildId)`
|
|
160
|
+
* - NOT available in DMs (correct behavior)
|
|
161
|
+
* - Instant availability in guilds
|
|
162
|
+
* - New guilds get commands via guildCreate event
|
|
163
|
+
*
|
|
164
|
+
* 3. **Targeted commands** (has guildIds array):
|
|
165
|
+
* - Registered only to specified guilds via `.create()` or `.edit()`
|
|
166
|
+
* - Useful for testing or server-specific features
|
|
167
|
+
* - Instant updates
|
|
168
|
+
*
|
|
169
|
+
* ### Why Register Global Commands Both Globally AND Per-Guild?
|
|
170
|
+
* - Global registration alone takes up to 1 hour to propagate (Discord limitation)
|
|
171
|
+
* - Per-guild registration gives instant availability
|
|
172
|
+
* - Guild commands override global ones in that guild (no duplicates)
|
|
173
|
+
* - Global registration still needed for DM access (no guild context in DMs)
|
|
174
|
+
*
|
|
175
|
+
* ### Why Not Register Everything Per-Guild Only?
|
|
176
|
+
* - Commands that work in DMs MUST be registered globally
|
|
177
|
+
* - There's no guild context in DMs, so per-guild commands don't appear there
|
|
178
|
+
*
|
|
179
|
+
* @param commands - Array of slash commands to register
|
|
180
|
+
* @returns Promise that resolves when registration is complete
|
|
181
|
+
* @private
|
|
182
|
+
*/
|
|
183
|
+
private registerSlashCommands;
|
|
184
|
+
/**
|
|
185
|
+
* Transforms an ElizaOS slash command to Discord API format.
|
|
186
|
+
* This bridges our developer-friendly API with Discord's native requirements.
|
|
187
|
+
* @param {DiscordSlashCommand} cmd - The ElizaOS command definition
|
|
188
|
+
* @returns {object} Discord API compatible command object
|
|
189
|
+
* @private
|
|
190
|
+
*/
|
|
191
|
+
private transformCommandToDiscordApi;
|
|
192
|
+
/**
|
|
193
|
+
* Checks if a command is guild-only (shouldn't appear in DMs).
|
|
194
|
+
*
|
|
195
|
+
* A command is considered guild-only if:
|
|
196
|
+
* - `contexts: [0]` is set (Discord's native format, where 0 = Guild only)
|
|
197
|
+
* - `guildOnly: true` is set AND no contexts override is provided
|
|
198
|
+
*
|
|
199
|
+
* `contexts` takes precedence over `guildOnly` to be consistent with
|
|
200
|
+
* `transformCommandToDiscordApi`. { guildOnly: true, contexts: [0, 1] }
|
|
201
|
+
* will correctly enable DM access (not be treated as guild-only).
|
|
202
|
+
*
|
|
203
|
+
* @param {DiscordSlashCommand} cmd - The command to check
|
|
204
|
+
* @returns {boolean} True if the command should only be available in guilds
|
|
205
|
+
* @private
|
|
206
|
+
*/
|
|
207
|
+
private isGuildOnlyCommand;
|
|
208
|
+
/**
|
|
209
|
+
* Handles the event when the bot joins a guild. It logs the guild name, fetches additional information about the guild, scans the guild for voice data, creates standardized world data structure, generates unique IDs, and emits events to the runtime.
|
|
210
|
+
* @param {Guild} guild - The guild that the bot has joined.
|
|
211
|
+
* @returns {Promise<void>} A promise that resolves when the guild creation is handled.
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
private handleGuildCreate;
|
|
215
|
+
/**
|
|
216
|
+
* Handles interactions created by the user, specifically commands and message components.
|
|
217
|
+
* @param {Interaction} interaction - The interaction object received.
|
|
218
|
+
* @returns {Promise<void>} A promise that resolves when the interaction is handled.
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
private handleInteractionCreate;
|
|
222
|
+
/**
|
|
223
|
+
* Builds a standardized list of rooms from Discord guild channels.
|
|
224
|
+
*
|
|
225
|
+
* @param {Guild} guild The guild to build rooms for.
|
|
226
|
+
* @param {UUID} _worldId The ID of the world to associate with the rooms (currently unused in favor of direct channel to room mapping).
|
|
227
|
+
* @returns {Promise<Array<{ id: UUID; name: string; type: ChannelType; channelId: string; participants: UUID[] }>>} An array of standardized room objects.
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
private buildStandardizedRooms;
|
|
231
|
+
/**
|
|
232
|
+
* Builds a standardized list of users (entities) from Discord guild members.
|
|
233
|
+
* Implements different strategies based on guild size for performance.
|
|
234
|
+
*
|
|
235
|
+
* @param {Guild} guild - The guild from which to build the user list.
|
|
236
|
+
* @returns {Promise<Entity[]>} A promise that resolves with an array of standardized entity objects.
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
private buildStandardizedUsers;
|
|
240
|
+
/**
|
|
241
|
+
* Handles tasks to be performed once the Discord client is fully ready and connected.
|
|
242
|
+
* This includes fetching guilds, scanning for voice data, and emitting connection events.
|
|
243
|
+
* @private
|
|
244
|
+
* @returns {Promise<void>} A promise that resolves when all on-ready tasks are completed.
|
|
245
|
+
*/
|
|
246
|
+
private onReady;
|
|
247
|
+
/**
|
|
248
|
+
* Registers send handlers for the Discord service instance.
|
|
249
|
+
* This allows the runtime to correctly dispatch messages to this service.
|
|
250
|
+
* @param {IAgentRuntime} runtime - The agent runtime instance.
|
|
251
|
+
* @param {DiscordService} serviceInstance - The instance of the DiscordService.
|
|
252
|
+
* @static
|
|
253
|
+
*/
|
|
254
|
+
static registerSendHandlers(runtime: IAgentRuntime, serviceInstance: DiscordService): void;
|
|
255
|
+
/**
|
|
256
|
+
* Fetches all members who have access to a specific text channel.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} channelId - The Discord ID of the text channel.
|
|
259
|
+
* @param {boolean} [useCache=true] - Whether to prioritize cached data. Defaults to true.
|
|
260
|
+
* @returns {Promise<Array<{id: string, username: string, displayName: string}>>} A promise that resolves with an array of channel member objects, each containing id, username, and displayName.
|
|
261
|
+
*/
|
|
262
|
+
getTextChannelMembers(channelId: string, useCache?: boolean): Promise<Array<{
|
|
263
|
+
id: string;
|
|
264
|
+
username: string;
|
|
265
|
+
displayName: string;
|
|
266
|
+
}>>;
|
|
267
|
+
/**
|
|
268
|
+
* Fetches the topic/description of a Discord text channel.
|
|
269
|
+
*
|
|
270
|
+
* WHY THIS METHOD EXISTS:
|
|
271
|
+
* =======================
|
|
272
|
+
* Room metadata contains topic from initial sync, but channel topics can change.
|
|
273
|
+
* This method lets plugins fetch FRESH topic data directly from Discord API.
|
|
274
|
+
*
|
|
275
|
+
* Used by plugin-content-seeder to get authoritative topic data for discussion seeding.
|
|
276
|
+
*
|
|
277
|
+
* WHY NOT JUST USE METADATA:
|
|
278
|
+
* Room.metadata.topic is set at sync time and may be stale if the Discord admin
|
|
279
|
+
* updates the channel topic. For plugins that care about freshness, this method
|
|
280
|
+
* provides a way to get current data.
|
|
281
|
+
*
|
|
282
|
+
* TRADEOFF: This makes an API call, so it's slower than reading metadata.
|
|
283
|
+
* Use metadata for most cases, this method when freshness matters.
|
|
284
|
+
*
|
|
285
|
+
* @param {string} channelId - The Discord ID of the text channel.
|
|
286
|
+
* @returns {Promise<string | null>} The channel topic, or null if not available.
|
|
287
|
+
*/
|
|
288
|
+
getChannelTopic(channelId: string): Promise<string | null>;
|
|
289
|
+
/**
|
|
290
|
+
* Generic handler for reaction events (add/remove).
|
|
291
|
+
* @private
|
|
292
|
+
*/
|
|
293
|
+
private handleReaction;
|
|
294
|
+
/**
|
|
295
|
+
* Handles reaction addition.
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
private handleReactionAdd;
|
|
299
|
+
/**
|
|
300
|
+
* Handles reaction removal.
|
|
301
|
+
* @private
|
|
302
|
+
*/
|
|
303
|
+
private handleReactionRemove;
|
|
304
|
+
/**
|
|
305
|
+
* Checks if a channel ID is allowed based on both env config and dynamic additions.
|
|
306
|
+
* @param {string} channelId - The channel ID to check
|
|
307
|
+
* @returns {boolean} Whether the channel is allowed
|
|
308
|
+
*/
|
|
309
|
+
isChannelAllowed(channelId: string): boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Adds a channel to the dynamic allowed list.
|
|
312
|
+
* @param {string} channelId - The channel ID to add
|
|
313
|
+
* @returns {boolean} Whether the channel was successfully added
|
|
314
|
+
*/
|
|
315
|
+
addAllowedChannel(channelId: string): boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Removes a channel from the dynamic allowed list.
|
|
318
|
+
* @param {string} channelId - The channel ID to remove
|
|
319
|
+
* @returns {boolean} Whether the channel was in the list and removed
|
|
320
|
+
*/
|
|
321
|
+
removeAllowedChannel(channelId: string): boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Gets the list of all allowed channels (env + dynamic).
|
|
324
|
+
* @returns {string[]} Array of allowed channel IDs
|
|
325
|
+
*/
|
|
326
|
+
getAllowedChannels(): string[];
|
|
327
|
+
/**
|
|
328
|
+
* Type guard to check if a channel is a guild text-based channel
|
|
329
|
+
* @private
|
|
330
|
+
*/
|
|
331
|
+
private isGuildTextBasedChannel;
|
|
332
|
+
/**
|
|
333
|
+
* Helper to delay execution
|
|
334
|
+
* @private
|
|
335
|
+
*/
|
|
336
|
+
private delay;
|
|
337
|
+
/**
|
|
338
|
+
* Get spider state for a channel from the database
|
|
339
|
+
* @private
|
|
340
|
+
*/
|
|
341
|
+
private getSpiderState;
|
|
342
|
+
/**
|
|
343
|
+
* Save spider state for a channel to the database
|
|
344
|
+
* @private
|
|
345
|
+
*/
|
|
346
|
+
private saveSpiderState;
|
|
347
|
+
/**
|
|
348
|
+
* Fetches and persists message history from a Discord channel.
|
|
349
|
+
* Supports pagination, state tracking, and streaming via callback.
|
|
350
|
+
*
|
|
351
|
+
* Persistence behavior:
|
|
352
|
+
* - When `onBatch` callback is NOT provided: Messages are automatically persisted
|
|
353
|
+
* to the database and accumulated in the returned `messages` array.
|
|
354
|
+
* - When `onBatch` callback IS provided: Messages are passed to the callback and
|
|
355
|
+
* the caller is responsible for persistence. This allows for custom handling.
|
|
356
|
+
*
|
|
357
|
+
* @param {string} channelId - The Discord channel ID to fetch from
|
|
358
|
+
* @param {ChannelHistoryOptions} options - Options for the fetch operation
|
|
359
|
+
* @returns {Promise<ChannelHistoryResult>} The result with messages and stats
|
|
360
|
+
*/
|
|
361
|
+
fetchChannelHistory(channelId: string, options?: ChannelHistoryOptions): Promise<ChannelHistoryResult>;
|
|
362
|
+
/**
|
|
363
|
+
* Builds a Memory object from a Discord Message.
|
|
364
|
+
* This is a reusable helper for converting Discord messages to ElizaOS Memory format.
|
|
365
|
+
*
|
|
366
|
+
* @param {Message} message - The Discord message to convert
|
|
367
|
+
* @param {Object} options - Optional parameters
|
|
368
|
+
* @param {string} options.processedContent - Pre-processed text content (if already processed, to avoid double-processing)
|
|
369
|
+
* @param {Media[]} options.processedAttachments - Pre-processed attachments (if already processed)
|
|
370
|
+
* @param {Object} options.extraContent - Additional content fields to merge into the memory content
|
|
371
|
+
* @param {Object} options.extraMetadata - Additional metadata fields to merge into the memory metadata
|
|
372
|
+
* @returns {Promise<Memory | null>} The Memory object, or null if the message is invalid
|
|
373
|
+
*/
|
|
374
|
+
buildMemoryFromMessage(message: Message, options?: {
|
|
375
|
+
processedContent?: string;
|
|
376
|
+
processedAttachments?: Media[];
|
|
377
|
+
extraContent?: Record<string, unknown>;
|
|
378
|
+
extraMetadata?: Record<string, unknown>;
|
|
379
|
+
}): Promise<Memory | null>;
|
|
380
|
+
/**
|
|
381
|
+
* Ensures entity connections exist for a batch of Discord messages using batch API.
|
|
382
|
+
* This should be called before persisting memories to avoid FK constraint failures.
|
|
383
|
+
*
|
|
384
|
+
* @param {Message[]} messages - The Discord messages to ensure connections for
|
|
385
|
+
* @param {Set<string>} ensuredEntityIds - Optional set of already-ensured entity IDs (for caching across batches)
|
|
386
|
+
* @returns {Promise<void>}
|
|
387
|
+
*/
|
|
388
|
+
private ensureConnectionsForMessages;
|
|
389
|
+
/**
|
|
390
|
+
* Stops the Discord service and cleans up resources.
|
|
391
|
+
* Implements the abstract method from the Service class.
|
|
392
|
+
*/
|
|
393
|
+
stop(): Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Asynchronously retrieves the type of a given channel.
|
|
396
|
+
*
|
|
397
|
+
* @param {Channel} channel - The channel for which to determine the type.
|
|
398
|
+
* @returns {Promise<ChannelType>} A Promise that resolves with the type of the channel.
|
|
399
|
+
*/
|
|
400
|
+
getChannelType(channel: Channel): Promise<ChannelType>;
|
|
401
|
+
}
|
|
402
|
+
export default DiscordService;
|
|
403
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=test-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../test-setup.ts"],"names":[],"mappings":""}
|
package/dist/tests.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Readable } from "node:stream";
|
|
2
|
+
import { type VoiceConnection } from "@discordjs/voice";
|
|
3
|
+
import { type IAgentRuntime, type TestSuite } from "@elizaos/core";
|
|
4
|
+
import { AttachmentBuilder, type Guild, type TextChannel } from "discord.js";
|
|
5
|
+
import type { DiscordService } from "./service";
|
|
6
|
+
/**
|
|
7
|
+
* Represents a test suite for Discord functionality.
|
|
8
|
+
* @class DiscordTestSuite
|
|
9
|
+
* @implements TestSuite
|
|
10
|
+
* @property {string} name - The name of the test suite
|
|
11
|
+
* @property {DiscordService | null} discordClient - The Discord client instance
|
|
12
|
+
* @property {Array<{ name: string; fn: (runtime: IAgentRuntime) => Promise<void> }>} tests - Array of test functions
|
|
13
|
+
*/
|
|
14
|
+
export declare class DiscordTestSuite implements TestSuite {
|
|
15
|
+
name: string;
|
|
16
|
+
private discordClient;
|
|
17
|
+
tests: {
|
|
18
|
+
name: string;
|
|
19
|
+
fn: (runtime: IAgentRuntime) => Promise<void>;
|
|
20
|
+
}[];
|
|
21
|
+
/**
|
|
22
|
+
* Constructor for initializing the tests array with test cases to be executed.
|
|
23
|
+
*
|
|
24
|
+
* @constructor
|
|
25
|
+
* @this {TestSuite}
|
|
26
|
+
*/
|
|
27
|
+
constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Asynchronously tests the creation of Discord client using the provided runtime.
|
|
30
|
+
*
|
|
31
|
+
* @param {IAgentRuntime} runtime - The agent runtime used to obtain the Discord service.
|
|
32
|
+
* @returns {Promise<void>} - A Promise that resolves once the Discord client is ready.
|
|
33
|
+
* @throws {Error} - If an error occurs while creating the Discord client.
|
|
34
|
+
*/
|
|
35
|
+
testCreatingDiscordClient(runtime: IAgentRuntime): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Asynchronously tests the join voice slash command functionality.
|
|
38
|
+
*
|
|
39
|
+
* @param {IAgentRuntime} runtime - The runtime environment for the agent.
|
|
40
|
+
* @returns {Promise<void>} - A promise that resolves once the test is complete.
|
|
41
|
+
* @throws {Error} - If there is an error in executing the slash command test.
|
|
42
|
+
*/
|
|
43
|
+
testJoinVoiceSlashCommand(runtime: IAgentRuntime): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Asynchronously tests the leave voice channel slash command.
|
|
46
|
+
*
|
|
47
|
+
* @param {IAgentRuntime} runtime - The Agent Runtime instance.
|
|
48
|
+
* @returns {Promise<void>} A promise that resolves when the test is complete.
|
|
49
|
+
*/
|
|
50
|
+
testLeaveVoiceSlashCommand(runtime: IAgentRuntime): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Test Text to Speech playback.
|
|
53
|
+
* @param {IAgentRuntime} runtime - The Agent Runtime instance.
|
|
54
|
+
* @throws {Error} - If voice channel is invalid, voice connection fails to become ready, or no text to speech service found.
|
|
55
|
+
*/
|
|
56
|
+
testTextToSpeechPlayback(runtime: IAgentRuntime): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Asynchronously tests sending a text message to a specified channel.
|
|
59
|
+
*
|
|
60
|
+
* @param {IAgentRuntime} runtime - The runtime for the agent.
|
|
61
|
+
* @returns {Promise<void>} A Promise that resolves when the message is sent successfully.
|
|
62
|
+
* @throws {Error} If there is an error in sending the text message.
|
|
63
|
+
*/
|
|
64
|
+
testSendingTextMessage(runtime: IAgentRuntime): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Asynchronously handles sending a test message using the given runtime and mock user data.
|
|
67
|
+
*
|
|
68
|
+
* @param {IAgentRuntime} runtime - The agent runtime object.
|
|
69
|
+
* @returns {Promise<void>} A Promise that resolves once the message is handled.
|
|
70
|
+
*/
|
|
71
|
+
testHandlingMessage(runtime: IAgentRuntime): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Asynchronously retrieves the test channel associated with the provided runtime.
|
|
74
|
+
*
|
|
75
|
+
* @param {IAgentRuntime} runtime - The runtime object containing necessary information.
|
|
76
|
+
* @returns {Promise<Channel>} The test channel retrieved from the Discord client.
|
|
77
|
+
* @throws {Error} If no test channel is found.
|
|
78
|
+
*/
|
|
79
|
+
getTestChannel(runtime: IAgentRuntime): Promise<import("discord.js").Channel>;
|
|
80
|
+
/**
|
|
81
|
+
* Async function to send a message to a text-based channel.
|
|
82
|
+
*
|
|
83
|
+
* @param {TextChannel} channel - The text-based channel the message is being sent to.
|
|
84
|
+
* @param {string} messageContent - The content of the message being sent.
|
|
85
|
+
* @param {AttachmentBuilder[]} files - An array of files to include in the message.
|
|
86
|
+
* @throws {Error} If the channel is not a text-based channel or does not exist.
|
|
87
|
+
* @throws {Error} If there is an error sending the message.
|
|
88
|
+
*/
|
|
89
|
+
sendMessageToChannel(channel: TextChannel, messageContent: string, files: AttachmentBuilder[]): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Play an audio stream from a given response stream using the provided VoiceConnection.
|
|
92
|
+
*
|
|
93
|
+
* @param responseStream - The response stream to play as audio.
|
|
94
|
+
* @param connection - The VoiceConnection to use for playing the audio.
|
|
95
|
+
* @returns A Promise that resolves when the TTS playback is finished.
|
|
96
|
+
*/
|
|
97
|
+
playAudioStream(responseStream: ReadableStream | NodeJS.ReadableStream | Readable, connection: VoiceConnection): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Retrieves the active guild where the bot is currently connected to a voice channel.
|
|
100
|
+
*
|
|
101
|
+
* @param {DiscordService} discordClient The DiscordService instance used to interact with the Discord API.
|
|
102
|
+
* @returns {Promise<Guild>} The active guild where the bot is currently connected to a voice channel.
|
|
103
|
+
* @throws {Error} If no active voice connection is found for the bot.
|
|
104
|
+
*/
|
|
105
|
+
getActiveGuild(discordClient: DiscordService): Promise<Guild>;
|
|
106
|
+
/**
|
|
107
|
+
* Waits for the VoiceManager in the Discord client to be ready.
|
|
108
|
+
*
|
|
109
|
+
* @param {DiscordService} discordClient - The Discord client to check for VoiceManager readiness.
|
|
110
|
+
* @throws {Error} If the Discord client is not initialized.
|
|
111
|
+
* @returns {Promise<void>} A promise that resolves when the VoiceManager is ready.
|
|
112
|
+
*/
|
|
113
|
+
private waitForVoiceManagerReady;
|
|
114
|
+
/**
|
|
115
|
+
* Validates the Discord test channel ID by checking if it is set in the runtime or environment variables.
|
|
116
|
+
* If the test channel ID is not set, an error is thrown.
|
|
117
|
+
*
|
|
118
|
+
* @param {IAgentRuntime} runtime The runtime object containing the settings and environment variables.
|
|
119
|
+
* @returns {string} The validated Discord test channel ID.
|
|
120
|
+
*/
|
|
121
|
+
private validateChannelId;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests.d.ts","sourceRoot":"","sources":["../tests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAMN,KAAK,eAAe,EAEpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,KAAK,aAAa,EAGlB,KAAK,SAAS,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,iBAAiB,EAGjB,KAAK,KAAK,EAEV,KAAK,WAAW,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAOhD;;;;;;;GAOG;AACH,qBAAa,gBAAiB,YAAW,SAAS;IACjD,IAAI,SAAa;IACjB,OAAO,CAAC,aAAa,CAAkB;IACvC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,EAAE,CAAC;IAEzE;;;;;OAKG;;IA8BH;;;;;;OAMG;IACG,yBAAyB,CAAC,OAAO,EAAE,aAAa;IAgCtD;;;;;;OAMG;IACG,yBAAyB,CAAC,OAAO,EAAE,aAAa;IAkDtD;;;;;OAKG;IACG,0BAA0B,CAAC,OAAO,EAAE,aAAa;IAqCvD;;;;OAIG;IACG,wBAAwB,CAAC,OAAO,EAAE,aAAa;IA0DrD;;;;;;OAMG;IACG,sBAAsB,CAAC,OAAO,EAAE,aAAa;IAoBnD;;;;;OAKG;IACG,mBAAmB,CAAC,OAAO,EAAE,aAAa;IA2DhD;;;;;;OAMG;IACG,cAAc,CAAC,OAAO,EAAE,aAAa;IAgB3C;;;;;;;;OAQG;IACG,oBAAoB,CACzB,OAAO,EAAE,WAAW,EACpB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,iBAAiB,EAAE;IAqB3B;;;;;;OAMG;IACG,eAAe,CACpB,cAAc,EAAE,cAAc,GAAG,MAAM,CAAC,cAAc,GAAG,QAAQ,EACjE,UAAU,EAAE,eAAe;IA4B5B;;;;;;OAMG;IACG,cAAc,CAAC,aAAa,EAAE,cAAc;IAiBlD;;;;;;OAMG;YACW,wBAAwB;IAqBtC;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAWzB"}
|