@elizaos/plugin-memory 1.0.5 → 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.
@@ -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
@@ -770,21 +770,15 @@ import {
770
770
  // src/types/index.ts
771
771
  var LongTermMemoryCategory;
772
772
  ((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";
773
+ LongTermMemoryCategory2["EPISODIC"] = "episodic";
774
+ LongTermMemoryCategory2["SEMANTIC"] = "semantic";
775
+ LongTermMemoryCategory2["PROCEDURAL"] = "procedural";
782
776
  })(LongTermMemoryCategory ||= {});
783
777
 
784
778
  // src/evaluators/long-term-extraction.ts
785
- var extractionTemplate = `# Task: Extract Long-Term Memory
779
+ var extractionTemplate = `# Task: Extract Long-Term Memory (Strict Criteria)
786
780
 
787
- You are analyzing a conversation to extract ONLY the most important, persistent facts about the user that should be remembered long-term.
781
+ You are analyzing a conversation to extract ONLY the most critical, persistent information about the user using cognitive science memory categories.
788
782
 
789
783
  # Recent Messages
790
784
  {{recentMessages}}
@@ -792,66 +786,127 @@ You are analyzing a conversation to extract ONLY the most important, persistent
792
786
  # Current Long-Term Memories
793
787
  {{existingMemories}}
794
788
 
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
789
+ # Memory Categories (Based on Cognitive Science)
805
790
 
806
- # STRICT EXTRACTION CRITERIA
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"
807
797
 
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
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
816
802
 
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
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"
826
810
 
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
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
832
816
 
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
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"
839
824
 
840
- **When in doubt, DO NOT extract.** It's better to miss temporary information than to clutter long-term memory.
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
841
830
 
842
- If there are no new long-term facts to extract, respond with <memories></memories>
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
843
894
 
844
- Respond in this XML format:
845
895
  <memories>
846
896
  <memory>
847
- <category>identity</category>
848
- <content>User is a software engineer specializing in backend development</content>
897
+ <category>semantic</category>
898
+ <content>User is a senior TypeScript developer with 8 years of backend experience</content>
849
899
  <confidence>0.95</confidence>
850
900
  </memory>
851
901
  <memory>
852
- <category>preferences</category>
853
- <content>Prefers code examples over lengthy explanations</content>
854
- <confidence>0.85</confidence>
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>
855
910
  </memory>
856
911
  </memories>`;
857
912
  function parseMemoryExtractionXML(xml) {
@@ -940,7 +995,7 @@ var longTermExtractionEvaluator = {
940
995
  const extractions = parseMemoryExtractionXML(response);
941
996
  logger3.info(`Extracted ${extractions.length} long-term memories`);
942
997
  for (const extraction of extractions) {
943
- if (extraction.confidence >= config.longTermConfidenceThreshold) {
998
+ if (extraction.confidence >= Math.max(config.longTermConfidenceThreshold, 0.85)) {
944
999
  await memoryService.storeLongTermMemory({
945
1000
  agentId: runtime.agentId,
946
1001
  entityId,
@@ -955,7 +1010,7 @@ var longTermExtractionEvaluator = {
955
1010
  });
956
1011
  logger3.info(`Stored long-term memory: [${extraction.category}] ${extraction.content.substring(0, 50)}...`);
957
1012
  } else {
958
- 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)})`);
959
1014
  }
960
1015
  }
961
1016
  const currentMessageCount = await runtime.countMemories(roomId, false, "messages");
