@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.
- package/README.md +72 -31
- package/dist/browser/index.browser.js +148 -48
- package/dist/browser/index.browser.js.map +7 -7
- package/dist/cjs/index.node.cjs +493 -108
- package/dist/cjs/index.node.js.map +7 -7
- package/dist/evaluators/summarization.d.ts +13 -6
- package/dist/node/index.node.js +493 -108
- package/dist/node/index.node.js.map +7 -7
- package/dist/providers/short-term-memory.d.ts +8 -6
- package/dist/services/memory-service.d.ts +6 -3
- package/dist/types/index.d.ts +12 -10
- package/package.json +1 -1
package/dist/node/index.node.js
CHANGED
|
@@ -117,14 +117,17 @@ class MemoryService extends Service {
|
|
|
117
117
|
this.sessionMessageCounts = new Map;
|
|
118
118
|
this.lastExtractionCheckpoints = new Map;
|
|
119
119
|
this.memoryConfig = {
|
|
120
|
-
shortTermSummarizationThreshold:
|
|
121
|
-
shortTermRetainRecent:
|
|
120
|
+
shortTermSummarizationThreshold: 16,
|
|
121
|
+
shortTermRetainRecent: 6,
|
|
122
|
+
shortTermSummarizationInterval: 10,
|
|
122
123
|
longTermExtractionEnabled: true,
|
|
123
124
|
longTermVectorSearchEnabled: false,
|
|
124
|
-
longTermConfidenceThreshold: 0.
|
|
125
|
-
|
|
125
|
+
longTermConfidenceThreshold: 0.85,
|
|
126
|
+
longTermExtractionThreshold: 30,
|
|
127
|
+
longTermExtractionInterval: 10,
|
|
126
128
|
summaryModelType: "TEXT_LARGE",
|
|
127
|
-
summaryMaxTokens: 2500
|
|
129
|
+
summaryMaxTokens: 2500,
|
|
130
|
+
summaryMaxNewMessages: 20
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
static async start(runtime) {
|
|
@@ -145,6 +148,14 @@ class MemoryService extends Service {
|
|
|
145
148
|
if (retainRecent) {
|
|
146
149
|
this.memoryConfig.shortTermRetainRecent = parseInt(retainRecent, 10);
|
|
147
150
|
}
|
|
151
|
+
const summarizationInterval = runtime.getSetting("MEMORY_SUMMARIZATION_INTERVAL");
|
|
152
|
+
if (summarizationInterval) {
|
|
153
|
+
this.memoryConfig.shortTermSummarizationInterval = parseInt(summarizationInterval, 10);
|
|
154
|
+
}
|
|
155
|
+
const maxNewMessages = runtime.getSetting("MEMORY_MAX_NEW_MESSAGES");
|
|
156
|
+
if (maxNewMessages) {
|
|
157
|
+
this.memoryConfig.summaryMaxNewMessages = parseInt(maxNewMessages, 10);
|
|
158
|
+
}
|
|
148
159
|
const longTermEnabled = runtime.getSetting("MEMORY_LONG_TERM_ENABLED");
|
|
149
160
|
if (longTermEnabled === "false") {
|
|
150
161
|
this.memoryConfig.longTermExtractionEnabled = false;
|
|
@@ -155,10 +166,21 @@ class MemoryService extends Service {
|
|
|
155
166
|
if (confidenceThreshold) {
|
|
156
167
|
this.memoryConfig.longTermConfidenceThreshold = parseFloat(confidenceThreshold);
|
|
157
168
|
}
|
|
169
|
+
const extractionThreshold = runtime.getSetting("MEMORY_EXTRACTION_THRESHOLD");
|
|
170
|
+
if (extractionThreshold) {
|
|
171
|
+
this.memoryConfig.longTermExtractionThreshold = parseInt(extractionThreshold, 10);
|
|
172
|
+
}
|
|
173
|
+
const extractionInterval = runtime.getSetting("MEMORY_EXTRACTION_INTERVAL");
|
|
174
|
+
if (extractionInterval) {
|
|
175
|
+
this.memoryConfig.longTermExtractionInterval = parseInt(extractionInterval, 10);
|
|
176
|
+
}
|
|
158
177
|
logger.info({
|
|
159
178
|
summarizationThreshold: this.memoryConfig.shortTermSummarizationThreshold,
|
|
179
|
+
summarizationInterval: this.memoryConfig.shortTermSummarizationInterval,
|
|
180
|
+
maxNewMessages: this.memoryConfig.summaryMaxNewMessages,
|
|
160
181
|
retainRecent: this.memoryConfig.shortTermRetainRecent,
|
|
161
182
|
longTermEnabled: this.memoryConfig.longTermExtractionEnabled,
|
|
183
|
+
extractionThreshold: this.memoryConfig.longTermExtractionThreshold,
|
|
162
184
|
extractionInterval: this.memoryConfig.longTermExtractionInterval,
|
|
163
185
|
confidenceThreshold: this.memoryConfig.longTermConfidenceThreshold
|
|
164
186
|
}, "MemoryService initialized");
|
|
@@ -219,14 +241,26 @@ class MemoryService extends Service {
|
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
async shouldRunExtraction(entityId, roomId, currentMessageCount) {
|
|
244
|
+
const threshold = this.memoryConfig.longTermExtractionThreshold;
|
|
222
245
|
const interval = this.memoryConfig.longTermExtractionInterval;
|
|
246
|
+
if (currentMessageCount < threshold) {
|
|
247
|
+
logger.debug({
|
|
248
|
+
entityId,
|
|
249
|
+
roomId,
|
|
250
|
+
currentMessageCount,
|
|
251
|
+
threshold,
|
|
252
|
+
shouldRun: false
|
|
253
|
+
}, "Extraction check: below threshold");
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
223
256
|
const lastCheckpoint = await this.getLastExtractionCheckpoint(entityId, roomId);
|
|
224
257
|
const currentCheckpoint = Math.floor(currentMessageCount / interval) * interval;
|
|
225
|
-
const shouldRun = currentMessageCount >=
|
|
258
|
+
const shouldRun = currentMessageCount >= threshold && currentCheckpoint > lastCheckpoint;
|
|
226
259
|
logger.debug({
|
|
227
260
|
entityId,
|
|
228
261
|
roomId,
|
|
229
262
|
currentMessageCount,
|
|
263
|
+
threshold,
|
|
230
264
|
interval,
|
|
231
265
|
lastCheckpoint,
|
|
232
266
|
currentCheckpoint,
|
|
@@ -294,7 +328,7 @@ class MemoryService extends Service {
|
|
|
294
328
|
accessCount: row.accessCount
|
|
295
329
|
}));
|
|
296
330
|
}
|
|
297
|
-
async updateLongTermMemory(id, updates) {
|
|
331
|
+
async updateLongTermMemory(id, entityId, updates) {
|
|
298
332
|
const db = this.getDb();
|
|
299
333
|
const updateData = {
|
|
300
334
|
updatedAt: new Date
|
|
@@ -317,13 +351,13 @@ class MemoryService extends Service {
|
|
|
317
351
|
if (updates.accessCount !== undefined) {
|
|
318
352
|
updateData.accessCount = updates.accessCount;
|
|
319
353
|
}
|
|
320
|
-
await db.update(longTermMemories).set(updateData).where(eq(longTermMemories.id, id));
|
|
321
|
-
logger.info(`Updated long-term memory: ${id}`);
|
|
354
|
+
await db.update(longTermMemories).set(updateData).where(and(eq(longTermMemories.id, id), eq(longTermMemories.agentId, this.runtime.agentId), eq(longTermMemories.entityId, entityId)));
|
|
355
|
+
logger.info(`Updated long-term memory: ${id} for entity ${entityId}`);
|
|
322
356
|
}
|
|
323
|
-
async deleteLongTermMemory(id) {
|
|
357
|
+
async deleteLongTermMemory(id, entityId) {
|
|
324
358
|
const db = this.getDb();
|
|
325
|
-
await db.delete(longTermMemories).where(eq(longTermMemories.id, id));
|
|
326
|
-
logger.info(`Deleted long-term memory: ${id}`);
|
|
359
|
+
await db.delete(longTermMemories).where(and(eq(longTermMemories.id, id), eq(longTermMemories.agentId, this.runtime.agentId), eq(longTermMemories.entityId, entityId)));
|
|
360
|
+
logger.info(`Deleted long-term memory: ${id} for entity ${entityId}`);
|
|
327
361
|
}
|
|
328
362
|
async getCurrentSessionSummary(roomId) {
|
|
329
363
|
const db = this.getDb();
|
|
@@ -378,7 +412,7 @@ class MemoryService extends Service {
|
|
|
378
412
|
logger.info(`Stored session summary for room ${newSummary.roomId}`);
|
|
379
413
|
return newSummary;
|
|
380
414
|
}
|
|
381
|
-
async updateSessionSummary(id, updates) {
|
|
415
|
+
async updateSessionSummary(id, roomId, updates) {
|
|
382
416
|
const db = this.getDb();
|
|
383
417
|
const updateData = {
|
|
384
418
|
updatedAt: new Date
|
|
@@ -404,8 +438,8 @@ class MemoryService extends Service {
|
|
|
404
438
|
if (updates.embedding !== undefined) {
|
|
405
439
|
updateData.embedding = updates.embedding;
|
|
406
440
|
}
|
|
407
|
-
await db.update(sessionSummaries).set(updateData).where(eq(sessionSummaries.id, id));
|
|
408
|
-
logger.info(`Updated session summary: ${id}`);
|
|
441
|
+
await db.update(sessionSummaries).set(updateData).where(and(eq(sessionSummaries.id, id), eq(sessionSummaries.agentId, this.runtime.agentId), eq(sessionSummaries.roomId, roomId)));
|
|
442
|
+
logger.info(`Updated session summary: ${id} for room ${roomId}`);
|
|
409
443
|
}
|
|
410
444
|
async getSessionSummaries(roomId, limit = 5) {
|
|
411
445
|
const db = this.getDb();
|
|
@@ -589,14 +623,31 @@ var summarizationEvaluator = {
|
|
|
589
623
|
}
|
|
590
624
|
const config = memoryService.getConfig();
|
|
591
625
|
const currentMessageCount = await runtime.countMemories(message.roomId, false, "messages");
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
626
|
+
const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);
|
|
627
|
+
if (!existingSummary) {
|
|
628
|
+
const shouldSummarize = currentMessageCount >= config.shortTermSummarizationThreshold;
|
|
629
|
+
logger2.debug({
|
|
630
|
+
roomId: message.roomId,
|
|
631
|
+
currentMessageCount,
|
|
632
|
+
threshold: config.shortTermSummarizationThreshold,
|
|
633
|
+
shouldSummarize,
|
|
634
|
+
reason: "initial_summary_check"
|
|
635
|
+
}, "Summarization validation check");
|
|
636
|
+
return shouldSummarize;
|
|
637
|
+
} else {
|
|
638
|
+
const newMessageCount = currentMessageCount - existingSummary.lastMessageOffset;
|
|
639
|
+
const shouldUpdate = newMessageCount >= config.shortTermSummarizationInterval;
|
|
640
|
+
logger2.debug({
|
|
641
|
+
roomId: message.roomId,
|
|
642
|
+
currentMessageCount,
|
|
643
|
+
lastOffset: existingSummary.lastMessageOffset,
|
|
644
|
+
newMessageCount,
|
|
645
|
+
interval: config.shortTermSummarizationInterval,
|
|
646
|
+
shouldUpdate,
|
|
647
|
+
reason: "summary_update_check"
|
|
648
|
+
}, "Summarization validation check");
|
|
649
|
+
return shouldUpdate;
|
|
650
|
+
}
|
|
600
651
|
},
|
|
601
652
|
handler: async (runtime, message) => {
|
|
602
653
|
const memoryService = runtime.getService("memory");
|
|
@@ -611,15 +662,25 @@ var summarizationEvaluator = {
|
|
|
611
662
|
const existingSummary = await memoryService.getCurrentSessionSummary(roomId);
|
|
612
663
|
const lastOffset = existingSummary?.lastMessageOffset || 0;
|
|
613
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
|
+
}
|
|
614
675
|
const newMessages = await runtime.getMemories({
|
|
615
676
|
tableName: "messages",
|
|
616
677
|
roomId,
|
|
617
|
-
count:
|
|
678
|
+
count: messagesToFetch,
|
|
618
679
|
unique: false,
|
|
619
680
|
start: lastOffset
|
|
620
681
|
});
|
|
621
682
|
if (newMessages.length === 0) {
|
|
622
|
-
logger2.debug("No new messages
|
|
683
|
+
logger2.debug("No new messages retrieved");
|
|
623
684
|
return;
|
|
624
685
|
}
|
|
625
686
|
const sortedMessages = newMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
|
|
@@ -664,7 +725,7 @@ var summarizationEvaluator = {
|
|
|
664
725
|
const startTime = existingSummary ? existingSummary.startTime : firstMessage?.createdAt && firstMessage.createdAt > 0 ? new Date(firstMessage.createdAt) : new Date;
|
|
665
726
|
const endTime = lastMessage?.createdAt && lastMessage.createdAt > 0 ? new Date(lastMessage.createdAt) : new Date;
|
|
666
727
|
if (existingSummary) {
|
|
667
|
-
await memoryService.updateSessionSummary(existingSummary.id, {
|
|
728
|
+
await memoryService.updateSessionSummary(existingSummary.id, roomId, {
|
|
668
729
|
summary: summaryResult.summary,
|
|
669
730
|
messageCount: existingSummary.messageCount + sortedMessages.length,
|
|
670
731
|
lastMessageOffset: newOffset,
|
|
@@ -709,21 +770,15 @@ import {
|
|
|
709
770
|
// src/types/index.ts
|
|
710
771
|
var LongTermMemoryCategory;
|
|
711
772
|
((LongTermMemoryCategory2) => {
|
|
712
|
-
LongTermMemoryCategory2["
|
|
713
|
-
LongTermMemoryCategory2["
|
|
714
|
-
LongTermMemoryCategory2["
|
|
715
|
-
LongTermMemoryCategory2["PREFERENCES"] = "preferences";
|
|
716
|
-
LongTermMemoryCategory2["DATA_SOURCES"] = "data_sources";
|
|
717
|
-
LongTermMemoryCategory2["GOALS"] = "goals";
|
|
718
|
-
LongTermMemoryCategory2["CONSTRAINTS"] = "constraints";
|
|
719
|
-
LongTermMemoryCategory2["DEFINITIONS"] = "definitions";
|
|
720
|
-
LongTermMemoryCategory2["BEHAVIORAL_PATTERNS"] = "behavioral_patterns";
|
|
773
|
+
LongTermMemoryCategory2["EPISODIC"] = "episodic";
|
|
774
|
+
LongTermMemoryCategory2["SEMANTIC"] = "semantic";
|
|
775
|
+
LongTermMemoryCategory2["PROCEDURAL"] = "procedural";
|
|
721
776
|
})(LongTermMemoryCategory ||= {});
|
|
722
777
|
|
|
723
778
|
// src/evaluators/long-term-extraction.ts
|
|
724
|
-
var extractionTemplate = `# Task: Extract Long-Term Memory
|
|
779
|
+
var extractionTemplate = `# Task: Extract Long-Term Memory (Strict Criteria)
|
|
725
780
|
|
|
726
|
-
You are analyzing a conversation to extract
|
|
781
|
+
You are analyzing a conversation to extract ONLY the most critical, persistent information about the user using cognitive science memory categories.
|
|
727
782
|
|
|
728
783
|
# Recent Messages
|
|
729
784
|
{{recentMessages}}
|
|
@@ -731,37 +786,127 @@ You are analyzing a conversation to extract facts that should be remembered long
|
|
|
731
786
|
# Current Long-Term Memories
|
|
732
787
|
{{existingMemories}}
|
|
733
788
|
|
|
734
|
-
# Memory Categories
|
|
735
|
-
1. **identity**: User's name, role, identity (e.g., "I'm a data scientist")
|
|
736
|
-
2. **expertise**: User's skills, knowledge domains, or unfamiliarity with topics
|
|
737
|
-
3. **projects**: Ongoing projects, past interactions, recurring topics
|
|
738
|
-
4. **preferences**: Communication style, format preferences, verbosity, etc.
|
|
739
|
-
5. **data_sources**: Frequently used files, databases, APIs
|
|
740
|
-
6. **goals**: Broader intentions (e.g., "preparing for interview")
|
|
741
|
-
7. **constraints**: User-defined rules or limitations
|
|
742
|
-
8. **definitions**: Custom terms, acronyms, glossaries
|
|
743
|
-
9. **behavioral_patterns**: How the user tends to interact
|
|
789
|
+
# Memory Categories (Based on Cognitive Science)
|
|
744
790
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
-
|
|
749
|
-
-
|
|
750
|
-
-
|
|
791
|
+
## 1. EPISODIC Memory
|
|
792
|
+
Personal experiences and specific events with temporal/spatial context.
|
|
793
|
+
**Examples:**
|
|
794
|
+
- "User completed migration project from MongoDB to PostgreSQL in Q2 2024"
|
|
795
|
+
- "User encountered authentication bug in production on March 15th"
|
|
796
|
+
- "User had a negative experience with Docker networking in previous job"
|
|
751
797
|
|
|
752
|
-
|
|
798
|
+
**Requirements:**
|
|
799
|
+
- Must include WHO did WHAT, WHEN/WHERE
|
|
800
|
+
- Must be a specific, concrete event (not a pattern)
|
|
801
|
+
- Must have significant impact or relevance to future work
|
|
802
|
+
|
|
803
|
+
## 2. SEMANTIC Memory
|
|
804
|
+
General facts, concepts, knowledge, and established truths about the user.
|
|
805
|
+
**Examples:**
|
|
806
|
+
- "User is a senior backend engineer with 8 years experience"
|
|
807
|
+
- "User specializes in distributed systems and microservices architecture"
|
|
808
|
+
- "User's primary programming language is TypeScript"
|
|
809
|
+
- "User works at Acme Corp as technical lead"
|
|
810
|
+
|
|
811
|
+
**Requirements:**
|
|
812
|
+
- Must be factual, timeless information
|
|
813
|
+
- Must be explicitly stated or demonstrated conclusively
|
|
814
|
+
- No speculation or inference from single instances
|
|
815
|
+
- Core identity, expertise, or knowledge only
|
|
816
|
+
|
|
817
|
+
## 3. PROCEDURAL Memory
|
|
818
|
+
Skills, workflows, methodologies, and how-to knowledge.
|
|
819
|
+
**Examples:**
|
|
820
|
+
- "User follows strict TDD workflow: write tests first, then implementation"
|
|
821
|
+
- "User prefers git rebase over merge to maintain linear history"
|
|
822
|
+
- "User's debugging process: check logs → reproduce locally → binary search"
|
|
823
|
+
- "User always writes JSDoc comments before implementing functions"
|
|
824
|
+
|
|
825
|
+
**Requirements:**
|
|
826
|
+
- Must describe HOW user does something
|
|
827
|
+
- Must be a repeated, consistent pattern (seen 3+ times or explicitly stated as standard practice)
|
|
828
|
+
- Must be a workflow, methodology, or skill application
|
|
829
|
+
- Not one-off preferences
|
|
830
|
+
|
|
831
|
+
# ULTRA-STRICT EXTRACTION CRITERIA
|
|
832
|
+
|
|
833
|
+
## ✅ DO EXTRACT (Only These):
|
|
834
|
+
|
|
835
|
+
**EPISODIC:**
|
|
836
|
+
- Significant completed projects or milestones
|
|
837
|
+
- Important bugs, incidents, or problems encountered
|
|
838
|
+
- Major decisions made with lasting impact
|
|
839
|
+
- Formative experiences that shape future work
|
|
840
|
+
|
|
841
|
+
**SEMANTIC:**
|
|
842
|
+
- Professional identity (role, title, company)
|
|
843
|
+
- Core expertise and specializations (stated explicitly or demonstrated conclusively)
|
|
844
|
+
- Primary languages, frameworks, or tools (not exploratory use)
|
|
845
|
+
- Established facts about their work context
|
|
846
|
+
|
|
847
|
+
**PROCEDURAL:**
|
|
848
|
+
- Consistent workflows demonstrated 3+ times or explicitly stated
|
|
849
|
+
- Standard practices user always follows
|
|
850
|
+
- Methodology preferences with clear rationale
|
|
851
|
+
- Debugging, testing, or development processes
|
|
852
|
+
|
|
853
|
+
## ❌ NEVER EXTRACT:
|
|
854
|
+
|
|
855
|
+
- **One-time requests or tasks** (e.g., "can you generate an image", "help me debug this")
|
|
856
|
+
- **Casual conversations** without lasting significance
|
|
857
|
+
- **Exploratory questions** (e.g., "how does X work?")
|
|
858
|
+
- **Temporary context** (current bug, today's task)
|
|
859
|
+
- **Preferences from single occurrence** (e.g., user asked for code once)
|
|
860
|
+
- **Social pleasantries** (thank you, greetings)
|
|
861
|
+
- **Testing or experimentation** (trying out a feature)
|
|
862
|
+
- **Common patterns everyone has** (likes clear explanations)
|
|
863
|
+
- **Situational information** (working on feature X today)
|
|
864
|
+
- **Opinions without persistence** (single complaint, isolated praise)
|
|
865
|
+
- **General knowledge** (not specific to user)
|
|
866
|
+
|
|
867
|
+
# Quality Gates (ALL Must Pass)
|
|
868
|
+
|
|
869
|
+
1. **Significance Test**: Will this matter in 3+ months?
|
|
870
|
+
2. **Specificity Test**: Is this concrete and actionable?
|
|
871
|
+
3. **Evidence Test**: Is there strong evidence (3+ instances OR explicit self-identification)?
|
|
872
|
+
4. **Uniqueness Test**: Is this specific to THIS user (not generic)?
|
|
873
|
+
5. **Confidence Test**: Confidence must be >= 0.85 (be VERY conservative)
|
|
874
|
+
6. **Non-Redundancy Test**: Does this add NEW information not in existing memories?
|
|
875
|
+
|
|
876
|
+
# Confidence Scoring (Be Conservative)
|
|
877
|
+
|
|
878
|
+
- **0.95-1.0**: User explicitly stated as core identity/practice AND demonstrated multiple times
|
|
879
|
+
- **0.85-0.94**: User explicitly stated OR consistently demonstrated 5+ times
|
|
880
|
+
- **0.75-0.84**: Strong pattern (3-4 instances) with supporting context
|
|
881
|
+
- **Below 0.75**: DO NOT EXTRACT (insufficient evidence)
|
|
882
|
+
|
|
883
|
+
# Critical Instructions
|
|
884
|
+
|
|
885
|
+
1. **Default to NOT extracting** - When in doubt, skip it
|
|
886
|
+
2. **Require overwhelming evidence** - One or two mentions is NOT enough
|
|
887
|
+
3. **Focus on what's PERSISTENT** - Not what's temporary or situational
|
|
888
|
+
4. **Verify against existing memories** - Don't duplicate or contradict
|
|
889
|
+
5. **Maximum 2-3 extractions per run** - Quality over quantity
|
|
890
|
+
|
|
891
|
+
**If there are no qualifying facts (which is common), respond with <memories></memories>**
|
|
892
|
+
|
|
893
|
+
# Response Format
|
|
753
894
|
|
|
754
|
-
Respond in this XML format:
|
|
755
895
|
<memories>
|
|
756
896
|
<memory>
|
|
757
|
-
<category>
|
|
758
|
-
<content>User is a
|
|
897
|
+
<category>semantic</category>
|
|
898
|
+
<content>User is a senior TypeScript developer with 8 years of backend experience</content>
|
|
759
899
|
<confidence>0.95</confidence>
|
|
760
900
|
</memory>
|
|
761
901
|
<memory>
|
|
762
|
-
<category>
|
|
763
|
-
<content>
|
|
764
|
-
<confidence>0.
|
|
902
|
+
<category>procedural</category>
|
|
903
|
+
<content>User follows TDD workflow: writes tests before implementation, runs tests after each change</content>
|
|
904
|
+
<confidence>0.88</confidence>
|
|
905
|
+
</memory>
|
|
906
|
+
<memory>
|
|
907
|
+
<category>episodic</category>
|
|
908
|
+
<content>User led database migration from MongoDB to PostgreSQL for payment system in Q2 2024</content>
|
|
909
|
+
<confidence>0.92</confidence>
|
|
765
910
|
</memory>
|
|
766
911
|
</memories>`;
|
|
767
912
|
function parseMemoryExtractionXML(xml) {
|
|
@@ -850,7 +995,7 @@ var longTermExtractionEvaluator = {
|
|
|
850
995
|
const extractions = parseMemoryExtractionXML(response);
|
|
851
996
|
logger3.info(`Extracted ${extractions.length} long-term memories`);
|
|
852
997
|
for (const extraction of extractions) {
|
|
853
|
-
if (extraction.confidence >= config.longTermConfidenceThreshold) {
|
|
998
|
+
if (extraction.confidence >= Math.max(config.longTermConfidenceThreshold, 0.85)) {
|
|
854
999
|
await memoryService.storeLongTermMemory({
|
|
855
1000
|
agentId: runtime.agentId,
|
|
856
1001
|
entityId,
|
|
@@ -865,7 +1010,7 @@ var longTermExtractionEvaluator = {
|
|
|
865
1010
|
});
|
|
866
1011
|
logger3.info(`Stored long-term memory: [${extraction.category}] ${extraction.content.substring(0, 50)}...`);
|
|
867
1012
|
} else {
|
|
868
|
-
logger3.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence})`);
|
|
1013
|
+
logger3.debug(`Skipped low-confidence memory: ${extraction.content} (confidence: ${extraction.confidence}, threshold: ${Math.max(config.longTermConfidenceThreshold, 0.85)})`);
|
|
869
1014
|
}
|
|
870
1015
|
}
|
|
871
1016
|
const currentMessageCount = await runtime.countMemories(roomId, false, "messages");
|
|
@@ -887,26 +1032,31 @@ import {
|
|
|
887
1032
|
getEntityDetails,
|
|
888
1033
|
logger as logger4
|
|
889
1034
|
} from "@elizaos/core";
|
|
1035
|
+
var getRecentInteractions = async (runtime, sourceEntityId, targetEntityId, excludeRoomId) => {
|
|
1036
|
+
const rooms = await runtime.getRoomsForParticipants([sourceEntityId, targetEntityId]);
|
|
1037
|
+
return runtime.getMemoriesByRoomIds({
|
|
1038
|
+
tableName: "messages",
|
|
1039
|
+
roomIds: rooms.filter((room) => room !== excludeRoomId),
|
|
1040
|
+
limit: 20
|
|
1041
|
+
});
|
|
1042
|
+
};
|
|
890
1043
|
var shortTermMemoryProvider = {
|
|
891
1044
|
name: "SHORT_TERM_MEMORY",
|
|
892
|
-
description: "
|
|
1045
|
+
description: "Unified conversation context with smart summarization and interactions",
|
|
893
1046
|
position: 95,
|
|
894
1047
|
get: async (runtime, message, _state) => {
|
|
895
1048
|
try {
|
|
896
1049
|
const memoryService = runtime.getService("memory");
|
|
897
|
-
if (!memoryService) {
|
|
898
|
-
return {
|
|
899
|
-
data: { summaries: [], recentMessages: [], mode: "disabled" },
|
|
900
|
-
values: {},
|
|
901
|
-
text: ""
|
|
902
|
-
};
|
|
903
|
-
}
|
|
904
1050
|
const { roomId } = message;
|
|
905
|
-
const
|
|
1051
|
+
const conversationLength = 16;
|
|
1052
|
+
const config = memoryService?.getConfig() || {
|
|
1053
|
+
shortTermSummarizationThreshold: 16,
|
|
1054
|
+
shortTermRetainRecent: 6
|
|
1055
|
+
};
|
|
906
1056
|
const totalMessageCount = await runtime.countMemories(roomId, false, "messages");
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
const [entitiesData, room, recentMessagesData] = await Promise.all([
|
|
1057
|
+
const useSummarization = memoryService && totalMessageCount >= config.shortTermSummarizationThreshold;
|
|
1058
|
+
if (!useSummarization) {
|
|
1059
|
+
const [entitiesData, room, recentMessagesData, recentInteractionsData] = await Promise.all([
|
|
910
1060
|
getEntityDetails({ runtime, roomId }),
|
|
911
1061
|
runtime.getRoom(roomId),
|
|
912
1062
|
runtime.getMemories({
|
|
@@ -914,7 +1064,8 @@ var shortTermMemoryProvider = {
|
|
|
914
1064
|
roomId,
|
|
915
1065
|
count: conversationLength,
|
|
916
1066
|
unique: false
|
|
917
|
-
})
|
|
1067
|
+
}),
|
|
1068
|
+
message.entityId !== runtime.agentId ? getRecentInteractions(runtime, message.entityId, runtime.agentId, roomId) : Promise.resolve([])
|
|
918
1069
|
]);
|
|
919
1070
|
const actionResultMessages = recentMessagesData.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
|
|
920
1071
|
const dialogueMessages = recentMessagesData.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
|
|
@@ -930,6 +1081,20 @@ var shortTermMemoryProvider = {
|
|
|
930
1081
|
conversationHeader: false
|
|
931
1082
|
})
|
|
932
1083
|
]);
|
|
1084
|
+
const formatConversationLog = (messages, includeThoughts) => {
|
|
1085
|
+
return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
|
|
1086
|
+
const entity = entitiesData.find((e) => e.id === msg.entityId);
|
|
1087
|
+
const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
|
|
1088
|
+
const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
|
|
1089
|
+
const text5 = msg.content.text || "";
|
|
1090
|
+
const thought = includeThoughts && msg.content.internalMonologue ? `
|
|
1091
|
+
[Internal thought: ${msg.content.internalMonologue}]` : "";
|
|
1092
|
+
return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
|
|
1093
|
+
}).join(`
|
|
1094
|
+
`);
|
|
1095
|
+
};
|
|
1096
|
+
const conversationLog = formatConversationLog(dialogueMessages, false);
|
|
1097
|
+
const conversationLogWithAgentThoughts = formatConversationLog(dialogueMessages, true);
|
|
933
1098
|
let actionResultsText = "";
|
|
934
1099
|
if (actionResultMessages.length > 0) {
|
|
935
1100
|
const groupedByRun = new Map;
|
|
@@ -938,7 +1103,10 @@ var shortTermMemoryProvider = {
|
|
|
938
1103
|
if (!groupedByRun.has(runId)) {
|
|
939
1104
|
groupedByRun.set(runId, []);
|
|
940
1105
|
}
|
|
941
|
-
groupedByRun.get(runId)
|
|
1106
|
+
const memories = groupedByRun.get(runId);
|
|
1107
|
+
if (memories) {
|
|
1108
|
+
memories.push(mem);
|
|
1109
|
+
}
|
|
942
1110
|
}
|
|
943
1111
|
const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
|
|
944
1112
|
const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
|
|
@@ -974,11 +1142,20 @@ ${runText}`;
|
|
|
974
1142
|
data: {
|
|
975
1143
|
summaries: [],
|
|
976
1144
|
recentMessages: [],
|
|
1145
|
+
recentInteractions: [],
|
|
977
1146
|
actionResults: [],
|
|
978
1147
|
mode: "full_conversation"
|
|
979
1148
|
},
|
|
980
1149
|
values: {
|
|
981
|
-
|
|
1150
|
+
recentPosts: "",
|
|
1151
|
+
recentMessages: "",
|
|
1152
|
+
recentMessageInteractions: "",
|
|
1153
|
+
recentPostInteractions: "",
|
|
1154
|
+
recentInteractions: "",
|
|
1155
|
+
recentActionResults: "",
|
|
1156
|
+
recentMessage: "No recent message available.",
|
|
1157
|
+
conversationLog: "",
|
|
1158
|
+
conversationLogWithAgentThoughts: ""
|
|
982
1159
|
},
|
|
983
1160
|
text: "No recent messages available"
|
|
984
1161
|
};
|
|
@@ -1000,6 +1177,80 @@ ${runText}`;
|
|
|
1000
1177
|
const hasReceivedMessage = !!receivedMessageContent?.trim();
|
|
1001
1178
|
const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
|
|
1002
1179
|
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.`) : "";
|
|
1180
|
+
const interactionEntityMap = new Map;
|
|
1181
|
+
if (recentInteractionsData.length > 0) {
|
|
1182
|
+
const uniqueEntityIds = [
|
|
1183
|
+
...new Set(recentInteractionsData.map((message2) => message2.entityId).filter((id) => id !== runtime.agentId))
|
|
1184
|
+
];
|
|
1185
|
+
const uniqueEntityIdSet = new Set(uniqueEntityIds);
|
|
1186
|
+
const entitiesDataIdSet = new Set;
|
|
1187
|
+
entitiesData.forEach((entity) => {
|
|
1188
|
+
if (uniqueEntityIdSet.has(entity.id)) {
|
|
1189
|
+
interactionEntityMap.set(entity.id, entity);
|
|
1190
|
+
entitiesDataIdSet.add(entity.id);
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
const remainingEntityIds = uniqueEntityIds.filter((id) => !entitiesDataIdSet.has(id));
|
|
1194
|
+
if (remainingEntityIds.length > 0) {
|
|
1195
|
+
const entities = await Promise.all(remainingEntityIds.map((entityId) => runtime.getEntityById(entityId)));
|
|
1196
|
+
entities.forEach((entity, index4) => {
|
|
1197
|
+
if (entity) {
|
|
1198
|
+
interactionEntityMap.set(remainingEntityIds[index4], entity);
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
const getRecentMessageInteractions = async (recentInteractionsData2) => {
|
|
1204
|
+
const formattedInteractions = recentInteractionsData2.map((message2) => {
|
|
1205
|
+
const isSelf = message2.entityId === runtime.agentId;
|
|
1206
|
+
let sender;
|
|
1207
|
+
if (isSelf) {
|
|
1208
|
+
sender = runtime.character.name;
|
|
1209
|
+
} else {
|
|
1210
|
+
sender = interactionEntityMap.get(message2.entityId)?.metadata?.userName || "unknown";
|
|
1211
|
+
}
|
|
1212
|
+
return `${sender}: ${message2.content.text}`;
|
|
1213
|
+
});
|
|
1214
|
+
return formattedInteractions.join(`
|
|
1215
|
+
`);
|
|
1216
|
+
};
|
|
1217
|
+
const getRecentPostInteractions = async (recentInteractionsData2, entities) => {
|
|
1218
|
+
const combinedEntities = [...entities];
|
|
1219
|
+
const actorIds = new Set(entities.map((entity) => entity.id));
|
|
1220
|
+
for (const [id, entity] of interactionEntityMap.entries()) {
|
|
1221
|
+
if (!actorIds.has(id)) {
|
|
1222
|
+
combinedEntities.push(entity);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
const formattedInteractions = formatPosts({
|
|
1226
|
+
messages: recentInteractionsData2,
|
|
1227
|
+
entities: combinedEntities,
|
|
1228
|
+
conversationHeader: true
|
|
1229
|
+
});
|
|
1230
|
+
return formattedInteractions;
|
|
1231
|
+
};
|
|
1232
|
+
const [recentMessageInteractions, recentPostInteractions] = await Promise.all([
|
|
1233
|
+
getRecentMessageInteractions(recentInteractionsData),
|
|
1234
|
+
getRecentPostInteractions(recentInteractionsData, entitiesData)
|
|
1235
|
+
]);
|
|
1236
|
+
const data = {
|
|
1237
|
+
summaries: [],
|
|
1238
|
+
recentMessages: dialogueMessages,
|
|
1239
|
+
recentInteractions: recentInteractionsData,
|
|
1240
|
+
actionResults: actionResultMessages,
|
|
1241
|
+
mode: "full_conversation"
|
|
1242
|
+
};
|
|
1243
|
+
const values = {
|
|
1244
|
+
recentPosts,
|
|
1245
|
+
recentMessages,
|
|
1246
|
+
recentMessageInteractions,
|
|
1247
|
+
recentPostInteractions,
|
|
1248
|
+
recentInteractions: isPostFormat ? recentPostInteractions : recentMessageInteractions,
|
|
1249
|
+
recentActionResults: actionResultsText,
|
|
1250
|
+
recentMessage,
|
|
1251
|
+
conversationLog,
|
|
1252
|
+
conversationLogWithAgentThoughts
|
|
1253
|
+
};
|
|
1003
1254
|
const text4 = [
|
|
1004
1255
|
isPostFormat ? recentPosts : recentMessages,
|
|
1005
1256
|
actionResultsText,
|
|
@@ -1009,40 +1260,68 @@ ${runText}`;
|
|
|
1009
1260
|
|
|
1010
1261
|
`);
|
|
1011
1262
|
return {
|
|
1012
|
-
data
|
|
1013
|
-
|
|
1014
|
-
recentMessages: dialogueMessages,
|
|
1015
|
-
actionResults: actionResultMessages,
|
|
1016
|
-
mode: "full_conversation"
|
|
1017
|
-
},
|
|
1018
|
-
values: {
|
|
1019
|
-
...(isPostFormat ? recentPosts : recentMessages) && {
|
|
1020
|
-
recentMessages: isPostFormat ? recentPosts : recentMessages
|
|
1021
|
-
},
|
|
1022
|
-
...recentPosts && { recentPosts },
|
|
1023
|
-
...actionResultsText && { recentActionResults: actionResultsText },
|
|
1024
|
-
...recentMessage && { recentMessage },
|
|
1025
|
-
...receivedMessageHeader && { receivedMessageHeader },
|
|
1026
|
-
...focusHeader && { focusHeader }
|
|
1027
|
-
},
|
|
1263
|
+
data,
|
|
1264
|
+
values,
|
|
1028
1265
|
text: text4
|
|
1029
1266
|
};
|
|
1030
1267
|
} else {
|
|
1031
1268
|
const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
|
|
1032
1269
|
const lastOffset = currentSummary?.lastMessageOffset || 0;
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
roomId,
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1270
|
+
const recentCount = config.shortTermRetainRecent;
|
|
1271
|
+
const [entitiesData, room, unsummarizedMessages, recentInteractionsData] = await Promise.all([
|
|
1272
|
+
getEntityDetails({ runtime, roomId }),
|
|
1273
|
+
runtime.getRoom(roomId),
|
|
1274
|
+
runtime.getMemories({
|
|
1275
|
+
tableName: "messages",
|
|
1276
|
+
roomId,
|
|
1277
|
+
count: recentCount,
|
|
1278
|
+
unique: false,
|
|
1279
|
+
start: lastOffset
|
|
1280
|
+
}),
|
|
1281
|
+
message.entityId !== runtime.agentId ? getRecentInteractions(runtime, message.entityId, runtime.agentId, roomId) : Promise.resolve([])
|
|
1282
|
+
]);
|
|
1042
1283
|
const isPostFormat = room?.type ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD : false;
|
|
1284
|
+
const actionResultMessages = unsummarizedMessages.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
|
|
1285
|
+
const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
|
|
1286
|
+
let actionResultsText = "";
|
|
1287
|
+
if (actionResultMessages.length > 0) {
|
|
1288
|
+
const groupedByRun = new Map;
|
|
1289
|
+
for (const mem of actionResultMessages) {
|
|
1290
|
+
const runId = String(mem.content?.runId || "unknown");
|
|
1291
|
+
if (!groupedByRun.has(runId)) {
|
|
1292
|
+
groupedByRun.set(runId, []);
|
|
1293
|
+
}
|
|
1294
|
+
groupedByRun.get(runId)?.push(mem);
|
|
1295
|
+
}
|
|
1296
|
+
const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
|
|
1297
|
+
const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
|
|
1298
|
+
const thought = sortedMemories[0]?.content?.planThought || "";
|
|
1299
|
+
const runText = sortedMemories.map((mem) => {
|
|
1300
|
+
const actionName = mem.content?.actionName || "Unknown";
|
|
1301
|
+
const status = mem.content?.actionStatus || "unknown";
|
|
1302
|
+
const planStep = mem.content?.planStep || "";
|
|
1303
|
+
const text5 = mem.content?.text || "";
|
|
1304
|
+
const error = mem.content?.error || "";
|
|
1305
|
+
let memText = ` - ${actionName} (${status})`;
|
|
1306
|
+
if (planStep)
|
|
1307
|
+
memText += ` [${planStep}]`;
|
|
1308
|
+
if (error) {
|
|
1309
|
+
memText += `: Error - ${error}`;
|
|
1310
|
+
} else if (text5 && text5 !== `Executed action: ${actionName}`) {
|
|
1311
|
+
memText += `: ${text5}`;
|
|
1312
|
+
}
|
|
1313
|
+
return memText;
|
|
1314
|
+
}).join(`
|
|
1315
|
+
`);
|
|
1316
|
+
return `**Action Run ${runId.slice(0, 8)}**${thought ? ` - "${thought}"` : ""}
|
|
1317
|
+
${runText}`;
|
|
1318
|
+
}).join(`
|
|
1319
|
+
|
|
1320
|
+
`);
|
|
1321
|
+
actionResultsText = formattedActionResults ? addHeader("# Recent Action Executions", formattedActionResults) : "";
|
|
1322
|
+
}
|
|
1043
1323
|
let recentMessagesText = "";
|
|
1044
|
-
if (
|
|
1045
|
-
const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
|
|
1324
|
+
if (dialogueMessages.length > 0) {
|
|
1046
1325
|
if (isPostFormat) {
|
|
1047
1326
|
recentMessagesText = formatPosts({
|
|
1048
1327
|
messages: dialogueMessages,
|
|
@@ -1059,6 +1338,31 @@ ${runText}`;
|
|
|
1059
1338
|
recentMessagesText = addHeader("# Recent Messages", recentMessagesText);
|
|
1060
1339
|
}
|
|
1061
1340
|
}
|
|
1341
|
+
let recentMessage = "No recent message available.";
|
|
1342
|
+
if (dialogueMessages.length > 0) {
|
|
1343
|
+
const mostRecentMessage = [...dialogueMessages].sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0))[0];
|
|
1344
|
+
const formattedSingleMessage = formatMessages({
|
|
1345
|
+
messages: [mostRecentMessage],
|
|
1346
|
+
entities: entitiesData
|
|
1347
|
+
});
|
|
1348
|
+
if (formattedSingleMessage) {
|
|
1349
|
+
recentMessage = formattedSingleMessage;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
const formatConversationLog = (messages, includeThoughts) => {
|
|
1353
|
+
return messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)).map((msg) => {
|
|
1354
|
+
const entity = entitiesData.find((e) => e.id === msg.entityId);
|
|
1355
|
+
const entityName = entity?.names[0] || (msg.entityId === runtime.agentId ? runtime.character.name : "Unknown");
|
|
1356
|
+
const timestamp4 = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : "Unknown time";
|
|
1357
|
+
const text5 = msg.content.text || "";
|
|
1358
|
+
const thought = includeThoughts && msg.content.internalMonologue ? `
|
|
1359
|
+
[Internal thought: ${msg.content.internalMonologue}]` : "";
|
|
1360
|
+
return `[${timestamp4}] ${entityName}: ${text5}${thought}`;
|
|
1361
|
+
}).join(`
|
|
1362
|
+
`);
|
|
1363
|
+
};
|
|
1364
|
+
const conversationLog = formatConversationLog(dialogueMessages, false);
|
|
1365
|
+
const conversationLogWithAgentThoughts = formatConversationLog(dialogueMessages, true);
|
|
1062
1366
|
let summaryText = "";
|
|
1063
1367
|
if (currentSummary) {
|
|
1064
1368
|
const messageRange = `${currentSummary.messageCount} messages`;
|
|
@@ -1078,9 +1382,66 @@ ${runText}`;
|
|
|
1078
1382
|
const hasReceivedMessage = !!receivedMessageContent?.trim();
|
|
1079
1383
|
const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
|
|
1080
1384
|
const focusHeader = hasReceivedMessage ? addHeader("# Focus your response", `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`) : "";
|
|
1385
|
+
const interactionEntityMap = new Map;
|
|
1386
|
+
if (recentInteractionsData.length > 0) {
|
|
1387
|
+
const uniqueEntityIds = [
|
|
1388
|
+
...new Set(recentInteractionsData.map((message2) => message2.entityId).filter((id) => id !== runtime.agentId))
|
|
1389
|
+
];
|
|
1390
|
+
const uniqueEntityIdSet = new Set(uniqueEntityIds);
|
|
1391
|
+
const entitiesDataIdSet = new Set;
|
|
1392
|
+
entitiesData.forEach((entity) => {
|
|
1393
|
+
if (uniqueEntityIdSet.has(entity.id)) {
|
|
1394
|
+
interactionEntityMap.set(entity.id, entity);
|
|
1395
|
+
entitiesDataIdSet.add(entity.id);
|
|
1396
|
+
}
|
|
1397
|
+
});
|
|
1398
|
+
const remainingEntityIds = uniqueEntityIds.filter((id) => !entitiesDataIdSet.has(id));
|
|
1399
|
+
if (remainingEntityIds.length > 0) {
|
|
1400
|
+
const entities = await Promise.all(remainingEntityIds.map((entityId) => runtime.getEntityById(entityId)));
|
|
1401
|
+
entities.forEach((entity, index4) => {
|
|
1402
|
+
if (entity) {
|
|
1403
|
+
interactionEntityMap.set(remainingEntityIds[index4], entity);
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
const getRecentMessageInteractions = async (recentInteractionsData2) => {
|
|
1409
|
+
const formattedInteractions = recentInteractionsData2.map((message2) => {
|
|
1410
|
+
const isSelf = message2.entityId === runtime.agentId;
|
|
1411
|
+
let sender;
|
|
1412
|
+
if (isSelf) {
|
|
1413
|
+
sender = runtime.character.name;
|
|
1414
|
+
} else {
|
|
1415
|
+
sender = interactionEntityMap.get(message2.entityId)?.metadata?.userName || "unknown";
|
|
1416
|
+
}
|
|
1417
|
+
return `${sender}: ${message2.content.text}`;
|
|
1418
|
+
});
|
|
1419
|
+
return formattedInteractions.join(`
|
|
1420
|
+
`);
|
|
1421
|
+
};
|
|
1422
|
+
const getRecentPostInteractions = async (recentInteractionsData2, entities) => {
|
|
1423
|
+
const combinedEntities = [...entities];
|
|
1424
|
+
const actorIds = new Set(entities.map((entity) => entity.id));
|
|
1425
|
+
for (const [id, entity] of interactionEntityMap.entries()) {
|
|
1426
|
+
if (!actorIds.has(id)) {
|
|
1427
|
+
combinedEntities.push(entity);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
const formattedInteractions = formatPosts({
|
|
1431
|
+
messages: recentInteractionsData2,
|
|
1432
|
+
entities: combinedEntities,
|
|
1433
|
+
conversationHeader: true
|
|
1434
|
+
});
|
|
1435
|
+
return formattedInteractions;
|
|
1436
|
+
};
|
|
1437
|
+
const [recentMessageInteractions, recentPostInteractions] = await Promise.all([
|
|
1438
|
+
getRecentMessageInteractions(recentInteractionsData),
|
|
1439
|
+
getRecentPostInteractions(recentInteractionsData, entitiesData)
|
|
1440
|
+
]);
|
|
1081
1441
|
const text4 = [
|
|
1082
1442
|
summaryText,
|
|
1083
1443
|
recentMessagesText,
|
|
1444
|
+
actionResultsText,
|
|
1084
1445
|
hasReceivedMessage ? receivedMessageHeader : "",
|
|
1085
1446
|
hasReceivedMessage ? focusHeader : ""
|
|
1086
1447
|
].filter(Boolean).join(`
|
|
@@ -1089,12 +1450,21 @@ ${runText}`;
|
|
|
1089
1450
|
return {
|
|
1090
1451
|
data: {
|
|
1091
1452
|
summaries: currentSummary ? [currentSummary] : [],
|
|
1092
|
-
recentMessages:
|
|
1453
|
+
recentMessages: dialogueMessages,
|
|
1454
|
+
recentInteractions: recentInteractionsData,
|
|
1455
|
+
actionResults: actionResultMessages,
|
|
1093
1456
|
mode: "summarized"
|
|
1094
1457
|
},
|
|
1095
1458
|
values: {
|
|
1096
1459
|
...summaryText && { sessionSummaries: summaryText },
|
|
1097
1460
|
...recentMessagesText && { recentMessages: recentMessagesText },
|
|
1461
|
+
recentMessageInteractions,
|
|
1462
|
+
recentPostInteractions,
|
|
1463
|
+
recentInteractions: isPostFormat ? recentPostInteractions : recentMessageInteractions,
|
|
1464
|
+
...actionResultsText && { recentActionResults: actionResultsText },
|
|
1465
|
+
recentMessage,
|
|
1466
|
+
conversationLog,
|
|
1467
|
+
conversationLogWithAgentThoughts,
|
|
1098
1468
|
...receivedMessageHeader && { receivedMessageHeader },
|
|
1099
1469
|
...focusHeader && { focusHeader }
|
|
1100
1470
|
},
|
|
@@ -1104,8 +1474,23 @@ ${runText}`;
|
|
|
1104
1474
|
} catch (error) {
|
|
1105
1475
|
logger4.error({ error }, "Error in shortTermMemoryProvider:");
|
|
1106
1476
|
return {
|
|
1107
|
-
data: {
|
|
1108
|
-
|
|
1477
|
+
data: {
|
|
1478
|
+
summaries: [],
|
|
1479
|
+
recentMessages: [],
|
|
1480
|
+
recentInteractions: [],
|
|
1481
|
+
actionResults: [],
|
|
1482
|
+
mode: "error"
|
|
1483
|
+
},
|
|
1484
|
+
values: {
|
|
1485
|
+
recentPosts: "",
|
|
1486
|
+
recentMessages: "",
|
|
1487
|
+
recentMessageInteractions: "",
|
|
1488
|
+
recentPostInteractions: "",
|
|
1489
|
+
recentInteractions: "",
|
|
1490
|
+
recentActionResults: "",
|
|
1491
|
+
conversationLog: "",
|
|
1492
|
+
conversationLogWithAgentThoughts: ""
|
|
1493
|
+
},
|
|
1109
1494
|
text: "Error retrieving conversation context."
|
|
1110
1495
|
};
|
|
1111
1496
|
}
|
|
@@ -1197,4 +1582,4 @@ export {
|
|
|
1197
1582
|
LongTermMemoryCategory
|
|
1198
1583
|
};
|
|
1199
1584
|
|
|
1200
|
-
//# debugId=
|
|
1585
|
+
//# debugId=B1C29E71DE6182A064756E2164756E21
|