@elizaos/plugin-memory 1.0.5 → 1.0.7

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.
@@ -118,13 +118,13 @@ class MemoryService extends Service {
118
118
  this.lastExtractionCheckpoints = new Map;
119
119
  this.memoryConfig = {
120
120
  shortTermSummarizationThreshold: 16,
121
- shortTermRetainRecent: 10,
121
+ shortTermRetainRecent: 6,
122
122
  shortTermSummarizationInterval: 10,
123
123
  longTermExtractionEnabled: true,
124
124
  longTermVectorSearchEnabled: false,
125
- longTermConfidenceThreshold: 0.7,
126
- longTermExtractionThreshold: 20,
127
- longTermExtractionInterval: 5,
125
+ longTermConfidenceThreshold: 0.85,
126
+ longTermExtractionThreshold: 30,
127
+ longTermExtractionInterval: 10,
128
128
  summaryModelType: "TEXT_LARGE",
129
129
  summaryMaxTokens: 2500,
130
130
  summaryMaxNewMessages: 20
@@ -174,7 +174,7 @@ class MemoryService extends Service {
174
174
  if (extractionInterval) {
175
175
  this.memoryConfig.longTermExtractionInterval = parseInt(extractionInterval, 10);
176
176
  }
177
- logger.info({
177
+ logger.debug({
178
178
  summarizationThreshold: this.memoryConfig.shortTermSummarizationThreshold,
179
179
  summarizationInterval: this.memoryConfig.shortTermSummarizationInterval,
180
180
  maxNewMessages: this.memoryConfig.summaryMaxNewMessages,
@@ -535,6 +535,16 @@ import {
535
535
  ModelType,
536
536
  composePromptFromState
537
537
  } from "@elizaos/core";
538
+ async function getDialogueMessageCount(runtime, roomId) {
539
+ const messages = await runtime.getMemories({
540
+ tableName: "messages",
541
+ roomId,
542
+ count: 100,
543
+ unique: false
544
+ });
545
+ 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"));
546
+ return dialogueMessages.length;
547
+ }
538
548
  var initialSummarizationTemplate = `# Task: Summarize Conversation
539
549
 
540
550
  You are analyzing a conversation to create a concise summary that captures the key points, topics, and important details.
@@ -622,26 +632,26 @@ var summarizationEvaluator = {
622
632
  return false;
623
633
  }
624
634
  const config = memoryService.getConfig();
625
- const currentMessageCount = await runtime.countMemories(message.roomId, false, "messages");
635
+ const currentDialogueCount = await getDialogueMessageCount(runtime, message.roomId);
626
636
  const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);
627
637
  if (!existingSummary) {
628
- const shouldSummarize = currentMessageCount >= config.shortTermSummarizationThreshold;
638
+ const shouldSummarize = currentDialogueCount >= config.shortTermSummarizationThreshold;
629
639
  logger2.debug({
630
640
  roomId: message.roomId,
631
- currentMessageCount,
641
+ currentDialogueCount,
632
642
  threshold: config.shortTermSummarizationThreshold,
633
643
  shouldSummarize,
634
644
  reason: "initial_summary_check"
635
645
  }, "Summarization validation check");
636
646
  return shouldSummarize;
637
647
  } else {
638
- const newMessageCount = currentMessageCount - existingSummary.lastMessageOffset;
639
- const shouldUpdate = newMessageCount >= config.shortTermSummarizationInterval;
648
+ const newDialogueCount = currentDialogueCount - existingSummary.lastMessageOffset;
649
+ const shouldUpdate = newDialogueCount >= config.shortTermSummarizationInterval;
640
650
  logger2.debug({
641
651
  roomId: message.roomId,
642
- currentMessageCount,
652
+ currentDialogueCount,
643
653
  lastOffset: existingSummary.lastMessageOffset,
644
- newMessageCount,
654
+ newDialogueCount,
645
655
  interval: config.shortTermSummarizationInterval,
646
656
  shouldUpdate,
647
657
  reason: "summary_update_check"
@@ -661,30 +671,31 @@ var summarizationEvaluator = {
661
671
  logger2.info(`Starting summarization for room ${roomId}`);
662
672
  const existingSummary = await memoryService.getCurrentSessionSummary(roomId);
663
673
  const lastOffset = existingSummary?.lastMessageOffset || 0;
664
- const totalMessageCount = await runtime.countMemories(roomId, false, "messages");
665
- const newMessageCount = totalMessageCount - lastOffset;
666
- const maxNewMessages = config.summaryMaxNewMessages || 50;
667
- const messagesToFetch = Math.min(newMessageCount, maxNewMessages);
668
- if (messagesToFetch === 0) {
669
- logger2.debug("No new messages to summarize");
670
- return;
671
- }
672
- if (newMessageCount > maxNewMessages) {
673
- logger2.warn(`Capping new messages at ${maxNewMessages} (${newMessageCount} available). Oldest messages will be skipped.`);
674
- }
675
- const newMessages = await runtime.getMemories({
674
+ const allMessages = await runtime.getMemories({
676
675
  tableName: "messages",
677
676
  roomId,
678
- count: messagesToFetch,
679
- unique: false,
680
- start: lastOffset
677
+ count: 1000,
678
+ unique: false
681
679
  });
682
- if (newMessages.length === 0) {
683
- logger2.debug("No new messages retrieved");
680
+ 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"));
681
+ const totalDialogueCount = allDialogueMessages.length;
682
+ const newDialogueCount = totalDialogueCount - lastOffset;
683
+ if (newDialogueCount === 0) {
684
+ logger2.debug("No new dialogue messages to summarize");
685
+ return;
686
+ }
687
+ const maxNewMessages = config.summaryMaxNewMessages || 50;
688
+ const messagesToProcess = Math.min(newDialogueCount, maxNewMessages);
689
+ if (newDialogueCount > maxNewMessages) {
690
+ logger2.warn(`Capping new dialogue messages at ${maxNewMessages} (${newDialogueCount} available). Oldest messages will be skipped.`);
691
+ }
692
+ const sortedDialogueMessages = allDialogueMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
693
+ const newDialogueMessages = sortedDialogueMessages.slice(lastOffset, lastOffset + messagesToProcess);
694
+ if (newDialogueMessages.length === 0) {
695
+ logger2.debug("No new dialogue messages retrieved after filtering");
684
696
  return;
685
697
  }
686
- const sortedMessages = newMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
687
- const formattedMessages = sortedMessages.map((msg) => {
698
+ const formattedMessages = newDialogueMessages.map((msg) => {
688
699
  const sender = msg.entityId === runtime.agentId ? runtime.character.name : "User";
689
700
  return `${sender}: ${msg.content.text || "[non-text message]"}`;
690
701
  }).join(`
@@ -704,11 +715,16 @@ var summarizationEvaluator = {
704
715
  template
705
716
  });
706
717
  } else {
718
+ const initialMessages = sortedDialogueMessages.map((msg) => {
719
+ const sender = msg.entityId === runtime.agentId ? runtime.character.name : "User";
720
+ return `${sender}: ${msg.content.text || "[non-text message]"}`;
721
+ }).join(`
722
+ `);
707
723
  template = initialSummarizationTemplate;
708
724
  prompt = composePromptFromState({
709
725
  state: {
710
726
  ...state,
711
- recentMessages: formattedMessages
727
+ recentMessages: initialMessages
712
728
  },
713
729
  template
714
730
  });
@@ -719,15 +735,15 @@ var summarizationEvaluator = {
719
735
  });
720
736
  const summaryResult = parseSummaryXML(response);
721
737
  logger2.info(`${existingSummary ? "Updated" : "Generated"} summary: ${summaryResult.summary.substring(0, 100)}...`);
722
- const newOffset = totalMessageCount;
723
- const firstMessage = sortedMessages[0];
724
- const lastMessage = sortedMessages[sortedMessages.length - 1];
738
+ const newOffset = lastOffset + newDialogueMessages.length;
739
+ const firstMessage = newDialogueMessages[0];
740
+ const lastMessage = newDialogueMessages[newDialogueMessages.length - 1];
725
741
  const startTime = existingSummary ? existingSummary.startTime : firstMessage?.createdAt && firstMessage.createdAt > 0 ? new Date(firstMessage.createdAt) : new Date;
726
742
  const endTime = lastMessage?.createdAt && lastMessage.createdAt > 0 ? new Date(lastMessage.createdAt) : new Date;
727
743
  if (existingSummary) {
728
744
  await memoryService.updateSessionSummary(existingSummary.id, roomId, {
729
745
  summary: summaryResult.summary,
730
- messageCount: existingSummary.messageCount + sortedMessages.length,
746
+ messageCount: existingSummary.messageCount + newDialogueMessages.length,
731
747
  lastMessageOffset: newOffset,
732
748
  endTime,
733
749
  topics: summaryResult.topics,
@@ -735,15 +751,15 @@ var summarizationEvaluator = {
735
751
  keyPoints: summaryResult.keyPoints
736
752
  }
737
753
  });
738
- logger2.info(`Updated summary for room ${roomId}: ${sortedMessages.length} new messages processed (offset: ${lastOffset} → ${newOffset})`);
754
+ logger2.info(`Updated summary for room ${roomId}: ${newDialogueMessages.length} new dialogue messages processed (offset: ${lastOffset} → ${newOffset})`);
739
755
  } else {
740
756
  await memoryService.storeSessionSummary({
741
757
  agentId: runtime.agentId,
742
758
  roomId,
743
759
  entityId: message.entityId !== runtime.agentId ? message.entityId : undefined,
744
760
  summary: summaryResult.summary,
745
- messageCount: sortedMessages.length,
746
- lastMessageOffset: newOffset,
761
+ messageCount: totalDialogueCount,
762
+ lastMessageOffset: totalDialogueCount,
747
763
  startTime,
748
764
  endTime,
749
765
  topics: summaryResult.topics,
@@ -751,7 +767,7 @@ var summarizationEvaluator = {
751
767
  keyPoints: summaryResult.keyPoints
752
768
  }
753
769
  });
754
- logger2.info(`Created new summary for room ${roomId}: ${sortedMessages.length} messages summarized (offset: 0 → ${newOffset})`);
770
+ logger2.info(`Created new summary for room ${roomId}: ${totalDialogueCount} dialogue messages summarized (offset: 0 → ${totalDialogueCount})`);
755
771
  }
756
772
  } catch (error) {
757
773
  logger2.error({ error }, "Error during summarization:");
@@ -770,21 +786,15 @@ import {
770
786
  // src/types/index.ts
771
787
  var LongTermMemoryCategory;
772
788
  ((LongTermMemoryCategory2) => {
773
- LongTermMemoryCategory2["IDENTITY"] = "identity";
774
- LongTermMemoryCategory2["EXPERTISE"] = "expertise";
775
- LongTermMemoryCategory2["PROJECTS"] = "projects";
776
- LongTermMemoryCategory2["PREFERENCES"] = "preferences";
777
- LongTermMemoryCategory2["DATA_SOURCES"] = "data_sources";
778
- LongTermMemoryCategory2["GOALS"] = "goals";
779
- LongTermMemoryCategory2["CONSTRAINTS"] = "constraints";
780
- LongTermMemoryCategory2["DEFINITIONS"] = "definitions";
781
- LongTermMemoryCategory2["BEHAVIORAL_PATTERNS"] = "behavioral_patterns";
789
+ LongTermMemoryCategory2["EPISODIC"] = "episodic";
790
+ LongTermMemoryCategory2["SEMANTIC"] = "semantic";
791
+ LongTermMemoryCategory2["PROCEDURAL"] = "procedural";
782
792
  })(LongTermMemoryCategory ||= {});
783
793
 
784
794
  // src/evaluators/long-term-extraction.ts
785
- var extractionTemplate = `# Task: Extract Long-Term Memory
795
+ var extractionTemplate = `# Task: Extract Long-Term Memory (Strict Criteria)
786
796
 
787
- You are analyzing a conversation to extract ONLY the most important, persistent facts about the user that should be remembered long-term.
797
+ You are analyzing a conversation to extract ONLY the most critical, persistent information about the user using cognitive science memory categories.
788
798
 
789
799
  # Recent Messages
790
800
  {{recentMessages}}
@@ -792,66 +802,127 @@ You are analyzing a conversation to extract ONLY the most important, persistent
792
802
  # Current Long-Term Memories
793
803
  {{existingMemories}}
794
804
 
795
- # Memory Categories
796
- 1. **identity**: User's name, role, identity (e.g., "I'm a data scientist")
797
- 2. **expertise**: User's skills, knowledge domains, or unfamiliarity with topics
798
- 3. **projects**: Ongoing projects, past interactions, recurring topics
799
- 4. **preferences**: Communication style, format preferences, verbosity, etc.
800
- 5. **data_sources**: Frequently used files, databases, APIs
801
- 6. **goals**: Broader intentions (e.g., "preparing for interview")
802
- 7. **constraints**: User-defined rules or limitations
803
- 8. **definitions**: Custom terms, acronyms, glossaries
804
- 9. **behavioral_patterns**: How the user tends to interact
805
+ # Memory Categories (Based on Cognitive Science)
805
806
 
806
- # STRICT EXTRACTION CRITERIA
807
+ ## 1. EPISODIC Memory
808
+ Personal experiences and specific events with temporal/spatial context.
809
+ **Examples:**
810
+ - "User completed migration project from MongoDB to PostgreSQL in Q2 2024"
811
+ - "User encountered authentication bug in production on March 15th"
812
+ - "User had a negative experience with Docker networking in previous job"
807
813
 
808
- **DO EXTRACT** - Facts that are:
809
- - Explicitly stated personal information (name, role, profession)
810
- - Repeated patterns across multiple conversations (3+ occurrences)
811
- - Core preferences stated with clear emphasis ("I always prefer...", "I never want...")
812
- - Important ongoing projects or goals mentioned multiple times
813
- - Persistent technical constraints or requirements
814
- - Domain expertise demonstrated consistently
815
- - Custom terminology the user defines and uses repeatedly
814
+ **Requirements:**
815
+ - Must include WHO did WHAT, WHEN/WHERE
816
+ - Must be a specific, concrete event (not a pattern)
817
+ - Must have significant impact or relevance to future work
816
818
 
817
- **DO NOT EXTRACT** - Facts that are:
818
- - One-time requests or isolated tasks (e.g., "generate an image or similar")
819
- - Single interactions without pattern repetition
820
- - Casual preferences from single occurrences
821
- - Testing or exploratory questions
822
- - Temporary context or transient information
823
- - General courtesy or social patterns (greetings, thank yous)
824
- - Random or playful requests that don't indicate lasting preference
825
- - Information that could change or is situational
819
+ ## 2. SEMANTIC Memory
820
+ General facts, concepts, knowledge, and established truths about the user.
821
+ **Examples:**
822
+ - "User is a senior backend engineer with 8 years experience"
823
+ - "User specializes in distributed systems and microservices architecture"
824
+ - "User's primary programming language is TypeScript"
825
+ - "User works at Acme Corp as technical lead"
826
826
 
827
- # Quality Standards
828
- - **Confidence threshold**: Only extract if confidence >= 0.8
829
- - **Persistence required**: Must see evidence across multiple messages or strong explicit statement
830
- - **Meaningful value**: Would this fact improve future interactions weeks from now?
831
- - **Not redundant**: Avoid if existing memories already cover this information
827
+ **Requirements:**
828
+ - Must be factual, timeless information
829
+ - Must be explicitly stated or demonstrated conclusively
830
+ - No speculation or inference from single instances
831
+ - Core identity, expertise, or knowledge only
832
832
 
833
- # Instructions
834
- Extract ONLY truly important NEW information that meets the strict criteria above. For each item:
835
- - Determine which category it belongs to
836
- - Write a clear, factual statement
837
- - Assess confidence (0.0 to 1.0) - BE CONSERVATIVE
838
- - Require strong evidence before extraction
833
+ ## 3. PROCEDURAL Memory
834
+ Skills, workflows, methodologies, and how-to knowledge.
835
+ **Examples:**
836
+ - "User follows strict TDD workflow: write tests first, then implementation"
837
+ - "User prefers git rebase over merge to maintain linear history"
838
+ - "User's debugging process: check logs → reproduce locally → binary search"
839
+ - "User always writes JSDoc comments before implementing functions"
839
840
 
840
- **When in doubt, DO NOT extract.** It's better to miss temporary information than to clutter long-term memory.
841
+ **Requirements:**
842
+ - Must describe HOW user does something
843
+ - Must be a repeated, consistent pattern (seen 3+ times or explicitly stated as standard practice)
844
+ - Must be a workflow, methodology, or skill application
845
+ - Not one-off preferences
841
846
 
842
- If there are no new long-term facts to extract, respond with <memories></memories>
847
+ # ULTRA-STRICT EXTRACTION CRITERIA
848
+
849
+ ## ✅ DO EXTRACT (Only These):
850
+
851
+ **EPISODIC:**
852
+ - Significant completed projects or milestones
853
+ - Important bugs, incidents, or problems encountered
854
+ - Major decisions made with lasting impact
855
+ - Formative experiences that shape future work
856
+
857
+ **SEMANTIC:**
858
+ - Professional identity (role, title, company)
859
+ - Core expertise and specializations (stated explicitly or demonstrated conclusively)
860
+ - Primary languages, frameworks, or tools (not exploratory use)
861
+ - Established facts about their work context
862
+
863
+ **PROCEDURAL:**
864
+ - Consistent workflows demonstrated 3+ times or explicitly stated
865
+ - Standard practices user always follows
866
+ - Methodology preferences with clear rationale
867
+ - Debugging, testing, or development processes
868
+
869
+ ## ❌ NEVER EXTRACT:
870
+
871
+ - **One-time requests or tasks** (e.g., "can you generate an image", "help me debug this")
872
+ - **Casual conversations** without lasting significance
873
+ - **Exploratory questions** (e.g., "how does X work?")
874
+ - **Temporary context** (current bug, today's task)
875
+ - **Preferences from single occurrence** (e.g., user asked for code once)
876
+ - **Social pleasantries** (thank you, greetings)
877
+ - **Testing or experimentation** (trying out a feature)
878
+ - **Common patterns everyone has** (likes clear explanations)
879
+ - **Situational information** (working on feature X today)
880
+ - **Opinions without persistence** (single complaint, isolated praise)
881
+ - **General knowledge** (not specific to user)
882
+
883
+ # Quality Gates (ALL Must Pass)
884
+
885
+ 1. **Significance Test**: Will this matter in 3+ months?
886
+ 2. **Specificity Test**: Is this concrete and actionable?
887
+ 3. **Evidence Test**: Is there strong evidence (3+ instances OR explicit self-identification)?
888
+ 4. **Uniqueness Test**: Is this specific to THIS user (not generic)?
889
+ 5. **Confidence Test**: Confidence must be >= 0.85 (be VERY conservative)
890
+ 6. **Non-Redundancy Test**: Does this add NEW information not in existing memories?
891
+
892
+ # Confidence Scoring (Be Conservative)
893
+
894
+ - **0.95-1.0**: User explicitly stated as core identity/practice AND demonstrated multiple times
895
+ - **0.85-0.94**: User explicitly stated OR consistently demonstrated 5+ times
896
+ - **0.75-0.84**: Strong pattern (3-4 instances) with supporting context
897
+ - **Below 0.75**: DO NOT EXTRACT (insufficient evidence)
898
+
899
+ # Critical Instructions
900
+
901
+ 1. **Default to NOT extracting** - When in doubt, skip it
902
+ 2. **Require overwhelming evidence** - One or two mentions is NOT enough
903
+ 3. **Focus on what's PERSISTENT** - Not what's temporary or situational
904
+ 4. **Verify against existing memories** - Don't duplicate or contradict
905
+ 5. **Maximum 2-3 extractions per run** - Quality over quantity
906
+
907
+ **If there are no qualifying facts (which is common), respond with <memories></memories>**
908
+
909
+ # Response Format
843
910
 
844
- Respond in this XML format:
845
911
  <memories>
846
912
  <memory>
847
- <category>identity</category>
848
- <content>User is a software engineer specializing in backend development</content>
913
+ <category>semantic</category>
914
+ <content>User is a senior TypeScript developer with 8 years of backend experience</content>
849
915
  <confidence>0.95</confidence>
850
916
  </memory>
851
917
  <memory>
852
- <category>preferences</category>
853
- <content>Prefers code examples over lengthy explanations</content>
854
- <confidence>0.85</confidence>
918
+ <category>procedural</category>
919
+ <content>User follows TDD workflow: writes tests before implementation, runs tests after each change</content>
920
+ <confidence>0.88</confidence>
921
+ </memory>
922
+ <memory>
923
+ <category>episodic</category>
924
+ <content>User led database migration from MongoDB to PostgreSQL for payment system in Q2 2024</content>
925
+ <confidence>0.92</confidence>
855
926
  </memory>
856
927
  </memories>`;
857
928
  function parseMemoryExtractionXML(xml) {
@@ -940,7 +1011,7 @@ var longTermExtractionEvaluator = {
940
1011
  const extractions = parseMemoryExtractionXML(response);
941
1012
  logger3.info(`Extracted ${extractions.length} long-term memories`);
942
1013
  for (const extraction of extractions) {
943
- if (extraction.confidence >= config.longTermConfidenceThreshold) {
1014
+ if (extraction.confidence >= Math.max(config.longTermConfidenceThreshold, 0.85)) {
944
1015
  await memoryService.storeLongTermMemory({
945
1016
  agentId: runtime.agentId,
946
1017
  entityId,
@@ -955,7 +1026,7 @@ var longTermExtractionEvaluator = {
955
1026
  });
956
1027
  logger3.info(`Stored long-term memory: [${extraction.category}] ${extraction.content.substring(0, 50)}...`);
957
1028
  } else {
958
- logger3.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence})`);
1029
+ logger3.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence}, threshold: ${Math.max(config.longTermConfidenceThreshold, 0.85)})`);
959
1030
  }
960
1031
  }
961
1032
  const currentMessageCount = await runtime.countMemories(roomId, false, "messages");
@@ -968,244 +1039,10 @@ var longTermExtractionEvaluator = {
968
1039
  examples: []
969
1040
  };
970
1041
 
971
- // src/providers/short-term-memory.ts
972
- import {
973
- addHeader,
974
- ChannelType,
975
- formatMessages,
976
- formatPosts,
977
- getEntityDetails,
978
- logger as logger4
979
- } from "@elizaos/core";
980
- var shortTermMemoryProvider = {
981
- name: "SHORT_TERM_MEMORY",
982
- description: "Adaptive conversation context with smart summarization",
983
- position: 95,
984
- get: async (runtime, message, _state) => {
985
- try {
986
- const memoryService = runtime.getService("memory");
987
- if (!memoryService) {
988
- return {
989
- data: { summaries: [], recentMessages: [], mode: "disabled" },
990
- values: {},
991
- text: ""
992
- };
993
- }
994
- const { roomId } = message;
995
- const config = memoryService.getConfig();
996
- const totalMessageCount = await runtime.countMemories(roomId, false, "messages");
997
- if (totalMessageCount < config.shortTermSummarizationThreshold) {
998
- const conversationLength = runtime.getConversationLength();
999
- const [entitiesData, room, recentMessagesData] = await Promise.all([
1000
- getEntityDetails({ runtime, roomId }),
1001
- runtime.getRoom(roomId),
1002
- runtime.getMemories({
1003
- tableName: "messages",
1004
- roomId,
1005
- count: conversationLength,
1006
- unique: false
1007
- })
1008
- ]);
1009
- const actionResultMessages = recentMessagesData.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
1010
- const dialogueMessages = recentMessagesData.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
1011
- const isPostFormat = room?.type ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD : false;
1012
- const [formattedRecentMessages, formattedRecentPosts] = await Promise.all([
1013
- formatMessages({
1014
- messages: dialogueMessages,
1015
- entities: entitiesData
1016
- }),
1017
- formatPosts({
1018
- messages: dialogueMessages,
1019
- entities: entitiesData,
1020
- conversationHeader: false
1021
- })
1022
- ]);
1023
- let actionResultsText = "";
1024
- if (actionResultMessages.length > 0) {
1025
- const groupedByRun = new Map;
1026
- for (const mem of actionResultMessages) {
1027
- const runId = String(mem.content?.runId || "unknown");
1028
- if (!groupedByRun.has(runId)) {
1029
- groupedByRun.set(runId, []);
1030
- }
1031
- groupedByRun.get(runId)?.push(mem);
1032
- }
1033
- const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
1034
- const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
1035
- const thought = sortedMemories[0]?.content?.planThought || "";
1036
- const runText = sortedMemories.map((mem) => {
1037
- const actionName = mem.content?.actionName || "Unknown";
1038
- const status = mem.content?.actionStatus || "unknown";
1039
- const planStep = mem.content?.planStep || "";
1040
- const text5 = mem.content?.text || "";
1041
- const error = mem.content?.error || "";
1042
- let memText = ` - ${actionName} (${status})`;
1043
- if (planStep)
1044
- memText += ` [${planStep}]`;
1045
- if (error) {
1046
- memText += `: Error - ${error}`;
1047
- } else if (text5 && text5 !== `Executed action: ${actionName}`) {
1048
- memText += `: ${text5}`;
1049
- }
1050
- return memText;
1051
- }).join(`
1052
- `);
1053
- return `**Action Run ${runId.slice(0, 8)}**${thought ? ` - "${thought}"` : ""}
1054
- ${runText}`;
1055
- }).join(`
1056
-
1057
- `);
1058
- actionResultsText = formattedActionResults ? addHeader("# Recent Action Executions", formattedActionResults) : "";
1059
- }
1060
- const recentPosts = formattedRecentPosts && formattedRecentPosts.length > 0 ? addHeader("# Posts in Thread", formattedRecentPosts) : "";
1061
- const recentMessages = formattedRecentMessages && formattedRecentMessages.length > 0 ? addHeader("# Conversation Messages", formattedRecentMessages) : "";
1062
- if (!recentPosts && !recentMessages && dialogueMessages.length === 0 && !message.content.text) {
1063
- return {
1064
- data: {
1065
- summaries: [],
1066
- recentMessages: [],
1067
- actionResults: [],
1068
- mode: "full_conversation"
1069
- },
1070
- values: {
1071
- recentMessage: "No recent message available."
1072
- },
1073
- text: "No recent messages available"
1074
- };
1075
- }
1076
- let recentMessage = "No recent message available.";
1077
- if (dialogueMessages.length > 0) {
1078
- const mostRecentMessage = [...dialogueMessages].sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0))[0];
1079
- const formattedSingleMessage = formatMessages({
1080
- messages: [mostRecentMessage],
1081
- entities: entitiesData
1082
- });
1083
- if (formattedSingleMessage) {
1084
- recentMessage = formattedSingleMessage;
1085
- }
1086
- }
1087
- const metaData = message.metadata;
1088
- const senderName = entitiesData.find((entity) => entity.id === message.entityId)?.names[0] || metaData?.entityName || "Unknown User";
1089
- const receivedMessageContent = message.content.text;
1090
- const hasReceivedMessage = !!receivedMessageContent?.trim();
1091
- const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1092
- const focusHeader = hasReceivedMessage ? 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.`) : "";
1093
- const text4 = [
1094
- isPostFormat ? recentPosts : recentMessages,
1095
- actionResultsText,
1096
- recentMessages || recentPosts || message.content.text ? receivedMessageHeader : "",
1097
- recentMessages || recentPosts || message.content.text ? focusHeader : ""
1098
- ].filter(Boolean).join(`
1099
-
1100
- `);
1101
- return {
1102
- data: {
1103
- summaries: [],
1104
- recentMessages: dialogueMessages,
1105
- actionResults: actionResultMessages,
1106
- mode: "full_conversation"
1107
- },
1108
- values: {
1109
- ...(isPostFormat ? recentPosts : recentMessages) && {
1110
- recentMessages: isPostFormat ? recentPosts : recentMessages
1111
- },
1112
- ...recentPosts && { recentPosts },
1113
- ...actionResultsText && { recentActionResults: actionResultsText },
1114
- ...recentMessage && { recentMessage },
1115
- ...receivedMessageHeader && { receivedMessageHeader },
1116
- ...focusHeader && { focusHeader }
1117
- },
1118
- text: text4
1119
- };
1120
- } else {
1121
- const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1122
- const lastOffset = currentSummary?.lastMessageOffset || 0;
1123
- const unsummarizedMessages = await runtime.getMemories({
1124
- tableName: "messages",
1125
- roomId,
1126
- count: config.shortTermRetainRecent,
1127
- unique: false,
1128
- start: lastOffset
1129
- });
1130
- const entitiesData = await getEntityDetails({ runtime, roomId });
1131
- const room = await runtime.getRoom(roomId);
1132
- const isPostFormat = room?.type ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD : false;
1133
- let recentMessagesText = "";
1134
- if (unsummarizedMessages.length > 0) {
1135
- const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
1136
- if (isPostFormat) {
1137
- recentMessagesText = formatPosts({
1138
- messages: dialogueMessages,
1139
- entities: entitiesData,
1140
- conversationHeader: false
1141
- });
1142
- } else {
1143
- recentMessagesText = formatMessages({
1144
- messages: dialogueMessages,
1145
- entities: entitiesData
1146
- });
1147
- }
1148
- if (recentMessagesText) {
1149
- recentMessagesText = addHeader("# Recent Messages", recentMessagesText);
1150
- }
1151
- }
1152
- let summaryText = "";
1153
- if (currentSummary) {
1154
- const messageRange = `${currentSummary.messageCount} messages`;
1155
- const timeRange = new Date(currentSummary.startTime).toLocaleDateString();
1156
- summaryText = `**Previous Conversation** (${messageRange}, ${timeRange})
1157
- `;
1158
- summaryText += currentSummary.summary;
1159
- if (currentSummary.topics && currentSummary.topics.length > 0) {
1160
- summaryText += `
1161
- *Topics: ${currentSummary.topics.join(", ")}*`;
1162
- }
1163
- summaryText = addHeader("# Conversation Summary", summaryText);
1164
- }
1165
- const metaData = message.metadata;
1166
- const senderName = entitiesData.find((entity) => entity.id === message.entityId)?.names[0] || metaData?.entityName || "Unknown User";
1167
- const receivedMessageContent = message.content.text;
1168
- const hasReceivedMessage = !!receivedMessageContent?.trim();
1169
- const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1170
- const focusHeader = hasReceivedMessage ? addHeader("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`) : "";
1171
- const text4 = [
1172
- summaryText,
1173
- recentMessagesText,
1174
- hasReceivedMessage ? receivedMessageHeader : "",
1175
- hasReceivedMessage ? focusHeader : ""
1176
- ].filter(Boolean).join(`
1177
-
1178
- `);
1179
- return {
1180
- data: {
1181
- summaries: currentSummary ? [currentSummary] : [],
1182
- recentMessages: unsummarizedMessages,
1183
- mode: "summarized"
1184
- },
1185
- values: {
1186
- ...summaryText && { sessionSummaries: summaryText },
1187
- ...recentMessagesText && { recentMessages: recentMessagesText },
1188
- ...receivedMessageHeader && { receivedMessageHeader },
1189
- ...focusHeader && { focusHeader }
1190
- },
1191
- text: text4
1192
- };
1193
- }
1194
- } catch (error) {
1195
- logger4.error({ error }, "Error in shortTermMemoryProvider:");
1196
- return {
1197
- data: { summaries: [], recentMessages: [], mode: "error" },
1198
- values: {},
1199
- text: "Error retrieving conversation context."
1200
- };
1201
- }
1202
- }
1203
- };
1204
-
1205
1042
  // src/providers/long-term-memory.ts