@@ -977,26 +1032,31 @@ import {
977
1032
  getEntityDetails,
978
1033
  logger as logger4
979
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
+ };
980
1043
  var shortTermMemoryProvider = {
981
1044
  name: "SHORT_TERM_MEMORY",
982
- description: "Adaptive conversation context with smart summarization",
1045
+ description: "Unified conversation context with smart summarization and interactions",
983
1046
  position: 95,
984
1047
  get: async (runtime, message, _state) => {
985
1048
  try {
986
1049
  const memoryService = runtime.getService("memory");
987
- if (!memoryService) {
988
- return {
989
- data: { summaries: [], recentMessages: [], mode: "disabled" },
990
- values: {},
991
- text: ""
992
- };
993
- }
994
1050
  const { roomId } = message;
995
- const config = memoryService.getConfig();
1051
+ const conversationLength = 16;
1052
+ const config = memoryService?.getConfig() || {
1053
+ shortTermSummarizationThreshold: 16,
1054
+ shortTermRetainRecent: 6
1055
+ };
996
1056
  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([
1057
+ const useSummarization = memoryService && totalMessageCount >= config.shortTermSummarizationThreshold;
1058
+ if (!useSummarization) {
1059
+ const [entitiesData, room, recentMessagesData, recentInteractionsData] = await Promise.all([
1000
1060
  getEntityDetails({ runtime, roomId }),
1001
1061
  runtime.getRoom(roomId),
1002
1062
  runtime.getMemories({
@@ -1004,7 +1064,8 @@ var shortTermMemoryProvider = {
1004
1064
  roomId,
1005
1065
  count: conversationLength,
1006
1066
  unique: false
1007
- })
1067
+ }),
1068
+ message.entityId !== runtime.agentId ? getRecentInteractions(runtime, message.entityId, runtime.agentId, roomId) : Promise.resolve([])
1008
1069
  ]);
1009
1070
  const actionResultMessages = recentMessagesData.filter((msg) => msg.content?.type === "action_result" && msg.metadata?.type === "action_result");
1010
1071
  const dialogueMessages = recentMessagesData.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
@@ -1020,6 +1081,20 @@ var shortTermMemoryProvider = {
1020
1081
  conversationHeader: false
1021
1082
  })
1022
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);
1023
1098
  let actionResultsText = "";
1024
1099
  if (actionResultMessages.length > 0) {
1025
1100
  const groupedByRun = new Map;
@@ -1028,7 +1103,10 @@ var shortTermMemoryProvider = {
1028
1103
  if (!groupedByRun.has(runId)) {
1029
1104
  groupedByRun.set(runId, []);
1030
1105
  }
1031
- groupedByRun.get(runId)?.push(mem);
1106
+ const memories = groupedByRun.get(runId);
1107
+ if (memories) {
1108
+ memories.push(mem);
1109
+ }
1032
1110
  }
1033
1111
  const formattedActionResults = Array.from(groupedByRun.entries()).slice(-3).map(([runId, memories]) => {
1034
1112
  const sortedMemories = memories.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
@@ -1064,11 +1142,20 @@ ${runText}`;
1064
1142
  data: {
1065
1143
  summaries: [],
1066
1144
  recentMessages: [],
1145
+ recentInteractions: [],
1067
1146
  actionResults: [],
1068
1147
  mode: "full_conversation"
1069
1148
  },
1070
1149
  values: {
1071
- recentMessage: "No recent message available."
1150
+ recentPosts: "",
1151
+ recentMessages: "",
1152
+ recentMessageInteractions: "",
1153
+ recentPostInteractions: "",
1154
+ recentInteractions: "",
1155
+ recentActionResults: "",
1156
+ recentMessage: "No recent message available.",
1157
+ conversationLog: "",
1158
+ conversationLogWithAgentThoughts: ""
1072
1159
  },
1073
1160
  text: "No recent messages available"
1074
1161
  };
@@ -1090,6 +1177,80 @@ ${runText}`;
1090
1177
  const hasReceivedMessage = !!receivedMessageContent?.trim();
1091
1178
  const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1092
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
+ };
1093
1254
  const text4 = [
1094
1255
  isPostFormat ? recentPosts : recentMessages,
1095
1256
  actionResultsText,
@@ -1099,40 +1260,68 @@ ${runText}`;
1099
1260
 
1100
1261
  `);
1101
1262
  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
- },
1263
+ data,
1264
+ values,
1118
1265
  text: text4
1119
1266
  };
1120
1267
  } else {
1121
1268
  const currentSummary = await memoryService.getCurrentSessionSummary(roomId);
1122
1269
  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);
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
+ ]);
1132
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
+ }
1133
1323
  let recentMessagesText = "";
1134
- if (unsummarizedMessages.length > 0) {
1135
- const dialogueMessages = unsummarizedMessages.filter((msg) => !(msg.content?.type === "action_result" && msg.metadata?.type === "action_result"));
1324
+ if (dialogueMessages.length > 0) {
1136
1325
  if (isPostFormat) {
1137
1326
  recentMessagesText = formatPosts({
1138
1327
  messages: dialogueMessages,
@@ -1149,6 +1338,31 @@ ${runText}`;
1149
1338
  recentMessagesText = addHeader("# Recent Messages", recentMessagesText);
1150
1339
  }
1151
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);
1152
1366
  let summaryText = "";
1153
1367
  if (currentSummary) {
1154
1368
  const messageRange = `${currentSummary.messageCount} messages`;
@@ -1168,9 +1382,66 @@ ${runText}`;
1168
1382
  const hasReceivedMessage = !!receivedMessageContent?.trim();
1169
1383
  const receivedMessageHeader = hasReceivedMessage ? addHeader("# Received Message", `${senderName}: ${receivedMessageContent}`) : "";
1170
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
+ ]);
1171
1441
  const text4 = [
1172
1442
  summaryText,
1173
1443
  recentMessagesText,
1444
+ actionResultsText,
1174
1445
  hasReceivedMessage ? receivedMessageHeader : "",
1175
1446
  hasReceivedMessage ? focusHeader : ""
1176
1447
  ].filter(Boolean).join(`
@@ -1179,12 +1450,21 @@ ${runText}`;
1179
1450
  return {
1180
1451
  data: {
1181
1452
  summaries: currentSummary ? [currentSummary] : [],
1182
- recentMessages: unsummarizedMessages,
1453
+ recentMessages: dialogueMessages,
1454
+ recentInteractions: recentInteractionsData,
1455
+ actionResults: actionResultMessages,
1183
1456
  mode: "summarized"
1184
1457
  },
1185
1458
  values: {
1186
1459
  ...summaryText && { sessionSummaries: summaryText },
1187
1460
  ...recentMessagesText && { recentMessages: recentMessagesText },
1461
+ recentMessageInteractions,
1462
+ recentPostInteractions,
1463
+ recentInteractions: isPostFormat ? recentPostInteractions : recentMessageInteractions,
1464
+ ...actionResultsText && { recentActionResults: actionResultsText },
1465
+ recentMessage,
1466
+ conversationLog,
1467
+ conversationLogWithAgentThoughts,
1188
1468
  ...receivedMessageHeader && { receivedMessageHeader },
1189
1469
  ...focusHeader && { focusHeader }
1190
1470
  },
@@ -1194,8 +1474,23 @@ ${runText}`;
1194
1474
  } catch (error) {
1195
1475
  logger4.error({ error }, "Error in shortTermMemoryProvider:");
1196
1476
  return {
1197
- data: { summaries: [], recentMessages: [], mode: "error" },
1198
- values: {},
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
+ },
1199
1494
  text: "Error retrieving conversation context."
1200
1495
  };
1201
1496
  }
@@ -1287,4 +1582,4 @@ export {
1287
1582
  LongTermMemoryCategory
1288
1583
  };
1289
1584
 
1290
- //# debugId=374CC1B0E70335CE64756E2164756E21
1585
+ //# debugId=B1C29E71DE6182A064756E2164756E21