@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.
- package/README.md +58 -34
- package/dist/browser/index.browser.js +133 -75
- package/dist/browser/index.browser.js.map +10 -9
- package/dist/cjs/index.node.cjs +379 -332
- package/dist/cjs/index.node.js.map +10 -9
- package/dist/index.d.ts +3 -0
- package/dist/node/index.node.js +390 -340
- package/dist/node/index.node.js.map +10 -9
- package/dist/providers/context-summary.d.ts +12 -0
- package/dist/providers/recent-messages.d.ts +15 -0
- package/dist/types/index.d.ts +9 -10
- package/package.json +1 -1
- package/dist/providers/short-term-memory.d.ts +0 -19
package/dist/node/index.node.js
CHANGED
|
@@ -118,13 +118,13 @@ class MemoryService extends Service {
|
|
|
118
118
|
this.lastExtractionCheckpoints = new Map;
|
|
119
119
|
this.memoryConfig = {
|
|
120
120
|
shortTermSummarizationThreshold: 16,
|
|
121
|
-
shortTermRetainRecent:
|
|
121
|
+
shortTermRetainRecent: 6,
|
|
122
122
|
shortTermSummarizationInterval: 10,
|
|
123
123
|
longTermExtractionEnabled: true,
|
|
124
124
|
longTermVectorSearchEnabled: false,
|
|
125
|
-
longTermConfidenceThreshold: 0.
|
|
126
|
-
longTermExtractionThreshold:
|
|
127
|
-
longTermExtractionInterval:
|
|
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.
|
|
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
|
|
635
|
+
const currentDialogueCount = await getDialogueMessageCount(runtime, message.roomId);
|
|
626
636
|
const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);
|
|
627
637
|
if (!existingSummary) {
|
|
628
|
-
const shouldSummarize =
|
|
638
|
+
const shouldSummarize = currentDialogueCount >= config.shortTermSummarizationThreshold;
|
|
629
639
|
logger2.debug({
|
|
630
640
|
roomId: message.roomId,
|
|
631
|
-
|
|
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
|
|
639
|
-
const shouldUpdate =
|
|
648
|
+
const newDialogueCount = currentDialogueCount - existingSummary.lastMessageOffset;
|
|
649
|
+
const shouldUpdate = newDialogueCount >= config.shortTermSummarizationInterval;
|
|
640
650
|
logger2.debug({
|
|
641
651
|
roomId: message.roomId,
|
|
642
|
-
|
|
652
|
+
currentDialogueCount,
|
|
643
653
|
lastOffset: existingSummary.lastMessageOffset,
|
|
644
|
-
|
|
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
|
|
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:
|
|
679
|
-
unique: false
|
|
680
|
-
start: lastOffset
|
|
677
|
+
count: 1000,
|
|
678
|
+
unique: false
|
|
681
679
|
});
|
|
682
|
-
|
|
683
|
-
|
|
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
|
|
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:
|
|
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 =
|
|
723
|
-
const firstMessage =
|
|
724
|
-
const lastMessage =
|
|
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 +
|
|
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}: ${
|
|
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:
|
|
746
|
-
lastMessageOffset:
|
|
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}: ${
|
|
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["
|
|
774
|
-
LongTermMemoryCategory2["
|
|
775
|
-
LongTermMemoryCategory2["
|
|
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
|
|
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
|
-
|
|
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
|
-
**
|
|
809
|
-
-
|
|
810
|
-
-
|
|
811
|
-
-
|
|
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
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
-
|
|
821
|
-
-
|
|
822
|
-
-
|
|
823
|
-
-
|
|
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
|
-
|
|
828
|
-
-
|
|
829
|
-
-
|
|
830
|
-
-
|
|
831
|
-
-
|
|
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
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
-
|
|
837
|
-
-
|
|
838
|
-
-
|
|
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
|
-
**
|
|
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
|
-
|
|
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>
|
|
848
|
-
<content>User is a
|
|
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>
|
|
853
|
-
<content>
|
|
854
|
-
<confidence>0.
|
|
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
|
|
1208
|
-
addHeader
|
|
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 =
|
|
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
|
-
|
|
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: [
|
|
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=
|
|
1340
|
+
//# debugId=755CC91A4D2723F764756E2164756E21
|