@elizaos/plugin-memory 1.1.1 → 2.0.0-alpha

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.
Files changed (44) hide show
  1. package/dist/evaluators/index.d.ts +3 -0
  2. package/dist/evaluators/index.d.ts.map +1 -0
  3. package/dist/evaluators/long-term-extraction.d.ts +1 -6
  4. package/dist/evaluators/long-term-extraction.d.ts.map +1 -0
  5. package/dist/evaluators/summarization.d.ts +1 -28
  6. package/dist/evaluators/summarization.d.ts.map +1 -0
  7. package/dist/generated/prompts/typescript/prompts.d.ts +16 -0
  8. package/dist/generated/prompts/typescript/prompts.d.ts.map +1 -0
  9. package/dist/index.d.ts +7 -39
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/{node/index.node.js → index.js} +800 -981
  12. package/dist/index.js.map +20 -0
  13. package/dist/providers/context-summary.d.ts +2 -11
  14. package/dist/providers/context-summary.d.ts.map +1 -0
  15. package/dist/providers/index.d.ts +3 -0
  16. package/dist/providers/index.d.ts.map +1 -0
  17. package/dist/providers/long-term-memory.d.ts +2 -16
  18. package/dist/providers/long-term-memory.d.ts.map +1 -0
  19. package/dist/schemas/index.d.ts +4 -9
  20. package/dist/schemas/index.d.ts.map +1 -0
  21. package/dist/schemas/long-term-memories.d.ts +1 -4
  22. package/dist/schemas/long-term-memories.d.ts.map +1 -0
  23. package/dist/schemas/memory-access-logs.d.ts +20 -58
  24. package/dist/schemas/memory-access-logs.d.ts.map +1 -0
  25. package/dist/schemas/session-summaries.d.ts +1 -4
  26. package/dist/schemas/session-summaries.d.ts.map +1 -0
  27. package/dist/services/memory-service.d.ts +7 -75
  28. package/dist/services/memory-service.d.ts.map +1 -0
  29. package/dist/types/index.d.ts +5 -26
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/package.json +45 -48
  32. package/README.md +0 -335
  33. package/dist/actions/remember.d.ts +0 -11
  34. package/dist/browser/index.browser.js +0 -209
  35. package/dist/browser/index.browser.js.map +0 -20
  36. package/dist/browser/index.d.ts +0 -2
  37. package/dist/cjs/index.d.ts +0 -2
  38. package/dist/cjs/index.node.cjs +0 -1293
  39. package/dist/cjs/index.node.js.map +0 -20
  40. package/dist/index.browser.d.ts +0 -2
  41. package/dist/index.node.d.ts +0 -2
  42. package/dist/node/index.d.ts +0 -2
  43. package/dist/node/index.node.js.map +0 -20
  44. package/dist/providers/recent-messages.d.ts +0 -15