1206
1043
  import {
1207
- logger as logger5,
1208
- addHeader as addHeader2
1044
+ logger as logger4,
1045
+ addHeader
1209
1046
  } from "@elizaos/core";
1210
1047
  var longTermMemoryProvider = {
1211
1048
  name: "LONG_TERM_MEMORY",
@@ -1238,7 +1075,7 @@ var longTermMemoryProvider = {
1238
1075
  };
1239
1076
  }
1240
1077
  const formattedMemories = await memoryService.getFormattedLongTermMemories(entityId);
1241
- const text4 = addHeader2("# What I Know About You", formattedMemories);
1078
+ const text4 = addHeader("# What I Know About You", formattedMemories);
1242
1079
  const categoryCounts = new Map;
1243
1080
  for (const memory of memories) {
1244
1081
  const count = categoryCounts.get(memory.category) || 0;
@@ -1257,7 +1094,7 @@ var longTermMemoryProvider = {
1257
1094
  text: text4
1258
1095
  };
1259
1096
  } catch (error) {
1260
- logger5.error({ error }, "Error in longTermMemoryProvider:");
1097
+ logger4.error({ error }, "Error in longTermMemoryProvider:");
1261
1098
  return {
1262
1099
  data: { memories: [] },
1263
1100
  values: { longTermMemories: "" },
@@ -1267,24 +1104,237 @@ var longTermMemoryProvider = {
1267
1104
  }
1268
1105
  };
1269
1106
 
1107
+ // src/providers/context-summary.ts
1108
+ import {
1109
+ addHeader as addHeader2,
1110
+ logger as logger5
1111
+ } from "@elizaos/core";
1112
+ var contextSummaryProvider = {
1113
+ name: "SUMMARIZED_CONTEXT",
1114
+ description: "Provides summarized context from previous conversations",
1115
+ position: 96,
1116
+ get: async (runtime, message, _state) => {
1117
+ try {
1118
+ const memoryService = runtime.getService("memory");
1119
+ const { roomId } = message;
1120
+ if (!memoryService) {
1121
+ return {
1122
+ data: {
1123
+ summary: null
1124
+ },
1125
+ values: {
1126
+ sessionSummaries: "",
1127
+ sessionSummariesWithTopics: ""
1128
+ },
1129
+ text: ""
1130
+ };
1131
+ }
1132
+ const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1133
+ if (!currentSummary) {
1134
+ return {
1135
+ data: {
1136
+ summary: null
1137
+ },
1138
+ values: {
1139
+ sessionSummaries: "",
1140
+ sessionSummariesWithTopics: ""
1141
+ },
1142
+ text: ""
1143
+ };
1144
+ }
1145
+ const messageRange = `${currentSummary.messageCount} messages`;
1146
+ const timeRange = new Date(currentSummary.startTime).toLocaleDateString();
1147
+ let summaryOnly = `**Previous Conversation** (${messageRange}, ${timeRange})
1148
+ `;
1149
+ summaryOnly += currentSummary.summary;
1150
+ let summaryWithTopics = summaryOnly;
1151
+ if (currentSummary.topics && currentSummary.topics.length > 0) {
1152
+ summaryWithTopics += `
1153
+ *Topics: ${currentSummary.topics.join(", ")}*`;
1154
+ }
1155
+ const sessionSummaries2 = addHeader2("# Conversation Summary", summaryOnly);
1156
+ const sessionSummariesWithTopics = addHeader2("# Conversation Summary", summaryWithTopics);
1157
+ return {
1158
+ data: {
1159
+ summary: currentSummary
1160
+ },
1161
+ values: {
1162
+ sessionSummaries: sessionSummaries2,
1163
+ sessionSummariesWithTopics
1164
+ },
1165
+ text: sessionSummariesWithTopics
1166
+ };
1167
+ } catch (error) {
1168
+ logger5.error({ error }, "Error in contextSummaryProvider:");
1169
+ return {
1170
+ data: {
1171
+ summary: null
1172
+ },
1173
+ values: {
1174
+ sessionSummaries: "",
1175
+ sessionSummariesWithTopics: ""
1176
+ },
1177
+ text: ""
1178
+ };
1179
+ }
1180
+ }
1181
+ };
1182
+
1183
+ // src/providers/recent-messages.ts
1184
+ import {
1185
+ addHeader as addHeader3,
1186
+ ChannelType,
1187
+ formatMessages,
1188
+ formatPosts,
1189
+ getEntityDetails,
1190
+ logger as logger6
1191
+ } from "@elizaos/core";
1192
+ var recentMessagesProvider = {
1193
+ name: "RECENT_MESSAGES",
1194
+ description: "Provides recent conversation messages with detailed context",
1195
+ position: 94,
1196
+ get: async (runtime, message, _state) => {
1197
+ try {
1198
+ const memoryService = runtime.getService("memory");
1199
+ const { roomId } = message;
1200
+ const config = memoryService?.getConfig() || {
1201
+ shortTermSummarizationThreshold: 16,
1202
+ shortTermRetainRecent: 6
1203
+ };
1204
+ const conversationLength = runtime.getConversationLength();
1205
+ let messagesToFetch = config.shortTermRetainRecent;
1206
+ let startOffset = 0;
1207
+ let hasSummary = false;
1208
+ if (memoryService) {
1209
+ const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1210
+ if (currentSummary) {
1211
+ hasSummary = true;
1212
+ startOffset = currentSummary.lastMessageOffset || 0;
1213
+ }
1214
+ }
1215
+ if (!hasSummary) {
1216
+ const allMessages = await runtime.getMemories({
1217
+ tableName: "messages",
1218
+ roomId,
1219
+ count: conversationLength,
1220
+ unique: false
1221
+ });
1222
+ 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;
1223
+ if (dialogueMessageCount < config.shortTermSummarizationThreshold) {
1224
+ messagesToFetch = conversationLength;
1225
+ }
1226
+ }
1227
+ const [entitiesData, room, recentMessagesData] = await Promise.all([
1228
+ getEntityDetails({ runtime, roomId }),
1229
+ runtime.getRoom(roomId),
1230
+ runtime.getMemories({
1231
+ tableName: "messages",
1232
+ roomId,
1233
+ count: messagesToFetch,
1234
+ unique: false,
1235
+ start: startOffset
1236
+ })
1237
+ ]);
1238
+ const isPostFormat = room?.type ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD : false;
1239
+ 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"));
1240
+ let recentMessagesText = "";
1241
+ if (dialogueMessages.length > 0) {
1242
+ if (isPostFormat) {
1243
+ recentMessagesText = formatPosts({
1244
+ messages: dialogueMessages,
1245
+ entities: entitiesData,
1246
+ conversationHeader: false
1247
+ });
1248
+ } else {
1249
+ recentMessagesText = formatMessages({
1250
+ messages: dialogueMessages,
1251
+ entities: entitiesData
1252
+ });
1253
+ }
1254
+ if (recentMessagesText) {
1255
+ recentMessagesText = addHeader3("# Recent Messages", recentMessagesText);
1256
+ }
1257
+ }
1258
+ const formatConversationLog = (messages, includeThoughts) => {
1259
+ return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
1260
+ const entity = entitiesData.find((e) => e.id === msg.entityId);
1261
+ const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
1262
+ const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
1263
+ const text5 = msg.content.text || "";
1264
+ const thought = includeThoughts && msg.content.internalMonologue ? `
1265
+ [Internal thought: ${msg.content.internalMonologue}]` : "";
1266
+ return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
1267
+ }).join(`
1268
+ `);
1269
+ };
1270
+ const conversationLog = addHeader3("# Conversation Messages", formatConversationLog(dialogueMessages, false));
1271
+ const conversationLogWithAgentThoughts = addHeader3("# Conversation Messages", formatConversationLog(dialogueMessages, true));
1272
+ const metaData = message.metadata;
1273
+ const senderName = entitiesData.find((entity) => entity.id === message.entityId)?.names[0] || metaData?.entityName || "Unknown User";
1274
+ const receivedMessageContent = message.content.text;
1275
+ const hasReceivedMessage = !!receivedMessageContent?.trim();
1276
+ const receivedMessageHeader = hasReceivedMessage ? addHeader3("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1277
+ const focusHeader = hasReceivedMessage ? addHeader3("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`) : "";
1278
+ const text4 = [recentMessagesText, receivedMessageHeader, focusHeader].filter(Boolean).join(`
1279
+
1280
+ `);
1281
+ return {
1282
+ data: {
1283
+ messages: dialogueMessages
1284
+ },
1285
+ values: {
1286
+ recentMessages: recentMessagesText,
1287
+ conversationLog,
1288
+ conversationLogWithAgentThoughts,
1289
+ ...receivedMessageHeader && { receivedMessageHeader },
1290
+ ...focusHeader && { focusHeader }
1291
+ },
1292
+ text: text4
1293
+ };
1294
+ } catch (error) {
1295
+ logger6.error({ error }, "Error in recentMessagesProvider:");
1296
+ return {
1297
+ data: {
1298
+ messages: []
1299
+ },
1300
+ values: {
1301
+ recentMessages: "",
1302
+ conversationLog: "",
1303
+ conversationLogWithAgentThoughts: "",
1304
+ receivedMessageHeader: "",
1305
+ focusHeader: ""
1306
+ },
1307
+ text: ""
1308
+ };
1309
+ }
1310
+ }
1311
+ };
1312
+
1270
1313
  // src/index.ts
1271
1314
  var memoryPlugin = {
1272
1315
  name: "memory",
1273
1316
  description: "Advanced memory management with conversation summarization and long-term persistent memory",
1274
1317
  services: [MemoryService],
1275
1318
  evaluators: [summarizationEvaluator, longTermExtractionEvaluator],
1276
- providers: [longTermMemoryProvider, shortTermMemoryProvider],
1319
+ providers: [
1320
+ longTermMemoryProvider,
1321
+ contextSummaryProvider,
1322
+ recentMessagesProvider
1323
+ ],
1277
1324
  schema: exports_schemas
1278
1325
  };
1279
1326
  var src_default = memoryPlugin;
1280
1327
  export {
1281
1328
  sessionSummaries,
1329
+ recentMessagesProvider,
1282
1330
  memoryPlugin,
1283
1331
  memoryAccessLogs,
1332
+ longTermMemoryProvider,
1284
1333
  longTermMemories,
1285
1334
  src_default as default,
1335
+ contextSummaryProvider,
1286
1336
  MemoryService,
1287
1337
  LongTermMemoryCategory
1288
1338
  };
1289
1339
 
1290
- //# debugId=374CC1B0E70335CE64756E2164756E21
1340
+ //# debugId=755CC91A4D2723F764756E2164756E21