@elizaos/plugin-discord 1.0.0-beta.4 → 1.0.0-beta.40
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/LICENSE +1 -1
- package/dist/index.js +112 -63
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Shaw Walters
|
|
3
|
+
Copyright (c) 2025 Shaw Walters and elizaOS Contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/dist/index.js
CHANGED
|
@@ -134,7 +134,14 @@ var chatWithAttachments = {
|
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
136
136
|
const { objective, attachmentIds } = attachmentData;
|
|
137
|
-
const
|
|
137
|
+
const conversationLength = runtime.getConversationLength();
|
|
138
|
+
const recentMessages = await runtime.getMemories({
|
|
139
|
+
tableName: "messages",
|
|
140
|
+
roomId: message.roomId,
|
|
141
|
+
count: conversationLength,
|
|
142
|
+
unique: false
|
|
143
|
+
});
|
|
144
|
+
const attachments = recentMessages.filter((msg) => msg.content.attachments && msg.content.attachments.length > 0).flatMap((msg) => msg.content.attachments).filter(
|
|
138
145
|
(attachment) => attachmentIds.map((attch) => attch.toLowerCase().slice(0, 5)).includes(attachment.id.toLowerCase().slice(0, 5)) || // or check the other way
|
|
139
146
|
attachmentIds.some((id) => {
|
|
140
147
|
const attachmentId = id.toLowerCase().slice(0, 5);
|
|
@@ -850,7 +857,14 @@ var transcribeMedia = {
|
|
|
850
857
|
);
|
|
851
858
|
return;
|
|
852
859
|
}
|
|
853
|
-
const
|
|
860
|
+
const conversationLength = runtime.getConversationLength();
|
|
861
|
+
const recentMessages = await runtime.getMemories({
|
|
862
|
+
tableName: "messages",
|
|
863
|
+
roomId: message.roomId,
|
|
864
|
+
count: conversationLength,
|
|
865
|
+
unique: false
|
|
866
|
+
});
|
|
867
|
+
const attachment = recentMessages.filter((msg) => msg.content.attachments && msg.content.attachments.length > 0).flatMap((msg) => msg.content.attachments).find((attachment2) => attachment2.id.toLowerCase() === attachmentId.toLowerCase());
|
|
854
868
|
if (!attachment) {
|
|
855
869
|
console.error(`Couldn't find attachment with ID ${attachmentId}`);
|
|
856
870
|
await runtime.createMemory(
|
|
@@ -962,7 +976,7 @@ var joinVoice = {
|
|
|
962
976
|
return false;
|
|
963
977
|
}
|
|
964
978
|
const room = state.data.room ?? await runtime.getRoom(message.roomId);
|
|
965
|
-
if (room?.type !== ChannelType2.GROUP) {
|
|
979
|
+
if (room?.type !== ChannelType2.GROUP && room?.type !== ChannelType2.VOICE_GROUP) {
|
|
966
980
|
return false;
|
|
967
981
|
}
|
|
968
982
|
const client = runtime.getService(ServiceType2.DISCORD);
|
|
@@ -978,7 +992,7 @@ var joinVoice = {
|
|
|
978
992
|
if (!room) {
|
|
979
993
|
throw new Error("No room found");
|
|
980
994
|
}
|
|
981
|
-
if (room.type !== ChannelType2.
|
|
995
|
+
if (room?.type !== ChannelType2.GROUP && room?.type !== ChannelType2.VOICE_GROUP) {
|
|
982
996
|
return false;
|
|
983
997
|
}
|
|
984
998
|
const serverId = room.serverId;
|
|
@@ -1269,7 +1283,7 @@ var leaveVoice = {
|
|
|
1269
1283
|
return false;
|
|
1270
1284
|
}
|
|
1271
1285
|
const room = state.data.room ?? await runtime.getRoom(message.roomId);
|
|
1272
|
-
if (room?.type !== ChannelType3.GROUP) {
|
|
1286
|
+
if (room?.type !== ChannelType3.GROUP && room?.type !== ChannelType3.VOICE_GROUP) {
|
|
1273
1287
|
return false;
|
|
1274
1288
|
}
|
|
1275
1289
|
const isConnectedToVoice = service.client.voice.adapters.size > 0;
|
|
@@ -1281,7 +1295,7 @@ var leaveVoice = {
|
|
|
1281
1295
|
if (!room) {
|
|
1282
1296
|
throw new Error("No room found");
|
|
1283
1297
|
}
|
|
1284
|
-
if (room.type !== ChannelType3.
|
|
1298
|
+
if (room?.type !== ChannelType3.GROUP && room?.type !== ChannelType3.VOICE_GROUP) {
|
|
1285
1299
|
throw new Error("Not a group");
|
|
1286
1300
|
}
|
|
1287
1301
|
const serverId = room.serverId;
|
|
@@ -2062,23 +2076,6 @@ import {
|
|
|
2062
2076
|
PermissionsBitField,
|
|
2063
2077
|
ThreadChannel
|
|
2064
2078
|
} from "discord.js";
|
|
2065
|
-
function getWavHeader(audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
|
|
2066
|
-
const wavHeader = Buffer.alloc(44);
|
|
2067
|
-
wavHeader.write("RIFF", 0);
|
|
2068
|
-
wavHeader.writeUInt32LE(36 + audioLength, 4);
|
|
2069
|
-
wavHeader.write("WAVE", 8);
|
|
2070
|
-
wavHeader.write("fmt ", 12);
|
|
2071
|
-
wavHeader.writeUInt32LE(16, 16);
|
|
2072
|
-
wavHeader.writeUInt16LE(1, 20);
|
|
2073
|
-
wavHeader.writeUInt16LE(channelCount, 22);
|
|
2074
|
-
wavHeader.writeUInt32LE(sampleRate, 24);
|
|
2075
|
-
wavHeader.writeUInt32LE(sampleRate * bitsPerSample * channelCount / 8, 28);
|
|
2076
|
-
wavHeader.writeUInt16LE(bitsPerSample * channelCount / 8, 32);
|
|
2077
|
-
wavHeader.writeUInt16LE(bitsPerSample, 34);
|
|
2078
|
-
wavHeader.write("data", 36);
|
|
2079
|
-
wavHeader.writeUInt32LE(audioLength, 40);
|
|
2080
|
-
return wavHeader;
|
|
2081
|
-
}
|
|
2082
2079
|
var MAX_MESSAGE_LENGTH = 1900;
|
|
2083
2080
|
async function sendMessageInChunks(channel, content, _inReplyTo, files) {
|
|
2084
2081
|
const sentMessages = [];
|
|
@@ -2207,6 +2204,9 @@ var MessageManager = class {
|
|
|
2207
2204
|
if (this.runtime.character.settings?.discord?.shouldIgnoreDirectMessages && message.channel.type === DiscordChannelType2.DM) {
|
|
2208
2205
|
return;
|
|
2209
2206
|
}
|
|
2207
|
+
if (this.runtime.character.settings?.discord?.shouldRespondOnlyToMentions && !message.mentions.users?.has(this.client.user?.id)) {
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
2210
|
const entityId = createUniqueUuid4(this.runtime, message.author.id);
|
|
2211
2211
|
const userName = message.author.bot ? `${message.author.username}#${message.author.discriminator}` : message.author.username;
|
|
2212
2212
|
const name = message.author.displayName;
|
|
@@ -2217,6 +2217,9 @@ var MessageManager = class {
|
|
|
2217
2217
|
if (message.guild) {
|
|
2218
2218
|
const guild = await message.guild.fetch();
|
|
2219
2219
|
type = await this.getChannelType(message.channel);
|
|
2220
|
+
if (type === null) {
|
|
2221
|
+
logger4.warn("null channel type, discord message", message);
|
|
2222
|
+
}
|
|
2220
2223
|
serverId = guild.id;
|
|
2221
2224
|
} else {
|
|
2222
2225
|
type = ChannelType7.DM;
|
|
@@ -2250,6 +2253,20 @@ var MessageManager = class {
|
|
|
2250
2253
|
}
|
|
2251
2254
|
const entityId2 = createUniqueUuid4(this.runtime, message.author.id);
|
|
2252
2255
|
const messageId = createUniqueUuid4(this.runtime, message.id);
|
|
2256
|
+
const channel = message.channel;
|
|
2257
|
+
const startTyping = () => {
|
|
2258
|
+
try {
|
|
2259
|
+
channel.sendTyping();
|
|
2260
|
+
} catch (err) {
|
|
2261
|
+
logger4.warn("Error sending typing indicator:", err);
|
|
2262
|
+
}
|
|
2263
|
+
};
|
|
2264
|
+
startTyping();
|
|
2265
|
+
const typingInterval = setInterval(startTyping, 8e3);
|
|
2266
|
+
const typingData = {
|
|
2267
|
+
interval: typingInterval,
|
|
2268
|
+
cleared: false
|
|
2269
|
+
};
|
|
2253
2270
|
const newMessage = {
|
|
2254
2271
|
id: messageId,
|
|
2255
2272
|
entityId: entityId2,
|
|
@@ -2264,6 +2281,10 @@ var MessageManager = class {
|
|
|
2264
2281
|
url: message.url,
|
|
2265
2282
|
inReplyTo: message.reference?.messageId ? createUniqueUuid4(this.runtime, message.reference?.messageId) : void 0
|
|
2266
2283
|
},
|
|
2284
|
+
metadata: {
|
|
2285
|
+
entityName: name,
|
|
2286
|
+
type: "message"
|
|
2287
|
+
},
|
|
2267
2288
|
createdAt: message.createdTimestamp
|
|
2268
2289
|
};
|
|
2269
2290
|
const callback = async (content, files) => {
|
|
@@ -2271,38 +2292,49 @@ var MessageManager = class {
|
|
|
2271
2292
|
if (message.id && !content.inReplyTo) {
|
|
2272
2293
|
content.inReplyTo = createUniqueUuid4(this.runtime, message.id);
|
|
2273
2294
|
}
|
|
2274
|
-
|
|
2275
|
-
message.
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2295
|
+
try {
|
|
2296
|
+
const messages = await sendMessageInChunks(channel, content.text, message.id, files);
|
|
2297
|
+
const memories = [];
|
|
2298
|
+
for (const m of messages) {
|
|
2299
|
+
const actions = content.actions;
|
|
2300
|
+
const memory = {
|
|
2301
|
+
id: createUniqueUuid4(this.runtime, m.id),
|
|
2302
|
+
entityId: this.runtime.agentId,
|
|
2303
|
+
agentId: this.runtime.agentId,
|
|
2304
|
+
content: {
|
|
2305
|
+
...content,
|
|
2306
|
+
actions,
|
|
2307
|
+
inReplyTo: messageId,
|
|
2308
|
+
url: m.url,
|
|
2309
|
+
channelType: type
|
|
2310
|
+
},
|
|
2311
|
+
roomId,
|
|
2312
|
+
createdAt: m.createdTimestamp
|
|
2313
|
+
};
|
|
2314
|
+
memories.push(memory);
|
|
2315
|
+
}
|
|
2316
|
+
for (const m of memories) {
|
|
2317
|
+
await this.runtime.createMemory(m, "messages");
|
|
2318
|
+
}
|
|
2319
|
+
if (typingData.interval && !typingData.cleared) {
|
|
2320
|
+
clearInterval(typingData.interval);
|
|
2321
|
+
typingData.cleared = true;
|
|
2322
|
+
}
|
|
2323
|
+
return memories;
|
|
2324
|
+
} catch (error) {
|
|
2325
|
+
console.error("Error sending message:", error);
|
|
2326
|
+
if (typingData.interval && !typingData.cleared) {
|
|
2327
|
+
clearInterval(typingData.interval);
|
|
2328
|
+
typingData.cleared = true;
|
|
2329
|
+
}
|
|
2330
|
+
return [];
|
|
2301
2331
|
}
|
|
2302
|
-
return memories;
|
|
2303
2332
|
} catch (error) {
|
|
2304
|
-
console.error("Error
|
|
2305
|
-
|
|
2333
|
+
console.error("Error handling message:", error);
|
|
2334
|
+
if (typingData.interval && !typingData.cleared) {
|
|
2335
|
+
clearInterval(typingData.interval);
|
|
2336
|
+
typingData.cleared = true;
|
|
2337
|
+
}
|
|
2306
2338
|
}
|
|
2307
2339
|
};
|
|
2308
2340
|
this.runtime.emitEvent(["DISCORD_MESSAGE_RECEIVED" /* MESSAGE_RECEIVED */, EventType.MESSAGE_RECEIVED], {
|
|
@@ -2310,6 +2342,12 @@ var MessageManager = class {
|
|
|
2310
2342
|
message: newMessage,
|
|
2311
2343
|
callback
|
|
2312
2344
|
});
|
|
2345
|
+
setTimeout(() => {
|
|
2346
|
+
if (typingData.interval && !typingData.cleared) {
|
|
2347
|
+
clearInterval(typingData.interval);
|
|
2348
|
+
typingData.cleared = true;
|
|
2349
|
+
}
|
|
2350
|
+
}, 500);
|
|
2313
2351
|
} catch (error) {
|
|
2314
2352
|
console.error("Error handling message:", error);
|
|
2315
2353
|
}
|
|
@@ -2359,7 +2397,8 @@ var MessageManager = class {
|
|
|
2359
2397
|
if (this.runtime.getService(ServiceType4.VIDEO)?.isVideoUrl(url)) {
|
|
2360
2398
|
const videoService = this.runtime.getService(ServiceType4.VIDEO);
|
|
2361
2399
|
if (!videoService) {
|
|
2362
|
-
|
|
2400
|
+
logger4.warn("Video service not found");
|
|
2401
|
+
continue;
|
|
2363
2402
|
}
|
|
2364
2403
|
const videoInfo = await videoService.processVideo(url, this.runtime);
|
|
2365
2404
|
attachments.push({
|
|
@@ -2373,7 +2412,8 @@ var MessageManager = class {
|
|
|
2373
2412
|
} else {
|
|
2374
2413
|
const browserService = this.runtime.getService(ServiceType4.BROWSER);
|
|
2375
2414
|
if (!browserService) {
|
|
2376
|
-
|
|
2415
|
+
logger4.warn("Browser service not found");
|
|
2416
|
+
continue;
|
|
2377
2417
|
}
|
|
2378
2418
|
const { title, description: summary } = await browserService.getPageContent(
|
|
2379
2419
|
url,
|
|
@@ -2432,6 +2472,7 @@ import {
|
|
|
2432
2472
|
ChannelType as ChannelType8,
|
|
2433
2473
|
ModelType as ModelType8,
|
|
2434
2474
|
createUniqueUuid as createUniqueUuid5,
|
|
2475
|
+
getWavHeader,
|
|
2435
2476
|
logger as logger5
|
|
2436
2477
|
} from "@elizaos/core";
|
|
2437
2478
|
import {
|
|
@@ -2872,8 +2913,7 @@ var VoiceManager = class extends EventEmitter {
|
|
|
2872
2913
|
* @param {BaseGuildVoiceChannel} channel - The voice channel the user is in.
|
|
2873
2914
|
* @param {Readable} audioStream - The audio stream to monitor.
|
|
2874
2915
|
*/
|
|
2875
|
-
async handleUserStream(
|
|
2876
|
-
const entityId = createUniqueUuid5(this.runtime, userId);
|
|
2916
|
+
async handleUserStream(entityId, name, userName, channel, audioStream) {
|
|
2877
2917
|
logger5.debug(`Starting audio monitor for user: ${entityId}`);
|
|
2878
2918
|
if (!this.userStates.has(entityId)) {
|
|
2879
2919
|
this.userStates.set(entityId, {
|
|
@@ -2965,9 +3005,10 @@ var VoiceManager = class extends EventEmitter {
|
|
|
2965
3005
|
return { text: "", actions: ["IGNORE"] };
|
|
2966
3006
|
}
|
|
2967
3007
|
const roomId = createUniqueUuid5(this.runtime, channelId);
|
|
3008
|
+
const uniqueEntityId = createUniqueUuid5(this.runtime, entityId);
|
|
2968
3009
|
const type = await this.getChannelType(channel);
|
|
2969
3010
|
await this.runtime.ensureConnection({
|
|
2970
|
-
entityId,
|
|
3011
|
+
entityId: uniqueEntityId,
|
|
2971
3012
|
roomId,
|
|
2972
3013
|
userName,
|
|
2973
3014
|
name,
|
|
@@ -2979,7 +3020,7 @@ var VoiceManager = class extends EventEmitter {
|
|
|
2979
3020
|
const memory = {
|
|
2980
3021
|
id: createUniqueUuid5(this.runtime, `${channelId}-voice-message-${Date.now()}`),
|
|
2981
3022
|
agentId: this.runtime.agentId,
|
|
2982
|
-
entityId,
|
|
3023
|
+
entityId: uniqueEntityId,
|
|
2983
3024
|
roomId,
|
|
2984
3025
|
content: {
|
|
2985
3026
|
text: message,
|
|
@@ -3009,7 +3050,7 @@ var VoiceManager = class extends EventEmitter {
|
|
|
3009
3050
|
createdAt: Date.now()
|
|
3010
3051
|
};
|
|
3011
3052
|
if (responseMemory.content.text?.trim()) {
|
|
3012
|
-
await this.runtime.createMemory(responseMemory);
|
|
3053
|
+
await this.runtime.createMemory(responseMemory, "messages");
|
|
3013
3054
|
const responseStream = await this.runtime.useModel(
|
|
3014
3055
|
ModelType8.TEXT_TO_SPEECH,
|
|
3015
3056
|
content.text
|
|
@@ -3301,6 +3342,11 @@ var DiscordService = class _DiscordService extends Service {
|
|
|
3301
3342
|
logger6.error(`Error handling interaction: ${error}`);
|
|
3302
3343
|
}
|
|
3303
3344
|
});
|
|
3345
|
+
this.client.on("userStream", (entityId, name, userName, channel, opusDecoder) => {
|
|
3346
|
+
if (entityId !== this.client?.user?.id) {
|
|
3347
|
+
this.voiceManager.handleUserStream(entityId, name, userName, channel, opusDecoder);
|
|
3348
|
+
}
|
|
3349
|
+
});
|
|
3304
3350
|
}
|
|
3305
3351
|
/**
|
|
3306
3352
|
* Handles the event when a new member joins a guild.
|
|
@@ -3312,10 +3358,12 @@ var DiscordService = class _DiscordService extends Service {
|
|
|
3312
3358
|
logger6.log(`New member joined: ${member.user.username}`);
|
|
3313
3359
|
const guild = member.guild;
|
|
3314
3360
|
const tag = member.user.bot ? `${member.user.username}#${member.user.discriminator}` : member.user.username;
|
|
3361
|
+
const worldId = createUniqueUuid6(this.runtime, guild.id);
|
|
3362
|
+
const entityId = createUniqueUuid6(this.runtime, member.id);
|
|
3315
3363
|
this.runtime.emitEvent([EventType2.ENTITY_JOINED], {
|
|
3316
3364
|
runtime: this.runtime,
|
|
3317
|
-
entityId
|
|
3318
|
-
worldId
|
|
3365
|
+
entityId,
|
|
3366
|
+
worldId,
|
|
3319
3367
|
source: "discord",
|
|
3320
3368
|
metadata: {
|
|
3321
3369
|
originalId: member.id,
|
|
@@ -3327,7 +3375,8 @@ var DiscordService = class _DiscordService extends Service {
|
|
|
3327
3375
|
});
|
|
3328
3376
|
this.runtime.emitEvent(["DISCORD_USER_JOINED" /* ENTITY_JOINED */], {
|
|
3329
3377
|
runtime: this.runtime,
|
|
3330
|
-
entityId
|
|
3378
|
+
entityId,
|
|
3379
|
+
worldId,
|
|
3331
3380
|
member,
|
|
3332
3381
|
guild
|
|
3333
3382
|
});
|