@@ -1,1293 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __moduleCache = /* @__PURE__ */ new WeakMap;
6
- var __toCommonJS = (from) => {
7
- var entry = __moduleCache.get(from), desc;
8
- if (entry)
9
- return entry;
10
- entry = __defProp({}, "__esModule", { value: true });
11
- if (from && typeof from === "object" || typeof from === "function")
12
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
- get: () => from[key],
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- }));
16
- __moduleCache.set(from, entry);
17
- return entry;
18
- };
19
- var __export = (target, all) => {
20
- for (var name in all)
21
- __defProp(target, name, {
22
- get: all[name],
23
- enumerable: true,
24
- configurable: true,
25
- set: (newValue) => all[name] = () => newValue
26
- });
27
- };
28
-
29
- // src/index.node.ts
30
- var exports_index_node = {};
31
- __export(exports_index_node, {
32
- sessionSummaries: () => sessionSummaries,
33
- recentMessagesProvider: () => recentMessagesProvider,
34
- memoryPlugin: () => memoryPlugin,
35
- memoryAccessLogs: () => memoryAccessLogs,
36
- longTermMemoryProvider: () => longTermMemoryProvider,
37
- longTermMemories: () => longTermMemories,
38
- default: () => src_default,
39
- contextSummaryProvider: () => contextSummaryProvider,
40
- MemoryService: () => MemoryService,
41
- LongTermMemoryCategory: () => LongTermMemoryCategory
42
- });
43
- module.exports = __toCommonJS(exports_index_node);
44
-
45
- // src/services/memory-service.ts
46
- var import_core = require("@elizaos/core");
47
- var import_drizzle_orm4 = require("drizzle-orm");
48
-
49
- // src/schemas/index.ts
50
- var exports_schemas = {};
51
- __export(exports_schemas, {
52
- sessionSummaries: () => sessionSummaries,
53
- memoryAccessLogs: () => memoryAccessLogs,
54
- longTermMemories: () => longTermMemories
55
- });
56
-
57
- // src/schemas/long-term-memories.ts
58
- var import_drizzle_orm = require("drizzle-orm");
59
- var import_pg_core = require("drizzle-orm/pg-core");
60
- var longTermMemories = import_pg_core.pgTable("long_term_memories", {
61
- id: import_pg_core.varchar("id", { length: 36 }).primaryKey(),
62
- agentId: import_pg_core.varchar("agent_id", { length: 36 }).notNull(),
63
- entityId: import_pg_core.varchar("entity_id", { length: 36 }).notNull(),
64
- category: import_pg_core.text("category").notNull(),
65
- content: import_pg_core.text("content").notNull(),
66
- metadata: import_pg_core.jsonb("metadata"),
67
- embedding: import_pg_core.real("embedding").array(),
68
- confidence: import_pg_core.real("confidence").default(1),
69
- source: import_pg_core.text("source"),
70
- createdAt: import_pg_core.timestamp("created_at").default(import_drizzle_orm.sql`now()`).notNull(),
71
- updatedAt: import_pg_core.timestamp("updated_at").default(import_drizzle_orm.sql`now()`).notNull(),
72
- lastAccessedAt: import_pg_core.timestamp("last_accessed_at"),
73
- accessCount: import_pg_core.integer("access_count").default(0)
74
- }, (table) => ({
75
- agentEntityIdx: import_pg_core.index("long_term_memories_agent_entity_idx").on(table.agentId, table.entityId),
76
- categoryIdx: import_pg_core.index("long_term_memories_category_idx").on(table.category),
77
- confidenceIdx: import_pg_core.index("long_term_memories_confidence_idx").on(table.confidence),
78
- createdAtIdx: import_pg_core.index("long_term_memories_created_at_idx").on(table.createdAt)
79
- }));
80
- // src/schemas/session-summaries.ts
81
- var import_drizzle_orm2 = require("drizzle-orm");
82
- var import_pg_core2 = require("drizzle-orm/pg-core");
83
- var sessionSummaries = import_pg_core2.pgTable("session_summaries", {
84
- id: import_pg_core2.varchar("id", { length: 36 }).primaryKey(),
85
- agentId: import_pg_core2.varchar("agent_id", { length: 36 }).notNull(),
86
- roomId: import_pg_core2.varchar("room_id", { length: 36 }).notNull(),
87
- entityId: import_pg_core2.varchar("entity_id", { length: 36 }),
88
- summary: import_pg_core2.text("summary").notNull(),
89
- messageCount: import_pg_core2.integer("message_count").notNull(),
90
- lastMessageOffset: import_pg_core2.integer("last_message_offset").notNull().default(0),
91
- startTime: import_pg_core2.timestamp("start_time").notNull(),
92
- endTime: import_pg_core2.timestamp("end_time").notNull(),
93
- topics: import_pg_core2.jsonb("topics"),
94
- metadata: import_pg_core2.jsonb("metadata"),
95
- embedding: import_pg_core2.real("embedding").array(),
96
- createdAt: import_pg_core2.timestamp("created_at").default(import_drizzle_orm2.sql`now()`).notNull(),
97
- updatedAt: import_pg_core2.timestamp("updated_at").default(import_drizzle_orm2.sql`now()`).notNull()
98
- }, (table) => ({
99
- agentRoomIdx: import_pg_core2.index("session_summaries_agent_room_idx").on(table.agentId, table.roomId),
100
- entityIdx: import_pg_core2.index("session_summaries_entity_idx").on(table.entityId),
101
- startTimeIdx: import_pg_core2.index("session_summaries_start_time_idx").on(table.startTime)
102
- }));
103
- // src/schemas/memory-access-logs.ts
104
- var import_drizzle_orm3 = require("drizzle-orm");
105
- var import_pg_core3 = require("drizzle-orm/pg-core");
106
- var memoryAccessLogs = import_pg_core3.pgTable("memory_access_logs", {
107
- id: import_pg_core3.varchar("id", { length: 36 }).primaryKey(),
108
- agentId: import_pg_core3.varchar("agent_id", { length: 36 }).notNull(),
109
- memoryId: import_pg_core3.varchar("memory_id", { length: 36 }).notNull(),
110
- memoryType: import_pg_core3.text("memory_type").notNull(),
111
- accessedAt: import_pg_core3.timestamp("accessed_at").default(import_drizzle_orm3.sql`now()`).notNull(),
112
- roomId: import_pg_core3.varchar("room_id", { length: 36 }),
113
- relevanceScore: import_pg_core3.real("relevance_score"),
114
- wasUseful: import_pg_core3.integer("was_useful")
115
- }, (table) => ({
116
- memoryIdx: import_pg_core3.index("memory_access_logs_memory_idx").on(table.memoryId),
117
- agentIdx: import_pg_core3.index("memory_access_logs_agent_idx").on(table.agentId),
118
- accessedAtIdx: import_pg_core3.index("memory_access_logs_accessed_at_idx").on(table.accessedAt)
119
- }));
120
- // src/services/memory-service.ts
121
- class MemoryService extends import_core.Service {
122
- static serviceType = "memory";
123
- sessionMessageCounts;
124
- memoryConfig;
125
- lastExtractionCheckpoints;
126
- capabilityDescription = "Advanced memory management with short-term summarization and long-term persistent facts";
127
- constructor(runtime) {
128
- super(runtime);
129
- this.sessionMessageCounts = new Map;
130
- this.lastExtractionCheckpoints = new Map;
131
- this.memoryConfig = {
132
- shortTermSummarizationThreshold: 16,
133
- shortTermRetainRecent: 6,
134
- shortTermSummarizationInterval: 10,
135
- longTermExtractionEnabled: true,
136
- longTermVectorSearchEnabled: false,
137
- longTermConfidenceThreshold: 0.85,
138
- longTermExtractionThreshold: 30,
139
- longTermExtractionInterval: 10,
140
- summaryModelType: "TEXT_LARGE",
141
- summaryMaxTokens: 2500,
142
- summaryMaxNewMessages: 20
143
- };
144
- }
145
- static async start(runtime) {
146
- const service = new MemoryService(runtime);
147
- await service.initialize(runtime);
148
- return service;
149
- }
150
- async stop() {
151
- import_core.logger.info("MemoryService stopped");
152
- }
153
- async initialize(runtime) {
154
- this.runtime = runtime;
155
- const threshold = runtime.getSetting("MEMORY_SUMMARIZATION_THRESHOLD");
156
- if (threshold) {
157
- this.memoryConfig.shortTermSummarizationThreshold = parseInt(threshold, 10);
158
- }
159
- const retainRecent = runtime.getSetting("MEMORY_RETAIN_RECENT");
160
- if (retainRecent) {
161
- this.memoryConfig.shortTermRetainRecent = parseInt(retainRecent, 10);
162
- }
163
- const summarizationInterval = runtime.getSetting("MEMORY_SUMMARIZATION_INTERVAL");
164
- if (summarizationInterval) {
165
- this.memoryConfig.shortTermSummarizationInterval = parseInt(summarizationInterval, 10);
166
- }
167
- const maxNewMessages = runtime.getSetting("MEMORY_MAX_NEW_MESSAGES");
168
- if (maxNewMessages) {
169
- this.memoryConfig.summaryMaxNewMessages = parseInt(maxNewMessages, 10);
170
- }
171
- const longTermEnabled = runtime.getSetting("MEMORY_LONG_TERM_ENABLED");
172
- if (longTermEnabled === "false") {
173
- this.memoryConfig.longTermExtractionEnabled = false;
174
- } else if (longTermEnabled === "true") {
175
- this.memoryConfig.longTermExtractionEnabled = true;
176
- }
177
- const confidenceThreshold = runtime.getSetting("MEMORY_CONFIDENCE_THRESHOLD");
178
- if (confidenceThreshold) {
179
- this.memoryConfig.longTermConfidenceThreshold = parseFloat(confidenceThreshold);
180
- }
181
- const extractionThreshold = runtime.getSetting("MEMORY_EXTRACTION_THRESHOLD");
182
- if (extractionThreshold) {
183
- this.memoryConfig.longTermExtractionThreshold = parseInt(extractionThreshold, 10);
184
- }
185
- const extractionInterval = runtime.getSetting("MEMORY_EXTRACTION_INTERVAL");
186
- if (extractionInterval) {
187
- this.memoryConfig.longTermExtractionInterval = parseInt(extractionInterval, 10);
188
- }
189
- import_core.logger.debug({
190
- summarizationThreshold: this.memoryConfig.shortTermSummarizationThreshold,
191
- summarizationInterval: this.memoryConfig.shortTermSummarizationInterval,
192
- maxNewMessages: this.memoryConfig.summaryMaxNewMessages,
193
- retainRecent: this.memoryConfig.shortTermRetainRecent,
194
- longTermEnabled: this.memoryConfig.longTermExtractionEnabled,
195
- extractionThreshold: this.memoryConfig.longTermExtractionThreshold,
196
- extractionInterval: this.memoryConfig.longTermExtractionInterval,
197
- confidenceThreshold: this.memoryConfig.longTermConfidenceThreshold
198
- }, "MemoryService initialized");
199
- }
200
- getDb() {
201
- const db = this.runtime.db;
202
- if (!db) {
203
- throw new Error("Database not available");
204
- }
205
- return db;
206
- }
207
- getConfig() {
208
- return { ...this.memoryConfig };
209
- }
210
- updateConfig(updates) {
211
- this.memoryConfig = { ...this.memoryConfig, ...updates };
212
- }
213
- incrementMessageCount(roomId) {
214
- const current = this.sessionMessageCounts.get(roomId) || 0;
215
- const newCount = current + 1;
216
- this.sessionMessageCounts.set(roomId, newCount);
217
- return newCount;
218
- }
219
- resetMessageCount(roomId) {
220
- this.sessionMessageCounts.set(roomId, 0);
221
- }
222
- async shouldSummarize(roomId) {
223
- const count = await this.runtime.countMemories(roomId, false, "messages");
224
- return count >= this.memoryConfig.shortTermSummarizationThreshold;
225
- }
226
- getExtractionKey(entityId, roomId) {
227
- return `memory:extraction:${entityId}:${roomId}`;
228
- }
229
- async getLastExtractionCheckpoint(entityId, roomId) {
230
- const key = this.getExtractionKey(entityId, roomId);
231
- const cached = this.lastExtractionCheckpoints.get(key);
232
- if (cached !== undefined) {
233
- return cached;
234
- }
235
- try {
236
- const checkpoint = await this.runtime.getCache(key);
237
- const messageCount = checkpoint ?? 0;
238
- this.lastExtractionCheckpoints.set(key, messageCount);
239
- return messageCount;
240
- } catch (error) {
241
- import_core.logger.warn({ error }, "Failed to get extraction checkpoint from cache");
242
- return 0;
243
- }
244
- }
245
- async setLastExtractionCheckpoint(entityId, roomId, messageCount) {
246
- const key = this.getExtractionKey(entityId, roomId);
247
- this.lastExtractionCheckpoints.set(key, messageCount);
248
- try {
249
- await this.runtime.setCache(key, messageCount);
250
- import_core.logger.debug(`Set extraction checkpoint for ${entityId} in room ${roomId} at message count ${messageCount}`);
251
- } catch (error) {
252
- import_core.logger.error({ error }, "Failed to persist extraction checkpoint to cache");
253
- }
254
- }
255
- async shouldRunExtraction(entityId, roomId, currentMessageCount) {
256
- const threshold = this.memoryConfig.longTermExtractionThreshold;
257
- const interval = this.memoryConfig.longTermExtractionInterval;
258
- if (currentMessageCount < threshold) {
259
- return false;
260
- }
261
- const lastCheckpoint = await this.getLastExtractionCheckpoint(entityId, roomId);
262
- const currentCheckpoint = Math.floor(currentMessageCount / interval) * interval;
263
- const shouldRun = currentMessageCount >= threshold && currentCheckpoint > lastCheckpoint;
264
- import_core.logger.debug({
265
- entityId,
266
- roomId,
267
- currentMessageCount,
268
- threshold,
269
- interval,
270
- lastCheckpoint,
271
- currentCheckpoint,
272
- shouldRun
273
- }, "Extraction check");
274
- return shouldRun;
275
- }
276
- async storeLongTermMemory(memory) {
277
- const db = this.getDb();
278
- const id = crypto.randomUUID();
279
- const now = new Date;
280
- const newMemory = {
281
- id,
282
- createdAt: now,
283
- updatedAt: now,
284
- accessCount: 0,
285
- ...memory
286
- };
287
- try {
288
- await db.insert(longTermMemories).values({
289
- id: newMemory.id,
290
- agentId: newMemory.agentId,
291
- entityId: newMemory.entityId,
292
- category: newMemory.category,
293
- content: newMemory.content,
294
- metadata: newMemory.metadata || {},
295
- embedding: newMemory.embedding,
296
- confidence: newMemory.confidence,
297
- source: newMemory.source,
298
- accessCount: newMemory.accessCount,
299
- createdAt: now,
300
- updatedAt: now,
301
- lastAccessedAt: newMemory.lastAccessedAt
302
- });
303
- } catch (error) {
304
- import_core.logger.error({ error }, "Failed to store long-term memory");
305
- throw error;
306
- }
307
- import_core.logger.info(`Stored long-term memory: ${newMemory.category} for entity ${newMemory.entityId}`);
308
- return newMemory;
309
- }
310
- async getLongTermMemories(entityId, category, limit = 10) {
311
- const db = this.getDb();
312
- const conditions = [
313
- import_drizzle_orm4.eq(longTermMemories.agentId, this.runtime.agentId),
314
- import_drizzle_orm4.eq(longTermMemories.entityId, entityId)
315
- ];
316
- if (category) {
317
- conditions.push(import_drizzle_orm4.eq(longTermMemories.category, category));
318
- }
319
- const results = await db.select().from(longTermMemories).where(import_drizzle_orm4.and(...conditions)).orderBy(import_drizzle_orm4.desc(longTermMemories.confidence), import_drizzle_orm4.desc(longTermMemories.updatedAt)).limit(limit);
320
- return results.map((row) => ({
321
- id: row.id,
322
- agentId: row.agentId,
323
- entityId: row.entityId,
324
- category: row.category,
325
- content: row.content,
326
- metadata: row.metadata,
327
- embedding: row.embedding,
328
- confidence: row.confidence,
329
- source: row.source,
330
- createdAt: row.createdAt,
331
- updatedAt: row.updatedAt,
332
- lastAccessedAt: row.lastAccessedAt,
333
- accessCount: row.accessCount
334
- }));
335
- }
336
- async updateLongTermMemory(id, entityId, updates) {
337
- const db = this.getDb();
338
- const updateData = {
339
- updatedAt: new Date
340
- };
341
- if (updates.content !== undefined) {
342
- updateData.content = updates.content;
343
- }
344
- if (updates.metadata !== undefined) {
345
- updateData.metadata = updates.metadata;
346
- }
347
- if (updates.confidence !== undefined) {
348
- updateData.confidence = updates.confidence;
349
- }
350
- if (updates.embedding !== undefined) {
351
- updateData.embedding = updates.embedding;
352
- }
353
- if (updates.lastAccessedAt !== undefined) {
354
- updateData.lastAccessedAt = updates.lastAccessedAt;
355
- }
356
- if (updates.accessCount !== undefined) {
357
- updateData.accessCount = updates.accessCount;
358
- }
359
- await db.update(longTermMemories).set(updateData).where(import_drizzle_orm4.and(import_drizzle_orm4.eq(longTermMemories.id, id), import_drizzle_orm4.eq(longTermMemories.agentId, this.runtime.agentId), import_drizzle_orm4.eq(longTermMemories.entityId, entityId)));
360
- import_core.logger.info(`Updated long-term memory: ${id} for entity ${entityId}`);
361
- }
362
- async deleteLongTermMemory(id, entityId) {
363
- const db = this.getDb();
364
- await db.delete(longTermMemories).where(import_drizzle_orm4.and(import_drizzle_orm4.eq(longTermMemories.id, id), import_drizzle_orm4.eq(longTermMemories.agentId, this.runtime.agentId), import_drizzle_orm4.eq(longTermMemories.entityId, entityId)));
365
- import_core.logger.info(`Deleted long-term memory: ${id} for entity ${entityId}`);
366
- }
367
- async getCurrentSessionSummary(roomId) {
368
- const db = this.getDb();
369
- const results = await db.select().from(sessionSummaries).where(import_drizzle_orm4.and(import_drizzle_orm4.eq(sessionSummaries.agentId, this.runtime.agentId), import_drizzle_orm4.eq(sessionSummaries.roomId, roomId))).orderBy(import_drizzle_orm4.desc(sessionSummaries.updatedAt)).limit(1);
370
- if (results.length === 0) {
371
- return null;
372
- }
373
- const row = results[0];
374
- return {
375
- id: row.id,
376
- agentId: row.agentId,
377
- roomId: row.roomId,
378
- entityId: row.entityId,
379
- summary: row.summary,
380
- messageCount: row.messageCount,
381
- lastMessageOffset: row.lastMessageOffset,
382
- startTime: row.startTime,
383
- endTime: row.endTime,
384
- topics: row.topics || [],
385
- metadata: row.metadata,
386
- embedding: row.embedding,
387
- createdAt: row.createdAt,
388
- updatedAt: row.updatedAt
389
- };
390
- }
391
- async storeSessionSummary(summary) {
392
- const db = this.getDb();
393
- const id = crypto.randomUUID();
394
- const now = new Date;
395
- const newSummary = {
396
- id,
397
- createdAt: now,
398
- updatedAt: now,
399
- ...summary
400
- };
401
- await db.insert(sessionSummaries).values({
402
- id: newSummary.id,
403
- agentId: newSummary.agentId,
404
- roomId: newSummary.roomId,
405
- entityId: newSummary.entityId || null,
406
- summary: newSummary.summary,
407
- messageCount: newSummary.messageCount,
408
- lastMessageOffset: newSummary.lastMessageOffset,
409
- startTime: newSummary.startTime,
410
- endTime: newSummary.endTime,
411
- topics: newSummary.topics || [],
412
- metadata: newSummary.metadata || {},
413
- embedding: newSummary.embedding,
414
- createdAt: now,
415
- updatedAt: now
416
- });
417
- import_core.logger.info(`Stored session summary for room ${newSummary.roomId}`);
418
- return newSummary;
419
- }
420
- async updateSessionSummary(id, roomId, updates) {
421
- const db = this.getDb();
422
- const updateData = {
423
- updatedAt: new Date
424
- };
425
- if (updates.summary !== undefined) {
426
- updateData.summary = updates.summary;
427
- }
428
- if (updates.messageCount !== undefined) {
429
- updateData.messageCount = updates.messageCount;
430
- }
431
- if (updates.lastMessageOffset !== undefined) {
432
- updateData.lastMessageOffset = updates.lastMessageOffset;
433
- }
434
- if (updates.endTime !== undefined) {
435
- updateData.endTime = updates.endTime;
436
- }
437
- if (updates.topics !== undefined) {
438
- updateData.topics = updates.topics;
439
- }
440
- if (updates.metadata !== undefined) {
441
- updateData.metadata = updates.metadata;
442
- }
443
- if (updates.embedding !== undefined) {
444
- updateData.embedding = updates.embedding;
445
- }
446
- await db.update(sessionSummaries).set(updateData).where(import_drizzle_orm4.and(import_drizzle_orm4.eq(sessionSummaries.id, id), import_drizzle_orm4.eq(sessionSummaries.agentId, this.runtime.agentId), import_drizzle_orm4.eq(sessionSummaries.roomId, roomId)));
447
- import_core.logger.info(`Updated session summary: ${id} for room ${roomId}`);
448
- }
449
- async getSessionSummaries(roomId, limit = 5) {
450
- const db = this.getDb();
451
- const results = await db.select().from(sessionSummaries).where(import_drizzle_orm4.and(import_drizzle_orm4.eq(sessionSummaries.agentId, this.runtime.agentId), import_drizzle_orm4.eq(sessionSummaries.roomId, roomId))).orderBy(import_drizzle_orm4.desc(sessionSummaries.updatedAt)).limit(limit);
452
- return results.map((row) => ({
453
- id: row.id,
454
- agentId: row.agentId,
455
- roomId: row.roomId,
456
- entityId: row.entityId,
457
- summary: row.summary,
458
- messageCount: row.messageCount,
459
- lastMessageOffset: row.lastMessageOffset,
460
- startTime: row.startTime,
461
- endTime: row.endTime,
462
- topics: row.topics || [],
463
- metadata: row.metadata,
464
- embedding: row.embedding,
465
- createdAt: row.createdAt,
466
- updatedAt: row.updatedAt
467
- }));
468
- }
469
- async searchLongTermMemories(entityId, queryEmbedding, limit = 5, matchThreshold = 0.7) {
470
- if (!this.memoryConfig.longTermVectorSearchEnabled) {
471
- import_core.logger.warn("Vector search is not enabled, falling back to recent memories");
472
- return this.getLongTermMemories(entityId, undefined, limit);
473
- }
474
- const db = this.getDb();
475
- try {
476
- const cleanVector = queryEmbedding.map((n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0);
477
- const similarity = import_drizzle_orm4.sql`1 - (${import_drizzle_orm4.cosineDistance(longTermMemories.embedding, cleanVector)})`;
478
- const conditions = [
479
- import_drizzle_orm4.eq(longTermMemories.agentId, this.runtime.agentId),
480
- import_drizzle_orm4.eq(longTermMemories.entityId, entityId),
481
- import_drizzle_orm4.sql`${longTermMemories.embedding} IS NOT NULL`
482
- ];
483
- if (matchThreshold > 0) {
484
- conditions.push(import_drizzle_orm4.gte(similarity, matchThreshold));
485
- }
486
- const results = await db.select({
487
- memory: longTermMemories,
488
- similarity
489
- }).from(longTermMemories).where(import_drizzle_orm4.and(...conditions)).orderBy(import_drizzle_orm4.desc(similarity)).limit(limit);
490
- return results.map((row) => ({
491
- id: row.memory.id,
492
- agentId: row.memory.agentId,
493
- entityId: row.memory.entityId,
494
- category: row.memory.category,
495
- content: row.memory.content,
496
- metadata: row.memory.metadata,
497
- embedding: row.memory.embedding,
498
- confidence: row.memory.confidence,
499
- source: row.memory.source,
500
- createdAt: row.memory.createdAt,
501
- updatedAt: row.memory.updatedAt,
502
- lastAccessedAt: row.memory.lastAccessedAt,
503
- accessCount: row.memory.accessCount,
504
- similarity: row.similarity
505
- }));
506
- } catch (error) {
507
- import_core.logger.warn({ error }, "Vector search failed, falling back to recent memories");
508
- return this.getLongTermMemories(entityId, undefined, limit);
509
- }
510
- }
511
- async getFormattedLongTermMemories(entityId) {
512
- const memories = await this.getLongTermMemories(entityId, undefined, 20);
513
- if (memories.length === 0) {
514
- return "";
515
- }
516
- const grouped = new Map;
517
- for (const memory of memories) {
518
- if (!grouped.has(memory.category)) {
519
- grouped.set(memory.category, []);
520
- }
521
- grouped.get(memory.category)?.push(memory);
522
- }
523
- const sections = [];
524
- for (const [category, categoryMemories] of grouped.entries()) {
525
- const categoryName = category.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
526
- const items = categoryMemories.map((m) => `- ${m.content}`).join(`
527
- `);
528
- sections.push(`**${categoryName}**:
529
- ${items}`);
530
- }
531
- return sections.join(`
532
-
533
- `);
534
- }
535
- }
536
-
537
- // src/evaluators/summarization.ts
538
- var import_core2 = require("@elizaos/core");
539
- async function getDialogueMessageCount(runtime, roomId) {
540
- const messages = await runtime.getMemories({
541
- tableName: "messages",
542
- roomId,
543
- count: 100,
544
- unique: false
545
- });
546
- const dialogueMessages = messages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result") && (msg.metadata?.type === "agent_response_message" || msg.metadata?.type === "user_message"));
547
- return dialogueMessages.length;
548
- }
549
- var initialSummarizationTemplate = `# Task: Summarize Conversation
550
-
551
- You are analyzing a conversation to create a concise summary that captures the key points, topics, and important details.
552
-
553
- # Recent Messages
554
- {{recentMessages}}
555
-
556
- # Instructions
557
- Generate a summary that:
558
- 1. Captures the main topics discussed
559
- 2. Highlights key information shared
560
- 3. Notes any decisions made or questions asked
561
- 4. Maintains context for future reference
562
- 5. Is concise but comprehensive
563
-
564
- **IMPORTANT**: Keep the summary under 2500 tokens. Be comprehensive but concise.
565
-
566
- Also extract:
567
- - **Topics**: List of main topics discussed (comma-separated)
568
- - **Key Points**: Important facts or decisions (bullet points)
569
-
570
- Respond in this XML format:
571
- <summary>
572
- <text>Your comprehensive summary here</text>
573
- <topics>topic1, topic2, topic3</topics>
574
- <keyPoints>
575
- <point>First key point</point>
576
- <point>Second key point</point>
577
- </keyPoints>
578
- </summary>`;
579
- var updateSummarizationTemplate = `# Task: Update and Condense Conversation Summary
580
-
581
- You are updating an existing conversation summary with new messages, while keeping the total summary concise.
582
-
583
- # Existing Summary
584
- {{existingSummary}}
585
-
586
- # Existing Topics
587
- {{existingTopics}}
588
-
589
- # New Messages Since Last Summary
590
- {{newMessages}}
591
-
592
- # Instructions
593
- Update the summary by:
594
- 1. Merging the existing summary with insights from the new messages
595
- 2. Removing redundant or less important details to stay under the token limit
596
- 3. Keeping the most important context and decisions
597
- 4. Adding new topics if they emerge
598
- 5. **CRITICAL**: Keep the ENTIRE updated summary under 2500 tokens
599
-
600
- The goal is a rolling summary that captures the essence of the conversation without growing indefinitely.
601
-
602
- Respond in this XML format:
603
- <summary>
604
- <text>Your updated and condensed summary here</text>
605
- <topics>topic1, topic2, topic3</topics>
606
- <keyPoints>
607
- <point>First key point</point>
608
- <point>Second key point</point>
609
- </keyPoints>
610
- </summary>`;
611
- function parseSummaryXML(xml) {
612
- const summaryMatch = xml.match(/<text>([\s\S]*?)<\/text>/);
613
- const topicsMatch = xml.match(/<topics>([\s\S]*?)<\/topics>/);
614
- const keyPointsMatches = xml.matchAll(/<point>([\s\S]*?)<\/point>/g);
615
- const summary = summaryMatch ? summaryMatch[1].trim() : "Summary not available";
616
- const topics = topicsMatch ? topicsMatch[1].split(",").map((t) => t.trim()).filter(Boolean) : [];
617
- const keyPoints = Array.from(keyPointsMatches).map((match) => match[1].trim());
618
- return { summary, topics, keyPoints };
619
- }
620
- var summarizationEvaluator = {
621
- name: "MEMORY_SUMMARIZATION",
622
- description: "Automatically summarizes conversations to optimize context usage",
623
- similes: [
624
- "CONVERSATION_SUMMARY",
625
- "CONTEXT_COMPRESSION",
626
- "MEMORY_OPTIMIZATION"
627
- ],
628
- alwaysRun: true,
629
- validate: async (runtime, message) => {
630
- if (!message.content?.text) {
631
- return false;
632
- }
633
- const memoryService = runtime.getService("memory");
634
- if (!memoryService) {
635
- return false;
636
- }
637
- const config = memoryService.getConfig();
638
- const currentDialogueCount = await getDialogueMessageCount(runtime, message.roomId);
639
- const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);
640
- if (!existingSummary) {
641
- const shouldSummarize = currentDialogueCount >= config.shortTermSummarizationThreshold;
642
- return shouldSummarize;
643
- } else {
644
- const newDialogueCount = currentDialogueCount - existingSummary.lastMessageOffset;
645
- const shouldUpdate = newDialogueCount >= config.shortTermSummarizationInterval;
646
- return shouldUpdate;
647
- }
648
- },
649
- handler: async (runtime, message) => {
650
- const memoryService = runtime.getService("memory");
651
- if (!memoryService) {
652
- import_core2.logger.error("MemoryService not found");
653
- return;
654
- }
655
- const config = memoryService.getConfig();
656
- const { roomId } = message;
657
- try {
658
- import_core2.logger.info(`Starting summarization for room ${roomId}`);
659
- const existingSummary = await memoryService.getCurrentSessionSummary(roomId);
660
- const lastOffset = existingSummary?.lastMessageOffset || 0;
661
- const allMessages = await runtime.getMemories({
662
- tableName: "messages",
663
- roomId,
664
- count: 1000,
665
- unique: false
666
- });
667
- const allDialogueMessages = allMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result") && (msg.metadata?.type === "agent_response_message" || msg.metadata?.type === "user_message"));
668
- const totalDialogueCount = allDialogueMessages.length;
669
- const newDialogueCount = totalDialogueCount - lastOffset;
670
- if (newDialogueCount === 0) {
671
- import_core2.logger.debug("No new dialogue messages to summarize");
672
- return;
673
- }
674
- const maxNewMessages = config.summaryMaxNewMessages || 50;
675
- const messagesToProcess = Math.min(newDialogueCount, maxNewMessages);
676
- if (newDialogueCount > maxNewMessages) {
677
- import_core2.logger.warn(`Capping new dialogue messages at ${maxNewMessages} (${newDialogueCount} available). Oldest messages will be skipped.`);
678
- }
679
- const sortedDialogueMessages = allDialogueMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
680
- const newDialogueMessages = sortedDialogueMessages.slice(lastOffset, lastOffset + messagesToProcess);
681
- if (newDialogueMessages.length === 0) {
682
- import_core2.logger.debug("No new dialogue messages retrieved after filtering");
683
- return;
684
- }
685
- const formattedMessages = newDialogueMessages.map((msg) => {
686
- const sender = msg.entityId === runtime.agentId ? runtime.character.name : "User";
687
- return `${sender}: ${msg.content.text || "[non-text message]"}`;
688
- }).join(`
689
- `);
690
- const state = await runtime.composeState(message);
691
- let prompt;
692
- let template;
693
- if (existingSummary) {
694
- template = updateSummarizationTemplate;
695
- prompt = import_core2.composePromptFromState({
696
- state: {
697
- ...state,
698
- existingSummary: existingSummary.summary,
699
- existingTopics: existingSummary.topics?.join(", ") || "None",
700
- newMessages: formattedMessages
701
- },
702
- template
703
- });
704
- } else {
705
- const initialMessages = sortedDialogueMessages.map((msg) => {
706
- const sender = msg.entityId === runtime.agentId ? runtime.character.name : "User";
707
- return `${sender}: ${msg.content.text || "[non-text message]"}`;
708
- }).join(`
709
- `);
710
- template = initialSummarizationTemplate;
711
- prompt = import_core2.composePromptFromState({
712
- state: {
713
- ...state,
714
- recentMessages: initialMessages
715
- },
716
- template
717
- });
718
- }
719
- const response = await runtime.useModel(import_core2.ModelType.TEXT_LARGE, {
720
- prompt,
721
- maxTokens: config.summaryMaxTokens || 2500
722
- });
723
- const summaryResult = parseSummaryXML(response);
724
- import_core2.logger.info(`${existingSummary ? "Updated" : "Generated"} summary: ${summaryResult.summary.substring(0, 100)}...`);
725
- const newOffset = lastOffset + newDialogueMessages.length;
726
- const firstMessage = newDialogueMessages[0];
727
- const lastMessage = newDialogueMessages[newDialogueMessages.length - 1];
728
- const startTime = existingSummary ? existingSummary.startTime : firstMessage?.createdAt && firstMessage.createdAt > 0 ? new Date(firstMessage.createdAt) : new Date;
729
- const endTime = lastMessage?.createdAt && lastMessage.createdAt > 0 ? new Date(lastMessage.createdAt) : new Date;
730
- if (existingSummary) {
731
- await memoryService.updateSessionSummary(existingSummary.id, roomId, {
732
- summary: summaryResult.summary,
733
- messageCount: existingSummary.messageCount + newDialogueMessages.length,
734
- lastMessageOffset: newOffset,
735
- endTime,
736
- topics: summaryResult.topics,
737
- metadata: {
738
- keyPoints: summaryResult.keyPoints
739
- }
740
- });
741
- import_core2.logger.info(`Updated summary for room ${roomId}: ${newDialogueMessages.length} new dialogue messages processed (offset: ${lastOffset} → ${newOffset})`);
742
- } else {
743
- await memoryService.storeSessionSummary({
744
- agentId: runtime.agentId,
745
- roomId,
746
- entityId: message.entityId !== runtime.agentId ? message.entityId : undefined,
747
- summary: summaryResult.summary,
748
- messageCount: totalDialogueCount,
749
- lastMessageOffset: totalDialogueCount,
750
- startTime,
751
- endTime,
752
- topics: summaryResult.topics,
753
- metadata: {
754
- keyPoints: summaryResult.keyPoints
755
- }
756
- });
757
- import_core2.logger.info(`Created new summary for room ${roomId}: ${totalDialogueCount} dialogue messages summarized (offset: 0 → ${totalDialogueCount})`);
758
- }
759
- } catch (error) {
760
- import_core2.logger.error({ error }, "Error during summarization:");
761
- }
762
- },
763
- examples: []
764
- };
765
-
766
- // src/evaluators/long-term-extraction.ts
767
- var import_core3 = require("@elizaos/core");
768
-
769
- // src/types/index.ts
770
- var LongTermMemoryCategory;
771
- ((LongTermMemoryCategory2) => {
772
- LongTermMemoryCategory2["EPISODIC"] = "episodic";
773
- LongTermMemoryCategory2["SEMANTIC"] = "semantic";
774
- LongTermMemoryCategory2["PROCEDURAL"] = "procedural";
775
- })(LongTermMemoryCategory ||= {});
776
-
777
- // src/evaluators/long-term-extraction.ts
778
- var extractionTemplate = `# Task: Extract Long-Term Memory (Strict Criteria)
779
-
780
- You are analyzing a conversation to extract ONLY the most critical, persistent information about the user using cognitive science memory categories.
781
-
782
- # Recent Messages
783
- {{recentMessages}}
784
-
785
- # Current Long-Term Memories
786
- {{existingMemories}}
787
-
788
- # Memory Categories (Based on Cognitive Science)
789
-
790
- ## 1. EPISODIC Memory
791
- Personal experiences and specific events with temporal/spatial context.
792
- **Examples:**
793
- - "User completed migration project from MongoDB to PostgreSQL in Q2 2024"
794
- - "User encountered authentication bug in production on March 15th"
795
- - "User had a negative experience with Docker networking in previous job"
796
-
797
- **Requirements:**
798
- - Must include WHO did WHAT, WHEN/WHERE
799
- - Must be a specific, concrete event (not a pattern)
800
- - Must have significant impact or relevance to future work
801
-
802
- ## 2. SEMANTIC Memory
803
- General facts, concepts, knowledge, and established truths about the user.
804
- **Examples:**
805
- - "User is a senior backend engineer with 8 years experience"
806
- - "User specializes in distributed systems and microservices architecture"
807
- - "User's primary programming language is TypeScript"
808
- - "User works at Acme Corp as technical lead"
809
-
810
- **Requirements:**
811
- - Must be factual, timeless information
812
- - Must be explicitly stated or demonstrated conclusively
813
- - No speculation or inference from single instances
814
- - Core identity, expertise, or knowledge only
815
-
816
- ## 3. PROCEDURAL Memory
817
- Skills, workflows, methodologies, and how-to knowledge.
818
- **Examples:**
819
- - "User follows strict TDD workflow: write tests first, then implementation"
820
- - "User prefers git rebase over merge to maintain linear history"
821
- - "User's debugging process: check logs → reproduce locally → binary search"
822
- - "User always writes JSDoc comments before implementing functions"
823
-
824
- **Requirements:**
825
- - Must describe HOW user does something
826
- - Must be a repeated, consistent pattern (seen 3+ times or explicitly stated as standard practice)
827
- - Must be a workflow, methodology, or skill application
828
- - Not one-off preferences
829
-
830
- # ULTRA-STRICT EXTRACTION CRITERIA
831
-
832
- ## ✅ DO EXTRACT (Only These):
833
-
834
- **EPISODIC:**
835
- - Significant completed projects or milestones
836
- - Important bugs, incidents, or problems encountered
837
- - Major decisions made with lasting impact
838
- - Formative experiences that shape future work
839
-
840
- **SEMANTIC:**
841
- - Professional identity (role, title, company)
842
- - Core expertise and specializations (stated explicitly or demonstrated conclusively)
843
- - Primary languages, frameworks, or tools (not exploratory use)
844
- - Established facts about their work context
845
-
846
- **PROCEDURAL:**
847
- - Consistent workflows demonstrated 3+ times or explicitly stated
848
- - Standard practices user always follows
849
- - Methodology preferences with clear rationale
850
- - Debugging, testing, or development processes
851
-
852
- ## ❌ NEVER EXTRACT:
853
-
854
- - **One-time requests or tasks** (e.g., "can you generate an image", "help me debug this")
855
- - **Casual conversations** without lasting significance
856
- - **Exploratory questions** (e.g., "how does X work?")
857
- - **Temporary context** (current bug, today's task)
858
- - **Preferences from single occurrence** (e.g., user asked for code once)
859
- - **Social pleasantries** (thank you, greetings)
860
- - **Testing or experimentation** (trying out a feature)
861
- - **Common patterns everyone has** (likes clear explanations)
862
- - **Situational information** (working on feature X today)
863
- - **Opinions without persistence** (single complaint, isolated praise)
864
- - **General knowledge** (not specific to user)
865
-
866
- # Quality Gates (ALL Must Pass)
867
-
868
- 1. **Significance Test**: Will this matter in 3+ months?
869
- 2. **Specificity Test**: Is this concrete and actionable?
870
- 3. **Evidence Test**: Is there strong evidence (3+ instances OR explicit self-identification)?
871
- 4. **Uniqueness Test**: Is this specific to THIS user (not generic)?
872
- 5. **Confidence Test**: Confidence must be >= 0.85 (be VERY conservative)
873
- 6. **Non-Redundancy Test**: Does this add NEW information not in existing memories?
874
-
875
- # Confidence Scoring (Be Conservative)
876
-
877
- - **0.95-1.0**: User explicitly stated as core identity/practice AND demonstrated multiple times
878
- - **0.85-0.94**: User explicitly stated OR consistently demonstrated 5+ times
879
- - **0.75-0.84**: Strong pattern (3-4 instances) with supporting context
880
- - **Below 0.75**: DO NOT EXTRACT (insufficient evidence)
881
-
882
- # Critical Instructions
883
-
884
- 1. **Default to NOT extracting** - When in doubt, skip it
885
- 2. **Require overwhelming evidence** - One or two mentions is NOT enough
886
- 3. **Focus on what's PERSISTENT** - Not what's temporary or situational
887
- 4. **Verify against existing memories** - Don't duplicate or contradict
888
- 5. **Maximum 2-3 extractions per run** - Quality over quantity
889
-
890
- **If there are no qualifying facts (which is common), respond with <memories></memories>**
891
-
892
- # Response Format
893
-
894
- <memories>
895
- <memory>
896
- <category>semantic</category>
897
- <content>User is a senior TypeScript developer with 8 years of backend experience</content>
898
- <confidence>0.95</confidence>
899
- </memory>
900
- <memory>
901
- <category>procedural</category>
902
- <content>User follows TDD workflow: writes tests before implementation, runs tests after each change</content>
903
- <confidence>0.88</confidence>
904
- </memory>
905
- <memory>
906
- <category>episodic</category>
907
- <content>User led database migration from MongoDB to PostgreSQL for payment system in Q2 2024</content>
908
- <confidence>0.92</confidence>
909
- </memory>
910
- </memories>`;
911
- function parseMemoryExtractionXML(xml) {
912
- const memoryMatches = xml.matchAll(/<memory>[\s\S]*?<category>(.*?)<\/category>[\s\S]*?<content>(.*?)<\/content>[\s\S]*?<confidence>(.*?)<\/confidence>[\s\S]*?<\/memory>/g);
913
- const extractions = [];
914
- for (const match of memoryMatches) {
915
- const category = match[1].trim();
916
- const content = match[2].trim();
917
- const confidence = parseFloat(match[3].trim());
918
- if (!Object.values(LongTermMemoryCategory).includes(category)) {
919
- import_core3.logger.warn(`Invalid memory category: ${category}`);
920
- continue;
921
- }
922
- if (content && !isNaN(confidence)) {
923
- extractions.push({ category, content, confidence });
924
- }
925
- }
926
- return extractions;
927
- }
928
- var longTermExtractionEvaluator = {
929
- name: "LONG_TERM_MEMORY_EXTRACTION",
930
- description: "Extracts long-term facts about users from conversations",
931
- similes: ["MEMORY_EXTRACTION", "FACT_LEARNING", "USER_PROFILING"],
932
- alwaysRun: true,
933
- validate: async (runtime, message) => {
934
- if (message.entityId === runtime.agentId) {
935
- return false;
936
- }
937
- if (!message.content?.text) {
938
- return false;
939
- }
940
- const memoryService = runtime.getService("memory");
941
- if (!memoryService) {
942
- return false;
943
- }
944
- const config = memoryService.getConfig();
945
- if (!config.longTermExtractionEnabled) {
946
- import_core3.logger.debug("Long-term memory extraction is disabled");
947
- return false;
948
- }
949
- const currentMessageCount = await runtime.countMemories(message.roomId, false, "messages");
950
- const shouldRun = await memoryService.shouldRunExtraction(message.entityId, message.roomId, currentMessageCount);
951
- return shouldRun;
952
- },
953
- handler: async (runtime, message) => {
954
- const memoryService = runtime.getService("memory");
955
- if (!memoryService) {
956
- import_core3.logger.error("MemoryService not found");
957
- return;
958
- }
959
- const config = memoryService.getConfig();
960
- const { entityId, roomId } = message;
961
- try {
962
- import_core3.logger.info(`Extracting long-term memories for entity ${entityId}`);
963
- const recentMessages = await runtime.getMemories({
964
- tableName: "messages",
965
- roomId,
966
- count: 20,
967
- unique: false
968
- });
969
- const formattedMessages = recentMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
970
- const sender = msg.entityId === runtime.agentId ? runtime.character.name : "User";
971
- return `${sender}: ${msg.content.text || "[non-text message]"}`;
972
- }).join(`
973
- `);
974
- const existingMemories = await memoryService.getLongTermMemories(entityId, undefined, 30);
975
- const formattedExisting = existingMemories.length > 0 ? existingMemories.map((m) => `[${m.category}] ${m.content} (confidence: ${m.confidence})`).join(`
976
- `) : "None yet";
977
- const state = await runtime.composeState(message);
978
- const prompt = import_core3.composePromptFromState({
979
- state: {
980
- ...state,
981
- recentMessages: formattedMessages,
982
- existingMemories: formattedExisting
983
- },
984
- template: extractionTemplate
985
- });
986
- const response = await runtime.useModel(import_core3.ModelType.TEXT_LARGE, {
987
- prompt
988
- });
989
- const extractions = parseMemoryExtractionXML(response);
990
- import_core3.logger.info(`Extracted ${extractions.length} long-term memories`);
991
- for (const extraction of extractions) {
992
- if (extraction.confidence >= Math.max(config.longTermConfidenceThreshold, 0.85)) {
993
- await memoryService.storeLongTermMemory({
994
- agentId: runtime.agentId,
995
- entityId,
996
- category: extraction.category,
997
- content: extraction.content,
998
- confidence: extraction.confidence,
999
- source: "conversation",
1000
- metadata: {
1001
- roomId,
1002
- extractedAt: new Date().toISOString()
1003
- }
1004
- });
1005
- import_core3.logger.info(`Stored long-term memory: [${extraction.category}] ${extraction.content.substring(0, 50)}...`);
1006
- } else {
1007
- import_core3.logger.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence}, threshold: ${Math.max(config.longTermConfidenceThreshold, 0.85)})`);
1008
- }
1009
- }
1010
- const currentMessageCount = await runtime.countMemories(roomId, false, "messages");
1011
- await memoryService.setLastExtractionCheckpoint(entityId, roomId, currentMessageCount);
1012
- import_core3.logger.debug(`Updated extraction checkpoint to ${currentMessageCount} for entity ${entityId} in room ${roomId}`);
1013
- } catch (error) {
1014
- import_core3.logger.error({ error }, "Error during long-term memory extraction:");
1015
- }
1016
- },
1017
- examples: []
1018
- };
1019
-
1020
- // src/providers/long-term-memory.ts
1021
- var import_core4 = require("@elizaos/core");
1022
- var longTermMemoryProvider = {
1023
- name: "LONG_TERM_MEMORY",
1024
- description: "Persistent facts and preferences about the user",
1025
- position: 50,
1026
- get: async (runtime, message, _state) => {
1027
- try {
1028
- const memoryService = runtime.getService("memory");
1029
- if (!memoryService) {
1030
- return {
1031
- data: { memories: [] },
1032
- values: { longTermMemories: "" },
1033
- text: ""
1034
- };
1035
- }
1036
- const { entityId } = message;
1037
- if (entityId === runtime.agentId) {
1038
- return {
1039
- data: { memories: [] },
1040
- values: { longTermMemories: "" },
1041
- text: ""
1042
- };
1043
- }
1044
- const memories = await memoryService.getLongTermMemories(entityId, undefined, 25);
1045
- if (memories.length === 0) {
1046
- return {
1047
- data: { memories: [] },
1048
- values: { longTermMemories: "" },
1049
- text: ""
1050
- };
1051
- }
1052
- const formattedMemories = await memoryService.getFormattedLongTermMemories(entityId);
1053
- const text4 = import_core4.addHeader("# What I Know About You", formattedMemories);
1054
- const categoryCounts = new Map;
1055
- for (const memory of memories) {
1056
- const count = categoryCounts.get(memory.category) || 0;
1057
- categoryCounts.set(memory.category, count + 1);
1058
- }
1059
- const categoryList = Array.from(categoryCounts.entries()).map(([cat, count]) => `${cat}: ${count}`).join(", ");
1060
- return {
1061
- data: {
1062
- memories,
1063
- categoryCounts: Object.fromEntries(categoryCounts)
1064
- },
1065
- values: {
1066
- longTermMemories: text4,
1067
- memoryCategories: categoryList
1068
- },
1069
- text: text4
1070
- };
1071
- } catch (error) {
1072
- import_core4.logger.error({ error }, "Error in longTermMemoryProvider:");
1073
- return {
1074
- data: { memories: [] },
1075
- values: { longTermMemories: "" },
1076
- text: ""
1077
- };
1078
- }
1079
- }
1080
- };
1081
-
1082
- // src/providers/context-summary.ts
1083
- var import_core5 = require("@elizaos/core");
1084
- var contextSummaryProvider = {
1085
- name: "SUMMARIZED_CONTEXT",
1086
- description: "Provides summarized context from previous conversations",
1087
- position: 96,
1088
- get: async (runtime, message, _state) => {
1089
- try {
1090
- const memoryService = runtime.getService("memory");
1091
- const { roomId } = message;
1092
- if (!memoryService) {
1093
- return {
1094
- data: {
1095
- summary: null
1096
- },
1097
- values: {
1098
- sessionSummaries: "",
1099
- sessionSummariesWithTopics: ""
1100
- },
1101
- text: ""
1102
- };
1103
- }
1104
- const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1105
- if (!currentSummary) {
1106
- return {
1107
- data: {
1108
- summary: null
1109
- },
1110
- values: {
1111
- sessionSummaries: "",
1112
- sessionSummariesWithTopics: ""
1113
- },
1114
- text: ""
1115
- };
1116
- }
1117
- const messageRange = `${currentSummary.messageCount} messages`;
1118
- const timeRange = new Date(currentSummary.startTime).toLocaleDateString();
1119
- let summaryOnly = `**Previous Conversation** (${messageRange}, ${timeRange})
1120
- `;
1121
- summaryOnly += currentSummary.summary;
1122
- let summaryWithTopics = summaryOnly;
1123
- if (currentSummary.topics && currentSummary.topics.length > 0) {
1124
- summaryWithTopics += `
1125
- *Topics: ${currentSummary.topics.join(", ")}*`;
1126
- }
1127
- const sessionSummaries2 = import_core5.addHeader("# Conversation Summary", summaryOnly);
1128
- const sessionSummariesWithTopics = import_core5.addHeader("# Conversation Summary", summaryWithTopics);
1129
- return {
1130
- data: {
1131
- summary: currentSummary
1132
- },
1133
- values: {
1134
- sessionSummaries: sessionSummaries2,
1135
- sessionSummariesWithTopics
1136
- },
1137
- text: sessionSummariesWithTopics
1138
- };
1139
- } catch (error) {
1140
- import_core5.logger.error({ error }, "Error in contextSummaryProvider:");
1141
- return {
1142
- data: {
1143
- summary: null
1144
- },
1145
- values: {
1146
- sessionSummaries: "",
1147
- sessionSummariesWithTopics: ""
1148
- },
1149
- text: ""
1150
- };
1151
- }
1152
- }
1153
- };
1154
-
1155
- // src/providers/recent-messages.ts
1156
- var import_core6 = require("@elizaos/core");
1157
- var recentMessagesProvider = {
1158
- name: "RECENT_MESSAGES",
1159
- description: "Provides recent conversation messages with detailed context",
1160
- position: 94,
1161
- get: async (runtime, message, _state) => {
1162
- try {
1163
- const memoryService = runtime.getService("memory");
1164
- const { roomId } = message;
1165
- const config = memoryService?.getConfig() || {
1166
- shortTermSummarizationThreshold: 16,
1167
- shortTermRetainRecent: 6
1168
- };
1169
- const conversationLength = runtime.getConversationLength();
1170
- let messagesToFetch = config.shortTermRetainRecent;
1171
- let startOffset = 0;
1172
- let hasSummary = false;
1173
- if (memoryService) {
1174
- const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1175
- if (currentSummary) {
1176
- hasSummary = true;
1177
- startOffset = currentSummary.lastMessageOffset || 0;
1178
- }
1179
- }
1180
- if (!hasSummary) {
1181
- const allMessages = await runtime.getMemories({
1182
- tableName: "messages",
1183
- roomId,
1184
- count: conversationLength,
1185
- unique: false
1186
- });
1187
- const dialogueMessageCount = allMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result") && (msg.metadata?.type === "agent_response_message" || msg.metadata?.type === "user_message")).length;
1188
- if (dialogueMessageCount < config.shortTermSummarizationThreshold) {
1189
- messagesToFetch = conversationLength;
1190
- }
1191
- }
1192
- const [entitiesData, room, recentMessagesData] = await Promise.all([
1193
- import_core6.getEntityDetails({ runtime, roomId }),
1194
- runtime.getRoom(roomId),
1195
- runtime.getMemories({
1196
- tableName: "messages",
1197
- roomId,
1198
- count: messagesToFetch,
1199
- unique: false,
1200
- start: startOffset
1201
- })
1202
- ]);
1203
- const isPostFormat = room?.type ? room.type === import_core6.ChannelType.FEED || room.type === import_core6.ChannelType.THREAD : false;
1204
- const dialogueMessages = recentMessagesData.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result") && (msg.metadata?.type === "agent_response_message" || msg.metadata?.type === "user_message"));
1205
- let recentMessagesText = "";
1206
- if (dialogueMessages.length > 0) {
1207
- if (isPostFormat) {
1208
- recentMessagesText = import_core6.formatPosts({
1209
- messages: dialogueMessages,
1210
- entities: entitiesData,
1211
- conversationHeader: false
1212
- });
1213
- } else {
1214
- recentMessagesText = import_core6.formatMessages({
1215
- messages: dialogueMessages,
1216
- entities: entitiesData
1217
- });
1218
- }
1219
- if (recentMessagesText) {
1220
- recentMessagesText = import_core6.addHeader("# Recent Messages", recentMessagesText);
1221
- }
1222
- }
1223
- const formatConversationLog = (messages, includeThoughts) => {
1224
- return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
1225
- const entity = entitiesData.find((e) => e.id === msg.entityId);
1226
- const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
1227
- const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
1228
- const text5 = msg.content.text || "";
1229
- const thought = includeThoughts && msg.content.thought ? `
1230
- [Internal thought: ${msg.content.thought}]` : "";
1231
- return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
1232
- }).join(`
1233
- `);
1234
- };
1235
- const conversationLog = import_core6.addHeader("# Conversation Messages", formatConversationLog(dialogueMessages, false));
1236
- const conversationLogWithAgentThoughts = import_core6.addHeader("# Conversation Messages", formatConversationLog(dialogueMessages, true));
1237
- const metaData = message.metadata;
1238
- const senderName = entitiesData.find((entity) => entity.id === message.entityId)?.names[0] || metaData?.entityName || "Unknown User";
1239
- const receivedMessageContent = message.content.text;
1240
- const hasReceivedMessage = !!receivedMessageContent?.trim();
1241
- const receivedMessageHeader = hasReceivedMessage ? import_core6.addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1242
- const focusHeader = hasReceivedMessage ? import_core6.addHeader("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`) : "";
1243
- const text4 = [recentMessagesText, receivedMessageHeader, focusHeader].filter(Boolean).join(`
1244
-
1245
- `);
1246
- return {
1247
- data: {
1248
- messages: dialogueMessages
1249
- },
1250
- values: {
1251
- recentMessages: recentMessagesText,
1252
- conversationLog,
1253
- conversationLogWithAgentThoughts,
1254
- ...receivedMessageHeader && { receivedMessageHeader },
1255
- ...focusHeader && { focusHeader }
1256
- },
1257
- text: text4
1258
- };
1259
- } catch (error) {
1260
- import_core6.logger.error({ error }, "Error in recentMessagesProvider:");
1261
- return {
1262
- data: {
1263
- messages: []
1264
- },
1265
- values: {
1266
- recentMessages: "",
1267
- conversationLog: "",
1268
- conversationLogWithAgentThoughts: "",
1269
- receivedMessageHeader: "",
1270
- focusHeader: ""
1271
- },
1272
- text: ""
1273
- };
1274
- }
1275
- }
1276
- };
1277
-
1278
- // src/index.ts
1279
- var memoryPlugin = {
1280
- name: "memory",
1281
- description: "Advanced memory management with conversation summarization and long-term persistent memory",
1282
- services: [MemoryService],
1283
- evaluators: [summarizationEvaluator, longTermExtractionEvaluator],
1284
- providers: [
1285
- longTermMemoryProvider,
1286
- contextSummaryProvider,
1287
- recentMessagesProvider
1288
- ],
1289
- schema: exports_schemas
1290
- };
1291
- var src_default = memoryPlugin;
1292
-
1293
- //# debugId=38CF5E9664327F8064756E2164756E21