@elizaos/plugin-memory 1.0.4 → 1.0.6

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.
@@ -126,14 +126,17 @@ class MemoryService extends import_core.Service {
126
126
  this.sessionMessageCounts = new Map;
127
127
  this.lastExtractionCheckpoints = new Map;
128
128
  this.memoryConfig = {
129
- shortTermSummarizationThreshold: 5,
130
- shortTermRetainRecent: 10,
129
+ shortTermSummarizationThreshold: 16,
130
+ shortTermRetainRecent: 6,
131
+ shortTermSummarizationInterval: 10,
131
132
  longTermExtractionEnabled: true,
132
133
  longTermVectorSearchEnabled: false,
133
- longTermConfidenceThreshold: 0.7,
134
- longTermExtractionInterval: 5,
134
+ longTermConfidenceThreshold: 0.85,
135
+ longTermExtractionThreshold: 30,
136
+ longTermExtractionInterval: 10,
135
137
  summaryModelType: "TEXT_LARGE",
136
- summaryMaxTokens: 2500
138
+ summaryMaxTokens: 2500,
139
+ summaryMaxNewMessages: 20
137
140
  };
138
141
  }
139
142
  static async start(runtime) {
@@ -154,6 +157,14 @@ class MemoryService extends import_core.Service {
154
157
  if (retainRecent) {
155
158
  this.memoryConfig.shortTermRetainRecent = parseInt(retainRecent, 10);
156
159
  }
160
+ const summarizationInterval = runtime.getSetting("MEMORY_SUMMARIZATION_INTERVAL");
161
+ if (summarizationInterval) {
162
+ this.memoryConfig.shortTermSummarizationInterval = parseInt(summarizationInterval, 10);
163
+ }
164
+ const maxNewMessages = runtime.getSetting("MEMORY_MAX_NEW_MESSAGES");
165
+ if (maxNewMessages) {
166
+ this.memoryConfig.summaryMaxNewMessages = parseInt(maxNewMessages, 10);
167
+ }
157
168
  const longTermEnabled = runtime.getSetting("MEMORY_LONG_TERM_ENABLED");
158
169
  if (longTermEnabled === "false") {
159
170
  this.memoryConfig.longTermExtractionEnabled = false;
@@ -164,10 +175,21 @@ class MemoryService extends import_core.Service {
164
175
  if (confidenceThreshold) {
165
176
  this.memoryConfig.longTermConfidenceThreshold = parseFloat(confidenceThreshold);
166
177
  }
178
+ const extractionThreshold = runtime.getSetting("MEMORY_EXTRACTION_THRESHOLD");
179
+ if (extractionThreshold) {
180
+ this.memoryConfig.longTermExtractionThreshold = parseInt(extractionThreshold, 10);
181
+ }
182
+ const extractionInterval = runtime.getSetting("MEMORY_EXTRACTION_INTERVAL");
183
+ if (extractionInterval) {
184
+ this.memoryConfig.longTermExtractionInterval = parseInt(extractionInterval, 10);
185
+ }
167
186
  import_core.logger.info({
168
187
  summarizationThreshold: this.memoryConfig.shortTermSummarizationThreshold,
188
+ summarizationInterval: this.memoryConfig.shortTermSummarizationInterval,
189
+ maxNewMessages: this.memoryConfig.summaryMaxNewMessages,
169
190
  retainRecent: this.memoryConfig.shortTermRetainRecent,
170
191
  longTermEnabled: this.memoryConfig.longTermExtractionEnabled,
192
+ extractionThreshold: this.memoryConfig.longTermExtractionThreshold,
171
193
  extractionInterval: this.memoryConfig.longTermExtractionInterval,
172
194
  confidenceThreshold: this.memoryConfig.longTermConfidenceThreshold
173
195
  }, "MemoryService initialized");
@@ -228,14 +250,26 @@ class MemoryService extends import_core.Service {
228
250
  }
229
251
  }
230
252
  async shouldRunExtraction(entityId, roomId, currentMessageCount) {
253
+ const threshold = this.memoryConfig.longTermExtractionThreshold;
231
254
  const interval = this.memoryConfig.longTermExtractionInterval;
255
+ if (currentMessageCount < threshold) {
256
+ import_core.logger.debug({
257
+ entityId,
258
+ roomId,
259
+ currentMessageCount,
260
+ threshold,
261
+ shouldRun: false
262
+ }, "Extraction check: below threshold");
263
+ return false;
264
+ }
232
265
  const lastCheckpoint = await this.getLastExtractionCheckpoint(entityId, roomId);
233
266
  const currentCheckpoint = Math.floor(currentMessageCount / interval) * interval;
234
- const shouldRun = currentMessageCount >= interval && currentCheckpoint > lastCheckpoint;
267
+ const shouldRun = currentMessageCount >= threshold && currentCheckpoint > lastCheckpoint;
235
268
  import_core.logger.debug({
236
269
  entityId,
237
270
  roomId,
238
271
  currentMessageCount,
272
+ threshold,
239
273
  interval,
240
274
  lastCheckpoint,
241
275
  currentCheckpoint,
@@ -303,7 +337,7 @@ class MemoryService extends import_core.Service {
303
337
  accessCount: row.accessCount
304
338
  }));
305
339
  }
306
- async updateLongTermMemory(id, updates) {
340
+ async updateLongTermMemory(id, entityId, updates) {
307
341
  const db = this.getDb();
308
342
  const updateData = {
309
343
  updatedAt: new Date
@@ -326,13 +360,13 @@ class MemoryService extends import_core.Service {
326
360
  if (updates.accessCount !== undefined) {
327
361
  updateData.accessCount = updates.accessCount;
328
362
  }
329
- await db.update(longTermMemories).set(updateData).where(import_drizzle_orm4.eq(longTermMemories.id, id));
330
- import_core.logger.info(`Updated long-term memory: ${id}`);
363
+ 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)));
364
+ import_core.logger.info(`Updated long-term memory: ${id} for entity ${entityId}`);
331
365
  }
332
- async deleteLongTermMemory(id) {
366
+ async deleteLongTermMemory(id, entityId) {
333
367
  const db = this.getDb();
334
- await db.delete(longTermMemories).where(import_drizzle_orm4.eq(longTermMemories.id, id));
335
- import_core.logger.info(`Deleted long-term memory: ${id}`);
368
+ 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)));
369
+ import_core.logger.info(`Deleted long-term memory: ${id} for entity ${entityId}`);
336
370
  }
337
371
  async getCurrentSessionSummary(roomId) {
338
372
  const db = this.getDb();
@@ -387,7 +421,7 @@ class MemoryService extends import_core.Service {
387
421
  import_core.logger.info(`Stored session summary for room ${newSummary.roomId}`);
388
422
  return newSummary;
389
423
  }
390
- async updateSessionSummary(id, updates) {
424
+ async updateSessionSummary(id, roomId, updates) {
391
425
  const db = this.getDb();
392
426
  const updateData = {
393
427
  updatedAt: new Date
@@ -413,8 +447,8 @@ class MemoryService extends import_core.Service {
413
447
  if (updates.embedding !== undefined) {
414
448
  updateData.embedding = updates.embedding;
415
449
  }
416
- await db.update(sessionSummaries).set(updateData).where(import_drizzle_orm4.eq(sessionSummaries.id, id));
417
- import_core.logger.info(`Updated session summary: ${id}`);
450
+ 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)));
451
+ import_core.logger.info(`Updated session summary: ${id} for room ${roomId}`);
418
452
  }
419
453
  async getSessionSummaries(roomId, limit = 5) {
420
454
  const db = this.getDb();
@@ -594,14 +628,31 @@ var summarizationEvaluator = {
594
628
  }
595
629
  const config = memoryService.getConfig();
596
630
  const currentMessageCount = await runtime.countMemories(message.roomId, false, "messages");
597
- const shouldSummarize = currentMessageCount >= config.shortTermSummarizationThreshold;
598
- import_core2.logger.debug({
599
- roomId: message.roomId,
600
- currentMessageCount,
601
- threshold: config.shortTermSummarizationThreshold,
602
- shouldSummarize
603
- }, "Summarization validation check");
604
- return shouldSummarize;
631
+ const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);
632
+ if (!existingSummary) {
633
+ const shouldSummarize = currentMessageCount >= config.shortTermSummarizationThreshold;
634
+ import_core2.logger.debug({
635
+ roomId: message.roomId,
636
+ currentMessageCount,
637
+ threshold: config.shortTermSummarizationThreshold,
638
+ shouldSummarize,
639
+ reason: "initial_summary_check"
640
+ }, "Summarization validation check");
641
+ return shouldSummarize;
642
+ } else {
643
+ const newMessageCount = currentMessageCount - existingSummary.lastMessageOffset;
644
+ const shouldUpdate = newMessageCount >= config.shortTermSummarizationInterval;
645
+ import_core2.logger.debug({
646
+ roomId: message.roomId,
647
+ currentMessageCount,
648
+ lastOffset: existingSummary.lastMessageOffset,
649
+ newMessageCount,
650
+ interval: config.shortTermSummarizationInterval,
651
+ shouldUpdate,
652
+ reason: "summary_update_check"
653
+ }, "Summarization validation check");
654
+ return shouldUpdate;
655
+ }
605
656
  },
606
657
  handler: async (runtime, message) => {
607
658
  const memoryService = runtime.getService("memory");
@@ -616,15 +667,25 @@ var summarizationEvaluator = {
616
667
  const existingSummary = await memoryService.getCurrentSessionSummary(roomId);
617
668
  const lastOffset = existingSummary?.lastMessageOffset || 0;
618
669
  const totalMessageCount = await runtime.countMemories(roomId, false, "messages");
670
+ const newMessageCount = totalMessageCount - lastOffset;
671
+ const maxNewMessages = config.summaryMaxNewMessages || 50;
672
+ const messagesToFetch = Math.min(newMessageCount, maxNewMessages);
673
+ if (messagesToFetch === 0) {
674
+ import_core2.logger.debug("No new messages to summarize");
675
+ return;
676
+ }
677
+ if (newMessageCount > maxNewMessages) {
678
+ import_core2.logger.warn(`Capping new messages at ${maxNewMessages} (${newMessageCount} available). Oldest messages will be skipped.`);
679
+ }
619
680
  const newMessages = await runtime.getMemories({
620
681
  tableName: "messages",
621
682
  roomId,
622
- count: config.shortTermSummarizationThreshold,
683
+ count: messagesToFetch,
623
684
  unique: false,
624
685
  start: lastOffset
625
686
  });
626
687
  if (newMessages.length === 0) {
627
- import_core2.logger.debug("No new messages to summarize");
688
+ import_core2.logger.debug("No new messages retrieved");
628
689
  return;
629
690
  }
630
691
  const sortedMessages = newMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
@@ -669,7 +730,7 @@ var summarizationEvaluator = {
669
730
  const startTime = existingSummary ? existingSummary.startTime : firstMessage?.createdAt && firstMessage.createdAt > 0 ? new Date(firstMessage.createdAt) : new Date;
670
731
  const endTime = lastMessage?.createdAt && lastMessage.createdAt > 0 ? new Date(lastMessage.createdAt) : new Date;
671
732
  if (existingSummary) {
672
- await memoryService.updateSessionSummary(existingSummary.id, {
733
+ await memoryService.updateSessionSummary(existingSummary.id, roomId, {
673
734
  summary: summaryResult.summary,
674
735
  messageCount: existingSummary.messageCount + sortedMessages.length,
675
736
  lastMessageOffset: newOffset,
@@ -710,21 +771,15 @@ var import_core3 = require("@elizaos/core");
710
771
  // src/types/index.ts
711
772
  var LongTermMemoryCategory;
712
773
  ((LongTermMemoryCategory2) => {
713
- LongTermMemoryCategory2["IDENTITY"] = "identity";
714
- LongTermMemoryCategory2["EXPERTISE"] = "expertise";
715
- LongTermMemoryCategory2["PROJECTS"] = "projects";
716
- LongTermMemoryCategory2["PREFERENCES"] = "preferences";
717
- LongTermMemoryCategory2["DATA_SOURCES"] = "data_sources";
718
- LongTermMemoryCategory2["GOALS"] = "goals";
719
- LongTermMemoryCategory2["CONSTRAINTS"] = "constraints";
720
- LongTermMemoryCategory2["DEFINITIONS"] = "definitions";
721
- LongTermMemoryCategory2["BEHAVIORAL_PATTERNS"] = "behavioral_patterns";
774
+ LongTermMemoryCategory2["EPISODIC"] = "episodic";
775
+ LongTermMemoryCategory2["SEMANTIC"] = "semantic";
776
+ LongTermMemoryCategory2["PROCEDURAL"] = "procedural";
722
777
  })(LongTermMemoryCategory ||= {});
723
778
 
724
779
  // src/evaluators/long-term-extraction.ts
725
- var extractionTemplate = `# Task: Extract Long-Term Memory
780
+ var extractionTemplate = `# Task: Extract Long-Term Memory (Strict Criteria)
726
781
 
727
- You are analyzing a conversation to extract facts that should be remembered long-term about the user.
782
+ You are analyzing a conversation to extract ONLY the most critical, persistent information about the user using cognitive science memory categories.
728
783
 
729
784
  # Recent Messages
730
785
  {{recentMessages}}
@@ -732,37 +787,127 @@ You are analyzing a conversation to extract facts that should be remembered long
732
787
  # Current Long-Term Memories
733
788
  {{existingMemories}}
734
789
 
735
- # Memory Categories
736
- 1. **identity**: User's name, role, identity (e.g., "I'm a data scientist")
737
- 2. **expertise**: User's skills, knowledge domains, or unfamiliarity with topics
738
- 3. **projects**: Ongoing projects, past interactions, recurring topics
739
- 4. **preferences**: Communication style, format preferences, verbosity, etc.
740
- 5. **data_sources**: Frequently used files, databases, APIs
741
- 6. **goals**: Broader intentions (e.g., "preparing for interview")
742
- 7. **constraints**: User-defined rules or limitations
743
- 8. **definitions**: Custom terms, acronyms, glossaries
744
- 9. **behavioral_patterns**: How the user tends to interact
790
+ # Memory Categories (Based on Cognitive Science)
745
791
 
746
- # Instructions
747
- Extract any NEW information that should be remembered long-term. For each item:
748
- - Determine which category it belongs to
749
- - Write a clear, factual statement
750
- - Assess confidence (0.0 to 1.0)
751
- - Only include information explicitly stated or strongly implied
792
+ ## 1. EPISODIC Memory
793
+ Personal experiences and specific events with temporal/spatial context.
794
+ **Examples:**
795
+ - "User completed migration project from MongoDB to PostgreSQL in Q2 2024"
796
+ - "User encountered authentication bug in production on March 15th"
797
+ - "User had a negative experience with Docker networking in previous job"
752
798
 
753
- If there are no new long-term facts to extract, respond with <memories></memories>
799
+ **Requirements:**
800
+ - Must include WHO did WHAT, WHEN/WHERE
801
+ - Must be a specific, concrete event (not a pattern)
802
+ - Must have significant impact or relevance to future work
803
+
804
+ ## 2. SEMANTIC Memory
805
+ General facts, concepts, knowledge, and established truths about the user.
806
+ **Examples:**
807
+ - "User is a senior backend engineer with 8 years experience"
808
+ - "User specializes in distributed systems and microservices architecture"
809
+ - "User's primary programming language is TypeScript"
810
+ - "User works at Acme Corp as technical lead"
811
+
812
+ **Requirements:**
813
+ - Must be factual, timeless information
814
+ - Must be explicitly stated or demonstrated conclusively
815
+ - No speculation or inference from single instances
816
+ - Core identity, expertise, or knowledge only
817
+
818
+ ## 3. PROCEDURAL Memory
819
+ Skills, workflows, methodologies, and how-to knowledge.
820
+ **Examples:**
821
+ - "User follows strict TDD workflow: write tests first, then implementation"
822
+ - "User prefers git rebase over merge to maintain linear history"
823
+ - "User's debugging process: check logs → reproduce locally → binary search"
824
+ - "User always writes JSDoc comments before implementing functions"
825
+
826
+ **Requirements:**
827
+ - Must describe HOW user does something
828
+ - Must be a repeated, consistent pattern (seen 3+ times or explicitly stated as standard practice)
829
+ - Must be a workflow, methodology, or skill application
830
+ - Not one-off preferences
831
+
832
+ # ULTRA-STRICT EXTRACTION CRITERIA
833
+
834
+ ## ✅ DO EXTRACT (Only These):
835
+
836
+ **EPISODIC:**
837
+ - Significant completed projects or milestones
838
+ - Important bugs, incidents, or problems encountered
839
+ - Major decisions made with lasting impact
840
+ - Formative experiences that shape future work
841
+
842
+ **SEMANTIC:**
843
+ - Professional identity (role, title, company)
844
+ - Core expertise and specializations (stated explicitly or demonstrated conclusively)
845
+ - Primary languages, frameworks, or tools (not exploratory use)
846
+ - Established facts about their work context
847
+
848
+ **PROCEDURAL:**
849
+ - Consistent workflows demonstrated 3+ times or explicitly stated
850
+ - Standard practices user always follows
851
+ - Methodology preferences with clear rationale
852
+ - Debugging, testing, or development processes
853
+
854
+ ## ❌ NEVER EXTRACT:
855
+
856
+ - **One-time requests or tasks** (e.g., "can you generate an image", "help me debug this")
857
+ - **Casual conversations** without lasting significance
858
+ - **Exploratory questions** (e.g., "how does X work?")
859
+ - **Temporary context** (current bug, today's task)
860
+ - **Preferences from single occurrence** (e.g., user asked for code once)
861
+ - **Social pleasantries** (thank you, greetings)
862
+ - **Testing or experimentation** (trying out a feature)
863
+ - **Common patterns everyone has** (likes clear explanations)
864
+ - **Situational information** (working on feature X today)
865
+ - **Opinions without persistence** (single complaint, isolated praise)
866
+ - **General knowledge** (not specific to user)
867
+
868
+ # Quality Gates (ALL Must Pass)
869
+
870
+ 1. **Significance Test**: Will this matter in 3+ months?
871
+ 2. **Specificity Test**: Is this concrete and actionable?
872
+ 3. **Evidence Test**: Is there strong evidence (3+ instances OR explicit self-identification)?
873
+ 4. **Uniqueness Test**: Is this specific to THIS user (not generic)?
874
+ 5. **Confidence Test**: Confidence must be >= 0.85 (be VERY conservative)
875
+ 6. **Non-Redundancy Test**: Does this add NEW information not in existing memories?
876
+
877
+ # Confidence Scoring (Be Conservative)
878
+
879
+ - **0.95-1.0**: User explicitly stated as core identity/practice AND demonstrated multiple times
880
+ - **0.85-0.94**: User explicitly stated OR consistently demonstrated 5+ times
881
+ - **0.75-0.84**: Strong pattern (3-4 instances) with supporting context
882
+ - **Below 0.75**: DO NOT EXTRACT (insufficient evidence)
883
+
884
+ # Critical Instructions
885
+
886
+ 1. **Default to NOT extracting** - When in doubt, skip it
887
+ 2. **Require overwhelming evidence** - One or two mentions is NOT enough
888
+ 3. **Focus on what's PERSISTENT** - Not what's temporary or situational
889
+ 4. **Verify against existing memories** - Don't duplicate or contradict
890
+ 5. **Maximum 2-3 extractions per run** - Quality over quantity
891
+
892
+ **If there are no qualifying facts (which is common), respond with <memories></memories>**
893
+
894
+ # Response Format
754
895
 
755
- Respond in this XML format:
756
896
  <memories>
757
897
  <memory>
758
- <category>identity</category>
759
- <content>User is a software engineer specializing in backend development</content>
898
+ <category>semantic</category>
899
+ <content>User is a senior TypeScript developer with 8 years of backend experience</content>
760
900
  <confidence>0.95</confidence>
761
901
  </memory>
762
902
  <memory>
763
- <category>preferences</category>
764
- <content>Prefers code examples over lengthy explanations</content>
765
- <confidence>0.85</confidence>
903
+ <category>procedural</category>
904
+ <content>User follows TDD workflow: writes tests before implementation, runs tests after each change</content>
905
+ <confidence>0.88</confidence>
906
+ </memory>
907
+ <memory>
908
+ <category>episodic</category>
909
+ <content>User led database migration from MongoDB to PostgreSQL for payment system in Q2 2024</content>
910
+ <confidence>0.92</confidence>
766
911
  </memory>
767
912
  </memories>`;
768
913
  function parseMemoryExtractionXML(xml) {
@@ -851,7 +996,7 @@ var longTermExtractionEvaluator = {
851
996
  const extractions = parseMemoryExtractionXML(response);
852
997
  import_core3.logger.info(`Extracted ${extractions.length} long-term memories`);
853
998
  for (const extraction of extractions) {
854
- if (extraction.confidence >= config.longTermConfidenceThreshold) {
999
+ if (extraction.confidence >= Math.max(config.longTermConfidenceThreshold, 0.85)) {
855
1000
  await memoryService.storeLongTermMemory({
856
1001
  agentId: runtime.agentId,
857
1002
  entityId,
@@ -866,7 +1011,7 @@ var longTermExtractionEvaluator = {
866
1011
  });
867
1012
  import_core3.logger.info(`Stored long-term memory: [${extraction.category}] ${extraction.content.substring(0, 50)}...`);
868
1013
  } else {
869
- import_core3.logger.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence})`);
1014
+ import_core3.logger.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence}, threshold: ${Math.max(config.longTermConfidenceThreshold, 0.85)})`);
870
1015
  }
871
1016
  }
872
1017
  const currentMessageCount = await runtime.countMemories(roomId, false, "messages");
@@ -881,26 +1026,31 @@ var longTermExtractionEvaluator = {
881
1026
 
882
1027
  // src/providers/short-term-memory.ts
883
1028
  var import_core4 = require("@elizaos/core");
1029
+ var getRecentInteractions = async (runtime, sourceEntityId, targetEntityId, excludeRoomId) => {
1030
+ const rooms = await runtime.getRoomsForParticipants([sourceEntityId, targetEntityId]);
1031
+ return runtime.getMemoriesByRoomIds({
1032
+ tableName: "messages",
1033
+ roomIds: rooms.filter((room) => room !== excludeRoomId),
1034
+ limit: 20
1035
+ });
1036
+ };
884
1037
  var shortTermMemoryProvider = {
885
1038
  name: "SHORT_TERM_MEMORY",
886
- description: "Adaptive conversation context with smart summarization",
1039
+ description: "Unified conversation context with smart summarization and interactions",
887
1040
  position: 95,
888
1041
  get: async (runtime, message, _state) => {
889
1042
  try {
890
1043
  const memoryService = runtime.getService("memory");
891
- if (!memoryService) {
892
- return {
893
- data: { summaries: [], recentMessages: [], mode: "disabled" },
894
- values: {},
895
- text: ""
896
- };
897
- }
898
1044
  const { roomId } = message;
899
- const config = memoryService.getConfig();
1045
+ const conversationLength = 16;
1046
+ const config = memoryService?.getConfig() || {
1047
+ shortTermSummarizationThreshold: 16,
1048
+ shortTermRetainRecent: 6
1049
+ };
900
1050
  const totalMessageCount = await runtime.countMemories(roomId, false, "messages");
901
- if (totalMessageCount < config.shortTermSummarizationThreshold) {
902
- const conversationLength = runtime.getConversationLength();
903
- const [entitiesData, room, recentMessagesData] = await Promise.all([
1051
+ const useSummarization = memoryService && totalMessageCount >= config.shortTermSummarizationThreshold;
1052
+ if (!useSummarization) {
1053
+ const [entitiesData, room, recentMessagesData, recentInteractionsData] = await Promise.all([
904
1054
  import_core4.getEntityDetails({ runtime, roomId }),
905
1055
  runtime.getRoom(roomId),
906
1056
  runtime.getMemories({
@@ -908,7 +1058,8 @@ var shortTermMemoryProvider = {
908
1058
  roomId,
909
1059
  count: conversationLength,
910
1060
  unique: false
911
- })
1061
+ }),
1062
+ message.entityId !== runtime.agentId ? getRecentInteractions(runtime, message.entityId, runtime.agentId, roomId) : Promise.resolve([])
912
1063
  ]);
913
1064
  const actionResultMessages = recentMessagesData.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
914
1065
  const dialogueMessages = recentMessagesData.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
@@ -924,6 +1075,20 @@ var shortTermMemoryProvider = {
924
1075
  conversationHeader: false
925
1076
  })
926
1077
  ]);
1078
+ const formatConversationLog = (messages, includeThoughts) => {
1079
+ return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
1080
+ const entity = entitiesData.find((e) => e.id === msg.entityId);
1081
+ const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
1082
+ const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
1083
+ const text5 = msg.content.text || "";
1084
+ const thought = includeThoughts && msg.content.internalMonologue ? `
1085
+ [Internal thought: ${msg.content.internalMonologue}]` : "";
1086
+ return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
1087
+ }).join(`
1088
+ `);
1089
+ };
1090
+ const conversationLog = formatConversationLog(dialogueMessages, false);
1091
+ const conversationLogWithAgentThoughts = formatConversationLog(dialogueMessages, true);
927
1092
  let actionResultsText = "";
928
1093
  if (actionResultMessages.length > 0) {
929
1094
  const groupedByRun = new Map;
@@ -932,7 +1097,10 @@ var shortTermMemoryProvider = {
932
1097
  if (!groupedByRun.has(runId)) {
933
1098
  groupedByRun.set(runId, []);
934
1099
  }
935
- groupedByRun.get(runId)?.push(mem);
1100
+ const memories = groupedByRun.get(runId);
1101
+ if (memories) {
1102
+ memories.push(mem);
1103
+ }
936
1104
  }
937
1105
  const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
938
1106
  const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
@@ -968,11 +1136,20 @@ ${runText}`;
968
1136
  data: {
969
1137
  summaries: [],
970
1138
  recentMessages: [],
1139
+ recentInteractions: [],
971
1140
  actionResults: [],
972
1141
  mode: "full_conversation"
973
1142
  },
974
1143
  values: {
975
- recentMessage: "No recent message available."
1144
+ recentPosts: "",
1145
+ recentMessages: "",
1146
+ recentMessageInteractions: "",
1147
+ recentPostInteractions: "",
1148
+ recentInteractions: "",
1149
+ recentActionResults: "",
1150
+ recentMessage: "No recent message available.",
1151
+ conversationLog: "",
1152
+ conversationLogWithAgentThoughts: ""
976
1153
  },
977
1154
  text: "No recent messages available"
978
1155
  };
@@ -994,6 +1171,80 @@ ${runText}`;
994
1171
  const hasReceivedMessage = !!receivedMessageContent?.trim();
995
1172
  const receivedMessageHeader = hasReceivedMessage ? import_core4.addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
996
1173
  const focusHeader = hasReceivedMessage ? import_core4.addHeader("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message. Do not repeat earlier replies unless the sender asks again.`) : "";
1174
+ const interactionEntityMap = new Map;
1175
+ if (recentInteractionsData.length > 0) {
1176
+ const uniqueEntityIds = [
1177
+ ...new Set(recentInteractionsData.map((message2) => message2.entityId).filter((id) => id !== runtime.agentId))
1178
+ ];
1179
+ const uniqueEntityIdSet = new Set(uniqueEntityIds);
1180
+ const entitiesDataIdSet = new Set;
1181
+ entitiesData.forEach((entity) => {
1182
+ if (uniqueEntityIdSet.has(entity.id)) {
1183
+ interactionEntityMap.set(entity.id, entity);
1184
+ entitiesDataIdSet.add(entity.id);
1185
+ }
1186
+ });
1187
+ const remainingEntityIds = uniqueEntityIds.filter((id) => !entitiesDataIdSet.has(id));
1188
+ if (remainingEntityIds.length > 0) {
1189
+ const entities = await Promise.all(remainingEntityIds.map((entityId) => runtime.getEntityById(entityId)));
1190
+ entities.forEach((entity, index4) => {
1191
+ if (entity) {
1192
+ interactionEntityMap.set(remainingEntityIds[index4], entity);
1193
+ }
1194
+ });
1195
+ }
1196
+ }
1197
+ const getRecentMessageInteractions = async (recentInteractionsData2) => {
1198
+ const formattedInteractions = recentInteractionsData2.map((message2) => {
1199
+ const isSelf = message2.entityId === runtime.agentId;
1200
+ let sender;
1201
+ if (isSelf) {
1202
+ sender = runtime.character.name;
1203
+ } else {
1204
+ sender = interactionEntityMap.get(message2.entityId)?.metadata?.userName || "unknown";
1205
+ }
1206
+ return `${sender}: ${message2.content.text}`;
1207
+ });
1208
+ return formattedInteractions.join(`
1209
+ `);
1210
+ };
1211
+ const getRecentPostInteractions = async (recentInteractionsData2, entities) => {
1212
+ const combinedEntities = [...entities];
1213
+ const actorIds = new Set(entities.map((entity) => entity.id));
1214
+ for (const [id, entity] of interactionEntityMap.entries()) {
1215
+ if (!actorIds.has(id)) {
1216
+ combinedEntities.push(entity);
1217
+ }
1218
+ }
1219
+ const formattedInteractions = import_core4.formatPosts({
1220
+ messages: recentInteractionsData2,
1221
+ entities: combinedEntities,
1222
+ conversationHeader: true
1223
+ });
1224
+ return formattedInteractions;
1225
+ };
1226
+ const [recentMessageInteractions, recentPostInteractions] = await Promise.all([
1227
+ getRecentMessageInteractions(recentInteractionsData),
1228
+ getRecentPostInteractions(recentInteractionsData, entitiesData)
1229
+ ]);
1230
+ const data = {
1231
+ summaries: [],
1232
+ recentMessages: dialogueMessages,
1233
+ recentInteractions: recentInteractionsData,
1234
+ actionResults: actionResultMessages,
1235
+ mode: "full_conversation"
1236
+ };
1237
+ const values = {
1238
+ recentPosts,
1239
+ recentMessages,
1240
+ recentMessageInteractions,
1241
+ recentPostInteractions,
1242
+ recentInteractions: isPostFormat ? recentPostInteractions : recentMessageInteractions,
1243
+ recentActionResults: actionResultsText,
1244
+ recentMessage,
1245
+ conversationLog,
1246
+ conversationLogWithAgentThoughts
1247
+ };
997
1248
  const text4 = [
998
1249
  isPostFormat ? recentPosts : recentMessages,
999
1250
  actionResultsText,
@@ -1003,40 +1254,68 @@ ${runText}`;
1003
1254
 
1004
1255
  `);
1005
1256
  return {
1006
- data: {
1007
- summaries: [],
1008
- recentMessages: dialogueMessages,
1009
- actionResults: actionResultMessages,
1010
- mode: "full_conversation"
1011
- },
1012
- values: {
1013
- ...(isPostFormat ? recentPosts : recentMessages) && {
1014
- recentMessages: isPostFormat ? recentPosts : recentMessages
1015
- },
1016
- ...recentPosts && { recentPosts },
1017
- ...actionResultsText && { recentActionResults: actionResultsText },
1018
- ...recentMessage && { recentMessage },
1019
- ...receivedMessageHeader && { receivedMessageHeader },
1020
- ...focusHeader && { focusHeader }
1021
- },
1257
+ data,
1258
+ values,
1022
1259
  text: text4
1023
1260
  };
1024
1261
  } else {
1025
1262
  const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1026
1263
  const lastOffset = currentSummary?.lastMessageOffset || 0;
1027
- const unsummarizedMessages = await runtime.getMemories({
1028
- tableName: "messages",
1029
- roomId,
1030
- count: config.shortTermRetainRecent,
1031
- unique: false,
1032
- start: lastOffset
1033
- });
1034
- const entitiesData = await import_core4.getEntityDetails({ runtime, roomId });
1035
- const room = await runtime.getRoom(roomId);
1264
+ const recentCount = config.shortTermRetainRecent;
1265
+ const [entitiesData, room, unsummarizedMessages, recentInteractionsData] = await Promise.all([
1266
+ import_core4.getEntityDetails({ runtime, roomId }),
1267
+ runtime.getRoom(roomId),
1268
+ runtime.getMemories({
1269
+ tableName: "messages",
1270
+ roomId,
1271
+ count: recentCount,
1272
+ unique: false,
1273
+ start: lastOffset
1274
+ }),
1275
+ message.entityId !== runtime.agentId ? getRecentInteractions(runtime, message.entityId, runtime.agentId, roomId) : Promise.resolve([])
1276
+ ]);
1036
1277
  const isPostFormat = room?.type ? room.type === import_core4.ChannelType.FEED || room.type === import_core4.ChannelType.THREAD : false;
1278
+ const actionResultMessages = unsummarizedMessages.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
1279
+ const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
1280
+ let actionResultsText = "";
1281
+ if (actionResultMessages.length > 0) {
1282
+ const groupedByRun = new Map;
1283
+ for (const mem of actionResultMessages) {
1284
+ const runId = String(mem.content?.runId || "unknown");
1285
+ if (!groupedByRun.has(runId)) {
1286
+ groupedByRun.set(runId, []);
1287
+ }
1288
+ groupedByRun.get(runId)?.push(mem);
1289
+ }
1290
+ const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
1291
+ const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
1292
+ const thought = sortedMemories[0]?.content?.planThought || "";
1293
+ const runText = sortedMemories.map((mem) => {
1294
+ const actionName = mem.content?.actionName || "Unknown";
1295
+ const status = mem.content?.actionStatus || "unknown";
1296
+ const planStep = mem.content?.planStep || "";
1297
+ const text5 = mem.content?.text || "";
1298
+ const error = mem.content?.error || "";
1299
+ let memText = ` - ${actionName} (${status})`;
1300
+ if (planStep)
1301
+ memText += ` [${planStep}]`;
1302
+ if (error) {
1303
+ memText += `: Error - ${error}`;
1304
+ } else if (text5 && text5 !== `Executed action: ${actionName}`) {
1305
+ memText += `: ${text5}`;
1306
+ }
1307
+ return memText;
1308
+ }).join(`
1309
+ `);
1310
+ return `**Action Run ${runId.slice(0, 8)}**${thought ? ` - "${thought}"` : ""}
1311
+ ${runText}`;
1312
+ }).join(`
1313
+
1314
+ `);
1315
+ actionResultsText = formattedActionResults ? import_core4.addHeader("# Recent Action Executions", formattedActionResults) : "";
1316
+ }
1037
1317
  let recentMessagesText = "";
1038
- if (unsummarizedMessages.length > 0) {
1039
- const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
1318
+ if (dialogueMessages.length > 0) {
1040
1319
  if (isPostFormat) {
1041
1320
  recentMessagesText = import_core4.formatPosts({
1042
1321
  messages: dialogueMessages,
@@ -1053,6 +1332,31 @@ ${runText}`;
1053
1332
  recentMessagesText = import_core4.addHeader("# Recent Messages", recentMessagesText);
1054
1333
  }
1055
1334
  }
1335
+ let recentMessage = "No recent message available.";
1336
+ if (dialogueMessages.length > 0) {
1337
+ const mostRecentMessage = [...dialogueMessages].sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0))[0];
1338
+ const formattedSingleMessage = import_core4.formatMessages({
1339
+ messages: [mostRecentMessage],
1340
+ entities: entitiesData
1341
+ });
1342
+ if (formattedSingleMessage) {
1343
+ recentMessage = formattedSingleMessage;
1344
+ }
1345
+ }
1346
+ const formatConversationLog = (messages, includeThoughts) => {
1347
+ return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
1348
+ const entity = entitiesData.find((e) => e.id === msg.entityId);
1349
+ const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
1350
+ const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
1351
+ const text5 = msg.content.text || "";
1352
+ const thought = includeThoughts && msg.content.internalMonologue ? `
1353
+ [Internal thought: ${msg.content.internalMonologue}]` : "";
1354
+ return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
1355
+ }).join(`
1356
+ `);
1357
+ };
1358
+ const conversationLog = formatConversationLog(dialogueMessages, false);
1359
+ const conversationLogWithAgentThoughts = formatConversationLog(dialogueMessages, true);
1056
1360
  let summaryText = "";
1057
1361
  if (currentSummary) {
1058
1362
  const messageRange = `${currentSummary.messageCount} messages`;
@@ -1072,9 +1376,66 @@ ${runText}`;
1072
1376
  const hasReceivedMessage = !!receivedMessageContent?.trim();
1073
1377
  const receivedMessageHeader = hasReceivedMessage ? import_core4.addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1074
1378
  const focusHeader = hasReceivedMessage ? import_core4.addHeader("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`) : "";
1379
+ const interactionEntityMap = new Map;
1380
+ if (recentInteractionsData.length > 0) {
1381
+ const uniqueEntityIds = [
1382
+ ...new Set(recentInteractionsData.map((message2) => message2.entityId).filter((id) => id !== runtime.agentId))
1383
+ ];
1384
+ const uniqueEntityIdSet = new Set(uniqueEntityIds);
1385
+ const entitiesDataIdSet = new Set;
1386
+ entitiesData.forEach((entity) => {
1387
+ if (uniqueEntityIdSet.has(entity.id)) {
1388
+ interactionEntityMap.set(entity.id, entity);
1389
+ entitiesDataIdSet.add(entity.id);
1390
+ }
1391
+ });
1392
+ const remainingEntityIds = uniqueEntityIds.filter((id) => !entitiesDataIdSet.has(id));
1393
+ if (remainingEntityIds.length > 0) {
1394
+ const entities = await Promise.all(remainingEntityIds.map((entityId) => runtime.getEntityById(entityId)));
1395
+ entities.forEach((entity, index4) => {
1396
+ if (entity) {
1397
+ interactionEntityMap.set(remainingEntityIds[index4], entity);
1398
+ }
1399
+ });
1400
+ }
1401
+ }
1402
+ const getRecentMessageInteractions = async (recentInteractionsData2) => {
1403
+ const formattedInteractions = recentInteractionsData2.map((message2) => {
1404
+ const isSelf = message2.entityId === runtime.agentId;
1405
+ let sender;
1406
+ if (isSelf) {
1407
+ sender = runtime.character.name;
1408
+ } else {
1409
+ sender = interactionEntityMap.get(message2.entityId)?.metadata?.userName || "unknown";
1410
+ }
1411
+ return `${sender}: ${message2.content.text}`;
1412
+ });
1413
+ return formattedInteractions.join(`
1414
+ `);
1415
+ };
1416
+ const getRecentPostInteractions = async (recentInteractionsData2, entities) => {
1417
+ const combinedEntities = [...entities];
1418
+ const actorIds = new Set(entities.map((entity) => entity.id));
1419
+ for (const [id, entity] of interactionEntityMap.entries()) {
1420
+ if (!actorIds.has(id)) {
1421
+ combinedEntities.push(entity);
1422
+ }
1423
+ }
1424
+ const formattedInteractions = import_core4.formatPosts({
1425
+ messages: recentInteractionsData2,
1426
+ entities: combinedEntities,
1427
+ conversationHeader: true
1428
+ });
1429
+ return formattedInteractions;
1430
+ };
1431
+ const [recentMessageInteractions, recentPostInteractions] = await Promise.all([
1432
+ getRecentMessageInteractions(recentInteractionsData),
1433
+ getRecentPostInteractions(recentInteractionsData, entitiesData)
1434
+ ]);
1075
1435
  const text4 = [
1076
1436
  summaryText,
1077
1437
  recentMessagesText,
1438
+ actionResultsText,
1078
1439
  hasReceivedMessage ? receivedMessageHeader : "",
1079
1440
  hasReceivedMessage ? focusHeader : ""
1080
1441
  ].filter(Boolean).join(`
@@ -1083,12 +1444,21 @@ ${runText}`;
1083
1444
  return {
1084
1445
  data: {
1085
1446
  summaries: currentSummary ? [currentSummary] : [],
1086
- recentMessages: unsummarizedMessages,
1447
+ recentMessages: dialogueMessages,
1448
+ recentInteractions: recentInteractionsData,
1449
+ actionResults: actionResultMessages,
1087
1450
  mode: "summarized"
1088
1451
  },
1089
1452
  values: {
1090
1453
  ...summaryText && { sessionSummaries: summaryText },
1091
1454
  ...recentMessagesText && { recentMessages: recentMessagesText },
1455
+ recentMessageInteractions,
1456
+ recentPostInteractions,
1457
+ recentInteractions: isPostFormat ? recentPostInteractions : recentMessageInteractions,
1458
+ ...actionResultsText && { recentActionResults: actionResultsText },
1459
+ recentMessage,
1460
+ conversationLog,
1461
+ conversationLogWithAgentThoughts,
1092
1462
  ...receivedMessageHeader && { receivedMessageHeader },
1093
1463
  ...focusHeader && { focusHeader }
1094
1464
  },
@@ -1098,8 +1468,23 @@ ${runText}`;
1098
1468
  } catch (error) {
1099
1469
  import_core4.logger.error({ error }, "Error in shortTermMemoryProvider:");
1100
1470
  return {
1101
- data: { summaries: [], recentMessages: [], mode: "error" },
1102
- values: {},
1471
+ data: {
1472
+ summaries: [],
1473
+ recentMessages: [],
1474
+ recentInteractions: [],
1475
+ actionResults: [],
1476
+ mode: "error"
1477
+ },
1478
+ values: {
1479
+ recentPosts: "",
1480
+ recentMessages: "",
1481
+ recentMessageInteractions: "",
1482
+ recentPostInteractions: "",
1483
+ recentInteractions: "",
1484
+ recentActionResults: "",
1485
+ conversationLog: "",
1486
+ conversationLogWithAgentThoughts: ""
1487
+ },
1103
1488
  text: "Error retrieving conversation context."
1104
1489
  };
1105
1490
  }
@@ -1179,4 +1564,4 @@ var memoryPlugin = {
1179
1564
  };
1180
1565
  var src_default = memoryPlugin;
1181
1566
 
1182
- //# debugId=DC07601B16F2760064756E2164756E21
1567
+ //# debugId=A3C66779A69339CA64756E2164756E21