@elizaos/plugin-memory 1.0.3 → 1.0.5

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 CHANGED
@@ -58,12 +58,16 @@ Configure the plugin via environment variables in your `.env` file:
58
58
 
59
59
  ```env
60
60
  # Short-term Memory Settings
61
- MEMORY_SUMMARIZATION_THRESHOLD=50 # Messages before summarization (default: 50)
62
- MEMORY_RETAIN_RECENT=10 # Recent messages to keep (default: 10)
61
+ MEMORY_SUMMARIZATION_THRESHOLD=16 # Messages before summarization starts (default: 16)
62
+ MEMORY_SUMMARIZATION_INTERVAL=10 # Update summary every N messages (default: 10)
63
+ MEMORY_RETAIN_RECENT=10 # Recent messages to keep (default: 10)
64
+ MEMORY_MAX_NEW_MESSAGES=20 # Max new messages in summary update (default: 20)
63
65
 
64
66
  # Long-term Memory Settings
65
- MEMORY_LONG_TERM_ENABLED=true # Enable long-term extraction (default: true)
66
- MEMORY_CONFIDENCE_THRESHOLD=0.7 # Minimum confidence to store (default: 0.7)
67
+ MEMORY_LONG_TERM_ENABLED=true # Enable long-term extraction (default: true)
68
+ MEMORY_EXTRACTION_THRESHOLD=20 # Min messages before extraction starts (default: 20)
69
+ MEMORY_EXTRACTION_INTERVAL=5 # Run extraction every N messages (default: 5)
70
+ MEMORY_CONFIDENCE_THRESHOLD=0.7 # Minimum confidence to store (default: 0.7)
67
71
  ```
68
72
 
69
73
  ### Manual Memory Storage
@@ -170,11 +174,16 @@ No manual migration is required - the schema is handled automatically by the run
170
174
 
171
175
  ### Long-term Memory Flow
172
176
 
173
- 1. **Monitoring**: longTermExtractionEvaluator runs periodically (every 10 messages)
174
- 2. **Analysis**: LLM analyzes conversation for facts worth remembering
175
- 3. **Extraction**: Identifies facts, categorizes them, assigns confidence
176
- 4. **Storage**: High-confidence facts stored in long_term_memories table
177
- 5. **Retrieval**: longTermMemoryProvider injects relevant facts in all future conversations
177
+ 1. **Warm-up Period**: Extraction waits until 20+ messages (configurable) to ensure meaningful patterns
178
+ 2. **Monitoring**: longTermExtractionEvaluator runs periodically (every 5 messages after threshold)
179
+ 3. **Analysis**: LLM analyzes conversation for **persistent, important** facts worth remembering
180
+ 4. **Strict Filtering**: Only extracts facts that show repetition or strong explicit statements
181
+ 5. **Storage**: High-confidence facts stored in long_term_memories table
182
+ 6. **Retrieval**: longTermMemoryProvider injects relevant facts in all future conversations
183
+
184
+ **Extraction Criteria**: The evaluator uses strict criteria to avoid storing trivial information:
185
+ - ✅ Extracts: Repeated patterns (3+ occurrences), explicit personal info, stated preferences
186
+ - ❌ Skips: One-time requests, casual interactions, testing behavior, temporary context
178
187
 
179
188
  ### Manual Memory Flow
180
189
 
@@ -221,10 +230,18 @@ No manual migration is required - the schema is handled automatically by the run
221
230
 
222
231
  ### Configuration Tips
223
232
 
224
- - **High-frequency chatbots**: Lower threshold (30-40 messages)
225
- - **Long-form conversations**: Higher threshold (60-100 messages)
226
- - **Critical applications**: Higher confidence threshold (0.8-0.9)
227
- - **Exploratory use**: Lower confidence threshold (0.6-0.7)
233
+ **Short-term Memory:**
234
+ - **High-frequency chatbots**: Lower summarization threshold (10-15 messages)
235
+ - **Long-form conversations**: Higher threshold (20-30 messages)
236
+ - **Adjust retention**: Keep more recent messages for immediate context
237
+
238
+ **Long-term Memory:**
239
+ - **Quick extraction**: Lower extraction threshold to 10-15 messages (may reduce quality)
240
+ - **Quality-focused**: Keep threshold at 20+ messages for better pattern recognition
241
+ - **Critical applications**: Raise confidence threshold to 0.8-0.9
242
+ - **Exploratory use**: Keep default 0.7 confidence threshold
243
+ - **Frequent updates**: Lower extraction interval to run every 3-5 messages
244
+ - **Conservative updates**: Raise interval to 10+ messages
228
245
 
229
246
  ## Advanced Features
230
247
 
@@ -1,8 +1,8 @@
1
- var zJ=Object.defineProperty;var DJ=(J,Q)=>{for(var Y in Q)zJ(J,Y,{get:Q[Y],enumerable:!0,configurable:!0,set:(W)=>Q[Y]=()=>W})};import{Service as MJ,logger as L}from"@elizaos/core";import{eq as D,and as g,desc as p,sql as GJ,cosineDistance as yJ,gte as lJ}from"drizzle-orm";var r={};DJ(r,{sessionSummaries:()=>k,memoryAccessLogs:()=>VJ,longTermMemories:()=>G});import{sql as ZJ}from"drizzle-orm";import{pgTable as RJ,text as a,integer as bJ,jsonb as CJ,real as _J,index as l,varchar as o,timestamp as m}from"drizzle-orm/pg-core";var G=RJ("long_term_memories",{id:o("id",{length:36}).primaryKey(),agentId:o("agent_id",{length:36}).notNull(),entityId:o("entity_id",{length:36}).notNull(),category:a("category").notNull(),content:a("content").notNull(),metadata:CJ("metadata"),embedding:_J("embedding").array(),confidence:_J("confidence").default(1),source:a("source"),createdAt:m("created_at").default(ZJ`now()`).notNull(),updatedAt:m("updated_at").default(ZJ`now()`).notNull(),lastAccessedAt:m("last_accessed_at"),accessCount:bJ("access_count").default(0)},(J)=>({agentEntityIdx:l("long_term_memories_agent_entity_idx").on(J.agentId,J.entityId),categoryIdx:l("long_term_memories_category_idx").on(J.category),confidenceIdx:l("long_term_memories_confidence_idx").on(J.confidence),createdAtIdx:l("long_term_memories_created_at_idx").on(J.createdAt)}));import{sql as $J}from"drizzle-orm";import{pgTable as fJ,text as hJ,integer as AJ,jsonb as UJ,real as vJ,index as s,varchar as c,timestamp as d}from"drizzle-orm/pg-core";var k=fJ("session_summaries",{id:c("id",{length:36}).primaryKey(),agentId:c("agent_id",{length:36}).notNull(),roomId:c("room_id",{length:36}).notNull(),entityId:c("entity_id",{length:36}),summary:hJ("summary").notNull(),messageCount:AJ("message_count").notNull(),lastMessageOffset:AJ("last_message_offset").notNull().default(0),startTime:d("start_time").notNull(),endTime:d("end_time").notNull(),topics:UJ("topics"),metadata:UJ("metadata"),embedding:vJ("embedding").array(),createdAt:d("created_at").default($J`now()`).notNull(),updatedAt:d("updated_at").default($J`now()`).notNull()},(J)=>({agentRoomIdx:s("session_summaries_agent_room_idx").on(J.agentId,J.roomId),entityIdx:s("session_summaries_entity_idx").on(J.entityId),startTimeIdx:s("session_summaries_start_time_idx").on(J.startTime)}));import{sql as TJ}from"drizzle-orm";import{pgTable as IJ,text as xJ,integer as SJ,real as pJ,index as t,varchar as u,timestamp as wJ}from"drizzle-orm/pg-core";var VJ=IJ("memory_access_logs",{id:u("id",{length:36}).primaryKey(),agentId:u("agent_id",{length:36}).notNull(),memoryId:u("memory_id",{length:36}).notNull(),memoryType:xJ("memory_type").notNull(),accessedAt:wJ("accessed_at").default(TJ`now()`).notNull(),roomId:u("room_id",{length:36}),relevanceScore:pJ("relevance_score"),wasUseful:SJ("was_useful")},(J)=>({memoryIdx:t("memory_access_logs_memory_idx").on(J.memoryId),agentIdx:t("memory_access_logs_agent_idx").on(J.agentId),accessedAtIdx:t("memory_access_logs_accessed_at_idx").on(J.accessedAt)}));class w extends MJ{static serviceType="memory";sessionMessageCounts;memoryConfig;lastExtractionCheckpoints;capabilityDescription="Advanced memory management with short-term summarization and long-term persistent facts";constructor(J){super(J);this.sessionMessageCounts=new Map,this.lastExtractionCheckpoints=new Map,this.memoryConfig={shortTermSummarizationThreshold:5,shortTermRetainRecent:10,longTermExtractionEnabled:!0,longTermVectorSearchEnabled:!1,longTermConfidenceThreshold:0.7,longTermExtractionInterval:5,summaryModelType:"TEXT_LARGE",summaryMaxTokens:2500}}static async start(J){let Q=new w(J);return await Q.initialize(J),Q}async stop(){L.info("MemoryService stopped")}async initialize(J){this.runtime=J;let Q=J.getSetting("MEMORY_SUMMARIZATION_THRESHOLD");if(Q)this.memoryConfig.shortTermSummarizationThreshold=parseInt(Q,10);let Y=J.getSetting("MEMORY_RETAIN_RECENT");if(Y)this.memoryConfig.shortTermRetainRecent=parseInt(Y,10);let W=J.getSetting("MEMORY_LONG_TERM_ENABLED");if(W==="false")this.memoryConfig.longTermExtractionEnabled=!1;else if(W==="true")this.memoryConfig.longTermExtractionEnabled=!0;let K=J.getSetting("MEMORY_CONFIDENCE_THRESHOLD");if(K)this.memoryConfig.longTermConfidenceThreshold=parseFloat(K);L.info({summarizationThreshold:this.memoryConfig.shortTermSummarizationThreshold,retainRecent:this.memoryConfig.shortTermRetainRecent,longTermEnabled:this.memoryConfig.longTermExtractionEnabled,extractionInterval:this.memoryConfig.longTermExtractionInterval,confidenceThreshold:this.memoryConfig.longTermConfidenceThreshold},"MemoryService initialized")}getDb(){let J=this.runtime.db;if(!J)throw Error("Database not available");return J}getConfig(){return{...this.memoryConfig}}updateConfig(J){this.memoryConfig={...this.memoryConfig,...J}}incrementMessageCount(J){let Y=(this.sessionMessageCounts.get(J)||0)+1;return this.sessionMessageCounts.set(J,Y),Y}resetMessageCount(J){this.sessionMessageCounts.set(J,0)}async shouldSummarize(J){return await this.runtime.countMemories(J,!1,"messages")>=this.memoryConfig.shortTermSummarizationThreshold}getExtractionKey(J,Q){return`memory:extraction:${J}:${Q}`}async getLastExtractionCheckpoint(J,Q){let Y=this.getExtractionKey(J,Q),W=this.lastExtractionCheckpoints.get(Y);if(W!==void 0)return W;try{let Z=await this.runtime.getCache(Y)??0;return this.lastExtractionCheckpoints.set(Y,Z),Z}catch(K){return L.warn({error:K},"Failed to get extraction checkpoint from cache"),0}}async setLastExtractionCheckpoint(J,Q,Y){let W=this.getExtractionKey(J,Q);this.lastExtractionCheckpoints.set(W,Y);try{await this.runtime.setCache(W,Y),L.debug(`Set extraction checkpoint for ${J} in room ${Q} at message count ${Y}`)}catch(K){L.error({error:K},"Failed to persist extraction checkpoint to cache")}}async shouldRunExtraction(J,Q,Y){let W=this.memoryConfig.longTermExtractionInterval,K=await this.getLastExtractionCheckpoint(J,Q),Z=Math.floor(Y/W)*W,$=Y>=W&&Z>K;return L.debug({entityId:J,roomId:Q,currentMessageCount:Y,interval:W,lastCheckpoint:K,currentCheckpoint:Z,shouldRun:$},"Extraction check"),$}async storeLongTermMemory(J){let Q=this.getDb(),Y=crypto.randomUUID(),W=new Date,K={id:Y,createdAt:W,updatedAt:W,accessCount:0,...J};try{await Q.insert(G).values({id:K.id,agentId:K.agentId,entityId:K.entityId,category:K.category,content:K.content,metadata:K.metadata||{},embedding:K.embedding,confidence:K.confidence,source:K.source,accessCount:K.accessCount,createdAt:W,updatedAt:W,lastAccessedAt:K.lastAccessedAt})}catch(Z){throw L.error({error:Z},"Failed to store long-term memory"),Z}return L.info(`Stored long-term memory: ${K.category} for entity ${K.entityId}`),K}async getLongTermMemories(J,Q,Y=10){let W=this.getDb(),K=[D(G.agentId,this.runtime.agentId),D(G.entityId,J)];if(Q)K.push(D(G.category,Q));return(await W.select().from(G).where(g(...K)).orderBy(p(G.confidence),p(G.updatedAt)).limit(Y)).map(($)=>({id:$.id,agentId:$.agentId,entityId:$.entityId,category:$.category,content:$.content,metadata:$.metadata,embedding:$.embedding,confidence:$.confidence,source:$.source,createdAt:$.createdAt,updatedAt:$.updatedAt,lastAccessedAt:$.lastAccessedAt,accessCount:$.accessCount}))}async updateLongTermMemory(J,Q){let Y=this.getDb(),W={updatedAt:new Date};if(Q.content!==void 0)W.content=Q.content;if(Q.metadata!==void 0)W.metadata=Q.metadata;if(Q.confidence!==void 0)W.confidence=Q.confidence;if(Q.embedding!==void 0)W.embedding=Q.embedding;if(Q.lastAccessedAt!==void 0)W.lastAccessedAt=Q.lastAccessedAt;if(Q.accessCount!==void 0)W.accessCount=Q.accessCount;await Y.update(G).set(W).where(D(G.id,J)),L.info(`Updated long-term memory: ${J}`)}async deleteLongTermMemory(J){await this.getDb().delete(G).where(D(G.id,J)),L.info(`Deleted long-term memory: ${J}`)}async getCurrentSessionSummary(J){let Y=await this.getDb().select().from(k).where(g(D(k.agentId,this.runtime.agentId),D(k.roomId,J))).orderBy(p(k.updatedAt)).limit(1);if(Y.length===0)return null;let W=Y[0];return{id:W.id,agentId:W.agentId,roomId:W.roomId,entityId:W.entityId,summary:W.summary,messageCount:W.messageCount,lastMessageOffset:W.lastMessageOffset,startTime:W.startTime,endTime:W.endTime,topics:W.topics||[],metadata:W.metadata,embedding:W.embedding,createdAt:W.createdAt,updatedAt:W.updatedAt}}async storeSessionSummary(J){let Q=this.getDb(),Y=crypto.randomUUID(),W=new Date,K={id:Y,createdAt:W,updatedAt:W,...J};return await Q.insert(k).values({id:K.id,agentId:K.agentId,roomId:K.roomId,entityId:K.entityId||null,summary:K.summary,messageCount:K.messageCount,lastMessageOffset:K.lastMessageOffset,startTime:K.startTime,endTime:K.endTime,topics:K.topics||[],metadata:K.metadata||{},embedding:K.embedding,createdAt:W,updatedAt:W}),L.info(`Stored session summary for room ${K.roomId}`),K}async updateSessionSummary(J,Q){let Y=this.getDb(),W={updatedAt:new Date};if(Q.summary!==void 0)W.summary=Q.summary;if(Q.messageCount!==void 0)W.messageCount=Q.messageCount;if(Q.lastMessageOffset!==void 0)W.lastMessageOffset=Q.lastMessageOffset;if(Q.endTime!==void 0)W.endTime=Q.endTime;if(Q.topics!==void 0)W.topics=Q.topics;if(Q.metadata!==void 0)W.metadata=Q.metadata;if(Q.embedding!==void 0)W.embedding=Q.embedding;await Y.update(k).set(W).where(D(k.id,J)),L.info(`Updated session summary: ${J}`)}async getSessionSummaries(J,Q=5){return(await this.getDb().select().from(k).where(g(D(k.agentId,this.runtime.agentId),D(k.roomId,J))).orderBy(p(k.updatedAt)).limit(Q)).map((K)=>({id:K.id,agentId:K.agentId,roomId:K.roomId,entityId:K.entityId,summary:K.summary,messageCount:K.messageCount,lastMessageOffset:K.lastMessageOffset,startTime:K.startTime,endTime:K.endTime,topics:K.topics||[],metadata:K.metadata,embedding:K.embedding,createdAt:K.createdAt,updatedAt:K.updatedAt}))}async searchLongTermMemories(J,Q,Y=5,W=0.7){if(!this.memoryConfig.longTermVectorSearchEnabled)return L.warn("Vector search is not enabled, falling back to recent memories"),this.getLongTermMemories(J,void 0,Y);let K=this.getDb();try{let Z=Q.map((_)=>Number.isFinite(_)?Number(_.toFixed(6)):0),$=GJ`1 - (${yJ(G.embedding,Z)})`,U=[D(G.agentId,this.runtime.agentId),D(G.entityId,J),GJ`${G.embedding} IS NOT NULL`];if(W>0)U.push(lJ($,W));return(await K.select({memory:G,similarity:$}).from(G).where(g(...U)).orderBy(p($)).limit(Y)).map((_)=>({id:_.memory.id,agentId:_.memory.agentId,entityId:_.memory.entityId,category:_.memory.category,content:_.memory.content,metadata:_.memory.metadata,embedding:_.memory.embedding,confidence:_.memory.confidence,source:_.memory.source,createdAt:_.memory.createdAt,updatedAt:_.memory.updatedAt,lastAccessedAt:_.memory.lastAccessedAt,accessCount:_.memory.accessCount,similarity:_.similarity}))}catch(Z){return L.warn({error:Z},"Vector search failed, falling back to recent memories"),this.getLongTermMemories(J,void 0,Y)}}async getFormattedLongTermMemories(J){let Q=await this.getLongTermMemories(J,void 0,20);if(Q.length===0)return"";let Y=new Map;for(let K of Q){if(!Y.has(K.category))Y.set(K.category,[]);Y.get(K.category)?.push(K)}let W=[];for(let[K,Z]of Y.entries()){let $=K.split("_").map((V)=>V.charAt(0).toUpperCase()+V.slice(1)).join(" "),U=Z.map((V)=>`- ${V.content}`).join(`
2
- `);W.push(`**${$}**:
3
- ${U}`)}return W.join(`
1
+ var DJ=Object.defineProperty;var zJ=(K,W)=>{for(var Q in W)DJ(K,Q,{get:W[Q],enumerable:!0,configurable:!0,set:(Y)=>W[Q]=()=>Y})};import{Service as MJ,logger as H}from"@elizaos/core";import{eq as E,and as I,desc as y,sql as UJ,cosineDistance as yJ,gte as lJ}from"drizzle-orm";var JJ={};zJ(JJ,{sessionSummaries:()=>k,memoryAccessLogs:()=>jJ,longTermMemories:()=>X});import{sql as $J}from"drizzle-orm";import{pgTable as RJ,text as m,integer as bJ,jsonb as fJ,real as AJ,index as u,varchar as t,timestamp as s}from"drizzle-orm/pg-core";var X=RJ("long_term_memories",{id:t("id",{length:36}).primaryKey(),agentId:t("agent_id",{length:36}).notNull(),entityId:t("entity_id",{length:36}).notNull(),category:m("category").notNull(),content:m("content").notNull(),metadata:fJ("metadata"),embedding:AJ("embedding").array(),confidence:AJ("confidence").default(1),source:m("source"),createdAt:s("created_at").default($J`now()`).notNull(),updatedAt:s("updated_at").default($J`now()`).notNull(),lastAccessedAt:s("last_accessed_at"),accessCount:bJ("access_count").default(0)},(K)=>({agentEntityIdx:u("long_term_memories_agent_entity_idx").on(K.agentId,K.entityId),categoryIdx:u("long_term_memories_category_idx").on(K.category),confidenceIdx:u("long_term_memories_confidence_idx").on(K.confidence),createdAtIdx:u("long_term_memories_created_at_idx").on(K.createdAt)}));import{sql as VJ}from"drizzle-orm";import{pgTable as CJ,text as vJ,integer as GJ,jsonb as XJ,real as TJ,index as r,varchar as g,timestamp as i}from"drizzle-orm/pg-core";var k=CJ("session_summaries",{id:g("id",{length:36}).primaryKey(),agentId:g("agent_id",{length:36}).notNull(),roomId:g("room_id",{length:36}).notNull(),entityId:g("entity_id",{length:36}),summary:vJ("summary").notNull(),messageCount:GJ("message_count").notNull(),lastMessageOffset:GJ("last_message_offset").notNull().default(0),startTime:i("start_time").notNull(),endTime:i("end_time").notNull(),topics:XJ("topics"),metadata:XJ("metadata"),embedding:TJ("embedding").array(),createdAt:i("created_at").default(VJ`now()`).notNull(),updatedAt:i("updated_at").default(VJ`now()`).notNull()},(K)=>({agentRoomIdx:r("session_summaries_agent_room_idx").on(K.agentId,K.roomId),entityIdx:r("session_summaries_entity_idx").on(K.entityId),startTimeIdx:r("session_summaries_start_time_idx").on(K.startTime)}));import{sql as hJ}from"drizzle-orm";import{pgTable as SJ,text as xJ,integer as IJ,real as pJ,index as e,varchar as n,timestamp as wJ}from"drizzle-orm/pg-core";var jJ=SJ("memory_access_logs",{id:n("id",{length:36}).primaryKey(),agentId:n("agent_id",{length:36}).notNull(),memoryId:n("memory_id",{length:36}).notNull(),memoryType:xJ("memory_type").notNull(),accessedAt:wJ("accessed_at").default(hJ`now()`).notNull(),roomId:n("room_id",{length:36}),relevanceScore:pJ("relevance_score"),wasUseful:IJ("was_useful")},(K)=>({memoryIdx:e("memory_access_logs_memory_idx").on(K.memoryId),agentIdx:e("memory_access_logs_agent_idx").on(K.agentId),accessedAtIdx:e("memory_access_logs_accessed_at_idx").on(K.accessedAt)}));class l extends MJ{static serviceType="memory";sessionMessageCounts;memoryConfig;lastExtractionCheckpoints;capabilityDescription="Advanced memory management with short-term summarization and long-term persistent facts";constructor(K){super(K);this.sessionMessageCounts=new Map,this.lastExtractionCheckpoints=new Map,this.memoryConfig={shortTermSummarizationThreshold:16,shortTermRetainRecent:10,shortTermSummarizationInterval:10,longTermExtractionEnabled:!0,longTermVectorSearchEnabled:!1,longTermConfidenceThreshold:0.7,longTermExtractionThreshold:20,longTermExtractionInterval:5,summaryModelType:"TEXT_LARGE",summaryMaxTokens:2500,summaryMaxNewMessages:20}}static async start(K){let W=new l(K);return await W.initialize(K),W}async stop(){H.info("MemoryService stopped")}async initialize(K){this.runtime=K;let W=K.getSetting("MEMORY_SUMMARIZATION_THRESHOLD");if(W)this.memoryConfig.shortTermSummarizationThreshold=parseInt(W,10);let Q=K.getSetting("MEMORY_RETAIN_RECENT");if(Q)this.memoryConfig.shortTermRetainRecent=parseInt(Q,10);let Y=K.getSetting("MEMORY_SUMMARIZATION_INTERVAL");if(Y)this.memoryConfig.shortTermSummarizationInterval=parseInt(Y,10);let J=K.getSetting("MEMORY_MAX_NEW_MESSAGES");if(J)this.memoryConfig.summaryMaxNewMessages=parseInt(J,10);let Z=K.getSetting("MEMORY_LONG_TERM_ENABLED");if(Z==="false")this.memoryConfig.longTermExtractionEnabled=!1;else if(Z==="true")this.memoryConfig.longTermExtractionEnabled=!0;let _=K.getSetting("MEMORY_CONFIDENCE_THRESHOLD");if(_)this.memoryConfig.longTermConfidenceThreshold=parseFloat(_);let A=K.getSetting("MEMORY_EXTRACTION_THRESHOLD");if(A)this.memoryConfig.longTermExtractionThreshold=parseInt(A,10);let V=K.getSetting("MEMORY_EXTRACTION_INTERVAL");if(V)this.memoryConfig.longTermExtractionInterval=parseInt(V,10);H.info({summarizationThreshold:this.memoryConfig.shortTermSummarizationThreshold,summarizationInterval:this.memoryConfig.shortTermSummarizationInterval,maxNewMessages:this.memoryConfig.summaryMaxNewMessages,retainRecent:this.memoryConfig.shortTermRetainRecent,longTermEnabled:this.memoryConfig.longTermExtractionEnabled,extractionThreshold:this.memoryConfig.longTermExtractionThreshold,extractionInterval:this.memoryConfig.longTermExtractionInterval,confidenceThreshold:this.memoryConfig.longTermConfidenceThreshold},"MemoryService initialized")}getDb(){let K=this.runtime.db;if(!K)throw Error("Database not available");return K}getConfig(){return{...this.memoryConfig}}updateConfig(K){this.memoryConfig={...this.memoryConfig,...K}}incrementMessageCount(K){let Q=(this.sessionMessageCounts.get(K)||0)+1;return this.sessionMessageCounts.set(K,Q),Q}resetMessageCount(K){this.sessionMessageCounts.set(K,0)}async shouldSummarize(K){return await this.runtime.countMemories(K,!1,"messages")>=this.memoryConfig.shortTermSummarizationThreshold}getExtractionKey(K,W){return`memory:extraction:${K}:${W}`}async getLastExtractionCheckpoint(K,W){let Q=this.getExtractionKey(K,W),Y=this.lastExtractionCheckpoints.get(Q);if(Y!==void 0)return Y;try{let Z=await this.runtime.getCache(Q)??0;return this.lastExtractionCheckpoints.set(Q,Z),Z}catch(J){return H.warn({error:J},"Failed to get extraction checkpoint from cache"),0}}async setLastExtractionCheckpoint(K,W,Q){let Y=this.getExtractionKey(K,W);this.lastExtractionCheckpoints.set(Y,Q);try{await this.runtime.setCache(Y,Q),H.debug(`Set extraction checkpoint for ${K} in room ${W} at message count ${Q}`)}catch(J){H.error({error:J},"Failed to persist extraction checkpoint to cache")}}async shouldRunExtraction(K,W,Q){let Y=this.memoryConfig.longTermExtractionThreshold,J=this.memoryConfig.longTermExtractionInterval;if(Q<Y)return H.debug({entityId:K,roomId:W,currentMessageCount:Q,threshold:Y,shouldRun:!1},"Extraction check: below threshold"),!1;let Z=await this.getLastExtractionCheckpoint(K,W),_=Math.floor(Q/J)*J,A=Q>=Y&&_>Z;return H.debug({entityId:K,roomId:W,currentMessageCount:Q,threshold:Y,interval:J,lastCheckpoint:Z,currentCheckpoint:_,shouldRun:A},"Extraction check"),A}async storeLongTermMemory(K){let W=this.getDb(),Q=crypto.randomUUID(),Y=new Date,J={id:Q,createdAt:Y,updatedAt:Y,accessCount:0,...K};try{await W.insert(X).values({id:J.id,agentId:J.agentId,entityId:J.entityId,category:J.category,content:J.content,metadata:J.metadata||{},embedding:J.embedding,confidence:J.confidence,source:J.source,accessCount:J.accessCount,createdAt:Y,updatedAt:Y,lastAccessedAt:J.lastAccessedAt})}catch(Z){throw H.error({error:Z},"Failed to store long-term memory"),Z}return H.info(`Stored long-term memory: ${J.category} for entity ${J.entityId}`),J}async getLongTermMemories(K,W,Q=10){let Y=this.getDb(),J=[E(X.agentId,this.runtime.agentId),E(X.entityId,K)];if(W)J.push(E(X.category,W));return(await Y.select().from(X).where(I(...J)).orderBy(y(X.confidence),y(X.updatedAt)).limit(Q)).map((_)=>({id:_.id,agentId:_.agentId,entityId:_.entityId,category:_.category,content:_.content,metadata:_.metadata,embedding:_.embedding,confidence:_.confidence,source:_.source,createdAt:_.createdAt,updatedAt:_.updatedAt,lastAccessedAt:_.lastAccessedAt,accessCount:_.accessCount}))}async updateLongTermMemory(K,W,Q){let Y=this.getDb(),J={updatedAt:new Date};if(Q.content!==void 0)J.content=Q.content;if(Q.metadata!==void 0)J.metadata=Q.metadata;if(Q.confidence!==void 0)J.confidence=Q.confidence;if(Q.embedding!==void 0)J.embedding=Q.embedding;if(Q.lastAccessedAt!==void 0)J.lastAccessedAt=Q.lastAccessedAt;if(Q.accessCount!==void 0)J.accessCount=Q.accessCount;await Y.update(X).set(J).where(I(E(X.id,K),E(X.agentId,this.runtime.agentId),E(X.entityId,W))),H.info(`Updated long-term memory: ${K} for entity ${W}`)}async deleteLongTermMemory(K,W){await this.getDb().delete(X).where(I(E(X.id,K),E(X.agentId,this.runtime.agentId),E(X.entityId,W))),H.info(`Deleted long-term memory: ${K} for entity ${W}`)}async getCurrentSessionSummary(K){let Q=await this.getDb().select().from(k).where(I(E(k.agentId,this.runtime.agentId),E(k.roomId,K))).orderBy(y(k.updatedAt)).limit(1);if(Q.length===0)return null;let Y=Q[0];return{id:Y.id,agentId:Y.agentId,roomId:Y.roomId,entityId:Y.entityId,summary:Y.summary,messageCount:Y.messageCount,lastMessageOffset:Y.lastMessageOffset,startTime:Y.startTime,endTime:Y.endTime,topics:Y.topics||[],metadata:Y.metadata,embedding:Y.embedding,createdAt:Y.createdAt,updatedAt:Y.updatedAt}}async storeSessionSummary(K){let W=this.getDb(),Q=crypto.randomUUID(),Y=new Date,J={id:Q,createdAt:Y,updatedAt:Y,...K};return await W.insert(k).values({id:J.id,agentId:J.agentId,roomId:J.roomId,entityId:J.entityId||null,summary:J.summary,messageCount:J.messageCount,lastMessageOffset:J.lastMessageOffset,startTime:J.startTime,endTime:J.endTime,topics:J.topics||[],metadata:J.metadata||{},embedding:J.embedding,createdAt:Y,updatedAt:Y}),H.info(`Stored session summary for room ${J.roomId}`),J}async updateSessionSummary(K,W,Q){let Y=this.getDb(),J={updatedAt:new Date};if(Q.summary!==void 0)J.summary=Q.summary;if(Q.messageCount!==void 0)J.messageCount=Q.messageCount;if(Q.lastMessageOffset!==void 0)J.lastMessageOffset=Q.lastMessageOffset;if(Q.endTime!==void 0)J.endTime=Q.endTime;if(Q.topics!==void 0)J.topics=Q.topics;if(Q.metadata!==void 0)J.metadata=Q.metadata;if(Q.embedding!==void 0)J.embedding=Q.embedding;await Y.update(k).set(J).where(I(E(k.id,K),E(k.agentId,this.runtime.agentId),E(k.roomId,W))),H.info(`Updated session summary: ${K} for room ${W}`)}async getSessionSummaries(K,W=5){return(await this.getDb().select().from(k).where(I(E(k.agentId,this.runtime.agentId),E(k.roomId,K))).orderBy(y(k.updatedAt)).limit(W)).map((J)=>({id:J.id,agentId:J.agentId,roomId:J.roomId,entityId:J.entityId,summary:J.summary,messageCount:J.messageCount,lastMessageOffset:J.lastMessageOffset,startTime:J.startTime,endTime:J.endTime,topics:J.topics||[],metadata:J.metadata,embedding:J.embedding,createdAt:J.createdAt,updatedAt:J.updatedAt}))}async searchLongTermMemories(K,W,Q=5,Y=0.7){if(!this.memoryConfig.longTermVectorSearchEnabled)return H.warn("Vector search is not enabled, falling back to recent memories"),this.getLongTermMemories(K,void 0,Q);let J=this.getDb();try{let Z=W.map(($)=>Number.isFinite($)?Number($.toFixed(6)):0),_=UJ`1 - (${yJ(X.embedding,Z)})`,A=[E(X.agentId,this.runtime.agentId),E(X.entityId,K),UJ`${X.embedding} IS NOT NULL`];if(Y>0)A.push(lJ(_,Y));return(await J.select({memory:X,similarity:_}).from(X).where(I(...A)).orderBy(y(_)).limit(Q)).map(($)=>({id:$.memory.id,agentId:$.memory.agentId,entityId:$.memory.entityId,category:$.memory.category,content:$.memory.content,metadata:$.memory.metadata,embedding:$.memory.embedding,confidence:$.memory.confidence,source:$.memory.source,createdAt:$.memory.createdAt,updatedAt:$.memory.updatedAt,lastAccessedAt:$.memory.lastAccessedAt,accessCount:$.memory.accessCount,similarity:$.similarity}))}catch(Z){return H.warn({error:Z},"Vector search failed, falling back to recent memories"),this.getLongTermMemories(K,void 0,Q)}}async getFormattedLongTermMemories(K){let W=await this.getLongTermMemories(K,void 0,20);if(W.length===0)return"";let Q=new Map;for(let J of W){if(!Q.has(J.category))Q.set(J.category,[]);Q.get(J.category)?.push(J)}let Y=[];for(let[J,Z]of Q.entries()){let _=J.split("_").map((V)=>V.charAt(0).toUpperCase()+V.slice(1)).join(" "),A=Z.map((V)=>`- ${V.content}`).join(`
2
+ `);Y.push(`**${_}**:
3
+ ${A}`)}return Y.join(`
4
4
 
5
- `)}}import{logger as R,ModelType as cJ,composePromptFromState as XJ}from"@elizaos/core";var dJ=`# Task: Summarize Conversation
5
+ `)}}import{logger as z,ModelType as cJ,composePromptFromState as BJ}from"@elizaos/core";var dJ=`# Task: Summarize Conversation
6
6
 
7
7
  You are analyzing a conversation to create a concise summary that captures the key points, topics, and important details.
8
8
 
@@ -62,10 +62,10 @@ Respond in this XML format:
62
62
  <point>First key point</point>
63
63
  <point>Second key point</point>
64
64
  </keyPoints>
65
- </summary>`;function gJ(J){let Q=J.match(/<text>([\s\S]*?)<\/text>/),Y=J.match(/<topics>([\s\S]*?)<\/topics>/),W=J.matchAll(/<point>([\s\S]*?)<\/point>/g),K=Q?Q[1].trim():"Summary not available",Z=Y?Y[1].split(",").map((U)=>U.trim()).filter(Boolean):[],$=Array.from(W).map((U)=>U[1].trim());return{summary:K,topics:Z,keyPoints:$}}var jJ={name:"MEMORY_SUMMARIZATION",description:"Automatically summarizes conversations to optimize context usage",similes:["CONVERSATION_SUMMARY","CONTEXT_COMPRESSION","MEMORY_OPTIMIZATION"],alwaysRun:!0,validate:async(J,Q)=>{if(!Q.content?.text)return R.debug("Skipping summarization: no message text"),!1;let Y=J.getService("memory");if(!Y)return R.debug("Skipping summarization: memory service not available"),!1;let W=Y.getConfig(),K=await J.countMemories(Q.roomId,!1,"messages"),Z=K>=W.shortTermSummarizationThreshold;return R.debug({roomId:Q.roomId,currentMessageCount:K,threshold:W.shortTermSummarizationThreshold,shouldSummarize:Z},"Summarization validation check"),Z},handler:async(J,Q)=>{let Y=J.getService("memory");if(!Y){R.error("MemoryService not found");return}let W=Y.getConfig(),{roomId:K}=Q;try{R.info(`Starting summarization for room ${K}`);let Z=await Y.getCurrentSessionSummary(K),$=Z?.lastMessageOffset||0,U=await J.countMemories(K,!1,"messages"),V=await J.getMemories({tableName:"messages",roomId:K,count:W.shortTermSummarizationThreshold,unique:!1,start:$});if(V.length===0){R.debug("No new messages to summarize");return}let _=V.sort((b,z)=>(b.createdAt||0)-(z.createdAt||0)),j=_.map((b)=>{return`${b.entityId===J.agentId?J.character.name:"User"}: ${b.content.text||"[non-text message]"}`}).join(`
66
- `),B=await J.composeState(Q),F,X;if(Z)X=uJ,F=XJ({state:{...B,existingSummary:Z.summary,existingTopics:Z.topics?.join(", ")||"None",newMessages:j},template:X});else X=dJ,F=XJ({state:{...B,recentMessages:j},template:X});let O=await J.useModel(cJ.TEXT_LARGE,{prompt:F,maxTokens:W.summaryMaxTokens||2500}),A=gJ(O);R.info(`${Z?"Updated":"Generated"} summary: ${A.summary.substring(0,100)}...`);let N=U,q=_[0],E=_[_.length-1],T=Z?Z.startTime:q?.createdAt&&q.createdAt>0?new Date(q.createdAt):new Date,I=E?.createdAt&&E.createdAt>0?new Date(E.createdAt):new Date;if(Z)await Y.updateSessionSummary(Z.id,{summary:A.summary,messageCount:Z.messageCount+_.length,lastMessageOffset:N,endTime:I,topics:A.topics,metadata:{keyPoints:A.keyPoints}}),R.info(`Updated summary for room ${K}: ${_.length} new messages processed (offset: ${$} → ${N})`);else await Y.storeSessionSummary({agentId:J.agentId,roomId:K,entityId:Q.entityId!==J.agentId?Q.entityId:void 0,summary:A.summary,messageCount:_.length,lastMessageOffset:N,startTime:T,endTime:I,topics:A.topics,metadata:{keyPoints:A.keyPoints}}),R.info(`Created new summary for room ${K}: ${_.length} messages summarized (offset: 0 → ${N})`)}catch(Z){R.error({error:Z},"Error during summarization:")}},examples:[]};import{logger as P,ModelType as iJ,composePromptFromState as nJ}from"@elizaos/core";var e;((_)=>{_.IDENTITY="identity";_.EXPERTISE="expertise";_.PROJECTS="projects";_.PREFERENCES="preferences";_.DATA_SOURCES="data_sources";_.GOALS="goals";_.CONSTRAINTS="constraints";_.DEFINITIONS="definitions";_.BEHAVIORAL_PATTERNS="behavioral_patterns"})(e||={});var aJ=`# Task: Extract Long-Term Memory
65
+ </summary>`;function gJ(K){let W=K.match(/<text>([\s\S]*?)<\/text>/),Q=K.match(/<topics>([\s\S]*?)<\/topics>/),Y=K.matchAll(/<point>([\s\S]*?)<\/point>/g),J=W?W[1].trim():"Summary not available",Z=Q?Q[1].split(",").map((A)=>A.trim()).filter(Boolean):[],_=Array.from(Y).map((A)=>A[1].trim());return{summary:J,topics:Z,keyPoints:_}}var OJ={name:"MEMORY_SUMMARIZATION",description:"Automatically summarizes conversations to optimize context usage",similes:["CONVERSATION_SUMMARY","CONTEXT_COMPRESSION","MEMORY_OPTIMIZATION"],alwaysRun:!0,validate:async(K,W)=>{if(!W.content?.text)return z.debug("Skipping summarization: no message text"),!1;let Q=K.getService("memory");if(!Q)return z.debug("Skipping summarization: memory service not available"),!1;let Y=Q.getConfig(),J=await K.countMemories(W.roomId,!1,"messages"),Z=await Q.getCurrentSessionSummary(W.roomId);if(!Z){let _=J>=Y.shortTermSummarizationThreshold;return z.debug({roomId:W.roomId,currentMessageCount:J,threshold:Y.shortTermSummarizationThreshold,shouldSummarize:_,reason:"initial_summary_check"},"Summarization validation check"),_}else{let _=J-Z.lastMessageOffset,A=_>=Y.shortTermSummarizationInterval;return z.debug({roomId:W.roomId,currentMessageCount:J,lastOffset:Z.lastMessageOffset,newMessageCount:_,interval:Y.shortTermSummarizationInterval,shouldUpdate:A,reason:"summary_update_check"},"Summarization validation check"),A}},handler:async(K,W)=>{let Q=K.getService("memory");if(!Q){z.error("MemoryService not found");return}let Y=Q.getConfig(),{roomId:J}=W;try{z.info(`Starting summarization for room ${J}`);let Z=await Q.getCurrentSessionSummary(J),_=Z?.lastMessageOffset||0,A=await K.countMemories(J,!1,"messages"),V=A-_,$=Y.summaryMaxNewMessages||50,F=Math.min(V,$);if(F===0){z.debug("No new messages to summarize");return}if(V>$)z.warn(`Capping new messages at ${$} (${V} available). Oldest messages will be skipped.`);let N=await K.getMemories({tableName:"messages",roomId:J,count:F,unique:!1,start:_});if(N.length===0){z.debug("No new messages retrieved");return}let j=N.sort((h,p)=>(h.createdAt||0)-(p.createdAt||0)),B=j.map((h)=>{return`${h.entityId===K.agentId?K.character.name:"User"}: ${h.content.text||"[non-text message]"}`}).join(`
66
+ `),O=await K.composeState(W),G,L;if(Z)L=uJ,G=BJ({state:{...O,existingSummary:Z.summary,existingTopics:Z.topics?.join(", ")||"None",newMessages:B},template:L});else L=dJ,G=BJ({state:{...O,recentMessages:B},template:L});let D=await K.useModel(cJ.TEXT_LARGE,{prompt:G,maxTokens:Y.summaryMaxTokens||2500}),U=gJ(D);z.info(`${Z?"Updated":"Generated"} summary: ${U.summary.substring(0,100)}...`);let R=A,C=j[0],T=j[j.length-1],b=Z?Z.startTime:C?.createdAt&&C.createdAt>0?new Date(C.createdAt):new Date,f=T?.createdAt&&T.createdAt>0?new Date(T.createdAt):new Date;if(Z)await Q.updateSessionSummary(Z.id,J,{summary:U.summary,messageCount:Z.messageCount+j.length,lastMessageOffset:R,endTime:f,topics:U.topics,metadata:{keyPoints:U.keyPoints}}),z.info(`Updated summary for room ${J}: ${j.length} new messages processed (offset: ${_} → ${R})`);else await Q.storeSessionSummary({agentId:K.agentId,roomId:J,entityId:W.entityId!==K.agentId?W.entityId:void 0,summary:U.summary,messageCount:j.length,lastMessageOffset:R,startTime:b,endTime:f,topics:U.topics,metadata:{keyPoints:U.keyPoints}}),z.info(`Created new summary for room ${J}: ${j.length} messages summarized (offset: 0 → ${R})`)}catch(Z){z.error({error:Z},"Error during summarization:")}},examples:[]};import{logger as q,ModelType as iJ,composePromptFromState as nJ}from"@elizaos/core";var KJ;(($)=>{$.IDENTITY="identity";$.EXPERTISE="expertise";$.PROJECTS="projects";$.PREFERENCES="preferences";$.DATA_SOURCES="data_sources";$.GOALS="goals";$.CONSTRAINTS="constraints";$.DEFINITIONS="definitions";$.BEHAVIORAL_PATTERNS="behavioral_patterns"})(KJ||={});var aJ=`# Task: Extract Long-Term Memory
67
67
 
68
- You are analyzing a conversation to extract facts that should be remembered long-term about the user.
68
+ You are analyzing a conversation to extract ONLY the most important, persistent facts about the user that should be remembered long-term.
69
69
 
70
70
  # Recent Messages
71
71
  {{recentMessages}}
@@ -84,12 +84,41 @@ You are analyzing a conversation to extract facts that should be remembered long
84
84
  8. **definitions**: Custom terms, acronyms, glossaries
85
85
  9. **behavioral_patterns**: How the user tends to interact
86
86
 
87
+ # STRICT EXTRACTION CRITERIA
88
+
89
+ **DO EXTRACT** - Facts that are:
90
+ - Explicitly stated personal information (name, role, profession)
91
+ - Repeated patterns across multiple conversations (3+ occurrences)
92
+ - Core preferences stated with clear emphasis ("I always prefer...", "I never want...")
93
+ - Important ongoing projects or goals mentioned multiple times
94
+ - Persistent technical constraints or requirements
95
+ - Domain expertise demonstrated consistently
96
+ - Custom terminology the user defines and uses repeatedly
97
+
98
+ **DO NOT EXTRACT** - Facts that are:
99
+ - One-time requests or isolated tasks (e.g., "generate an image or similar")
100
+ - Single interactions without pattern repetition
101
+ - Casual preferences from single occurrences
102
+ - Testing or exploratory questions
103
+ - Temporary context or transient information
104
+ - General courtesy or social patterns (greetings, thank yous)
105
+ - Random or playful requests that don't indicate lasting preference
106
+ - Information that could change or is situational
107
+
108
+ # Quality Standards
109
+ - **Confidence threshold**: Only extract if confidence >= 0.8
110
+ - **Persistence required**: Must see evidence across multiple messages or strong explicit statement
111
+ - **Meaningful value**: Would this fact improve future interactions weeks from now?
112
+ - **Not redundant**: Avoid if existing memories already cover this information
113
+
87
114
  # Instructions
88
- Extract any NEW information that should be remembered long-term. For each item:
115
+ Extract ONLY truly important NEW information that meets the strict criteria above. For each item:
89
116
  - Determine which category it belongs to
90
117
  - Write a clear, factual statement
91
- - Assess confidence (0.0 to 1.0)
92
- - Only include information explicitly stated or strongly implied
118
+ - Assess confidence (0.0 to 1.0) - BE CONSERVATIVE
119
+ - Require strong evidence before extraction
120
+
121
+ **When in doubt, DO NOT extract.** It's better to miss temporary information than to clutter long-term memory.
93
122
 
94
123
  If there are no new long-term facts to extract, respond with <memories></memories>
95
124
 
@@ -105,18 +134,18 @@ Respond in this XML format:
105
134
  <content>Prefers code examples over lengthy explanations</content>
106
135
  <confidence>0.85</confidence>
107
136
  </memory>
108
- </memories>`;function oJ(J){let Q=J.matchAll(/<memory>[\s\S]*?<category>(.*?)<\/category>[\s\S]*?<content>(.*?)<\/content>[\s\S]*?<confidence>(.*?)<\/confidence>[\s\S]*?<\/memory>/g),Y=[];for(let W of Q){let K=W[1].trim(),Z=W[2].trim(),$=parseFloat(W[3].trim());if(!Object.values(e).includes(K)){P.warn(`Invalid memory category: ${K}`);continue}if(Z&&!isNaN($))Y.push({category:K,content:Z,confidence:$})}return Y}var BJ={name:"LONG_TERM_MEMORY_EXTRACTION",description:"Extracts long-term facts about users from conversations",similes:["MEMORY_EXTRACTION","FACT_LEARNING","USER_PROFILING"],alwaysRun:!0,validate:async(J,Q)=>{if(P.debug(`Validating long-term memory extraction for message: ${Q.content?.text}`),Q.entityId===J.agentId)return P.debug("Skipping long-term memory extraction for agent's own message"),!1;if(!Q.content?.text)return P.debug("Skipping long-term memory extraction for message without text"),!1;let Y=J.getService("memory");if(!Y)return P.debug("MemoryService not found"),!1;if(!Y.getConfig().longTermExtractionEnabled)return P.debug("Long-term memory extraction is disabled"),!1;let K=await J.countMemories(Q.roomId,!1,"messages"),Z=await Y.shouldRunExtraction(Q.entityId,Q.roomId,K);return P.debug(`Should run extraction: ${Z}`),Z},handler:async(J,Q)=>{let Y=J.getService("memory");if(!Y){P.error("MemoryService not found");return}let W=Y.getConfig(),{entityId:K,roomId:Z}=Q;try{P.info(`Extracting long-term memories for entity ${K}`);let U=(await J.getMemories({tableName:"messages",roomId:Z,count:20,unique:!1})).sort((A,N)=>(A.createdAt||0)-(N.createdAt||0)).map((A)=>{return`${A.entityId===J.agentId?J.character.name:"User"}: ${A.content.text||"[non-text message]"}`}).join(`
109
- `),V=await Y.getLongTermMemories(K,void 0,30),_=V.length>0?V.map((A)=>`[${A.category}] ${A.content} (confidence: ${A.confidence})`).join(`
110
- `):"None yet",j=await J.composeState(Q),B=nJ({state:{...j,recentMessages:U,existingMemories:_},template:aJ}),F=await J.useModel(iJ.TEXT_LARGE,{prompt:B}),X=oJ(F);P.info(`Extracted ${X.length} long-term memories`);for(let A of X)if(A.confidence>=W.longTermConfidenceThreshold)await Y.storeLongTermMemory({agentId:J.agentId,entityId:K,category:A.category,content:A.content,confidence:A.confidence,source:"conversation",metadata:{roomId:Z,extractedAt:new Date().toISOString()}}),P.info(`Stored long-term memory: [${A.category}] ${A.content.substring(0,50)}...`);else P.debug(`Skipped low-confidence memory: ${A.content} (confidence: ${A.confidence})`);let O=await J.countMemories(Z,!1,"messages");await Y.setLastExtractionCheckpoint(K,Z,O),P.debug(`Updated extraction checkpoint to ${O} for entity ${K} in room ${Z}`)}catch($){P.error({error:$},"Error during long-term memory extraction:")}},examples:[]};import{addHeader as C,ChannelType as i,formatMessages as JJ,formatPosts as OJ,getEntityDetails as FJ,logger as mJ}from"@elizaos/core";var NJ={name:"SHORT_TERM_MEMORY",description:"Adaptive conversation context with smart summarization",position:95,get:async(J,Q,Y)=>{try{let W=J.getService("memory");if(!W)return{data:{summaries:[],recentMessages:[],mode:"disabled"},values:{sessionSummaries:"",recentMessages:""},text:""};let{roomId:K}=Q,Z=W.getConfig();if(await J.countMemories(K,!1,"messages")<Z.shortTermSummarizationThreshold){let U=J.getConversationLength(),[V,_,j]=await Promise.all([FJ({runtime:J,roomId:K}),J.getRoom(K),J.getMemories({tableName:"messages",roomId:K,count:U,unique:!1})]),B=j.filter((H)=>H.content?.type==="action_result"&&H.metadata?.type==="action_result"),F=j.filter((H)=>!(H.content?.type==="action_result"&&H.metadata?.type==="action_result")),X=_?.type?_.type===i.FEED||_.type===i.THREAD:!1,[O,A]=await Promise.all([JJ({messages:F,entities:V}),OJ({messages:F,entities:V,conversationHeader:!1})]),N="";if(B.length>0){let H=new Map;for(let x of B){let h=String(x.content?.runId||"unknown");if(!H.has(h))H.set(h,[]);H.get(h)?.push(x)}let S=Array.from(H.entries()).slice(-3).map(([x,h])=>{let KJ=h.sort((v,M)=>(v.createdAt||0)-(M.createdAt||0)),QJ=KJ[0]?.content?.planThought||"",PJ=KJ.map((v)=>{let M=v.content?.actionName||"Unknown",qJ=v.content?.actionStatus||"unknown",WJ=v.content?.planStep||"",n=v.content?.text||"",YJ=v.content?.error||"",y=` - ${M} (${qJ})`;if(WJ)y+=` [${WJ}]`;if(YJ)y+=`: Error - ${YJ}`;else if(n&&n!==`Executed action: ${M}`)y+=`: ${n}`;return y}).join(`
111
- `);return`**Action Run ${x.slice(0,8)}**${QJ?` - "${QJ}"`:""}
137
+ </memories>`;function oJ(K){let W=K.matchAll(/<memory>[\s\S]*?<category>(.*?)<\/category>[\s\S]*?<content>(.*?)<\/content>[\s\S]*?<confidence>(.*?)<\/confidence>[\s\S]*?<\/memory>/g),Q=[];for(let Y of W){let J=Y[1].trim(),Z=Y[2].trim(),_=parseFloat(Y[3].trim());if(!Object.values(KJ).includes(J)){q.warn(`Invalid memory category: ${J}`);continue}if(Z&&!isNaN(_))Q.push({category:J,content:Z,confidence:_})}return Q}var EJ={name:"LONG_TERM_MEMORY_EXTRACTION",description:"Extracts long-term facts about users from conversations",similes:["MEMORY_EXTRACTION","FACT_LEARNING","USER_PROFILING"],alwaysRun:!0,validate:async(K,W)=>{if(q.debug(`Validating long-term memory extraction for message: ${W.content?.text}`),W.entityId===K.agentId)return q.debug("Skipping long-term memory extraction for agent's own message"),!1;if(!W.content?.text)return q.debug("Skipping long-term memory extraction for message without text"),!1;let Q=K.getService("memory");if(!Q)return q.debug("MemoryService not found"),!1;if(!Q.getConfig().longTermExtractionEnabled)return q.debug("Long-term memory extraction is disabled"),!1;let J=await K.countMemories(W.roomId,!1,"messages"),Z=await Q.shouldRunExtraction(W.entityId,W.roomId,J);return q.debug(`Should run extraction: ${Z}`),Z},handler:async(K,W)=>{let Q=K.getService("memory");if(!Q){q.error("MemoryService not found");return}let Y=Q.getConfig(),{entityId:J,roomId:Z}=W;try{q.info(`Extracting long-term memories for entity ${J}`);let A=(await K.getMemories({tableName:"messages",roomId:Z,count:20,unique:!1})).sort((G,L)=>(G.createdAt||0)-(L.createdAt||0)).map((G)=>{return`${G.entityId===K.agentId?K.character.name:"User"}: ${G.content.text||"[non-text message]"}`}).join(`
138
+ `),V=await Q.getLongTermMemories(J,void 0,30),$=V.length>0?V.map((G)=>`[${G.category}] ${G.content} (confidence: ${G.confidence})`).join(`
139
+ `):"None yet",F=await K.composeState(W),N=nJ({state:{...F,recentMessages:A,existingMemories:$},template:aJ}),j=await K.useModel(iJ.TEXT_LARGE,{prompt:N}),B=oJ(j);q.info(`Extracted ${B.length} long-term memories`);for(let G of B)if(G.confidence>=Y.longTermConfidenceThreshold)await Q.storeLongTermMemory({agentId:K.agentId,entityId:J,category:G.category,content:G.content,confidence:G.confidence,source:"conversation",metadata:{roomId:Z,extractedAt:new Date().toISOString()}}),q.info(`Stored long-term memory: [${G.category}] ${G.content.substring(0,50)}...`);else q.debug(`Skipped low-confidence memory: ${G.content} (confidence: ${G.confidence})`);let O=await K.countMemories(Z,!1,"messages");await Q.setLastExtractionCheckpoint(J,Z,O),q.debug(`Updated extraction checkpoint to ${O} for entity ${J} in room ${Z}`)}catch(_){q.error({error:_},"Error during long-term memory extraction:")}},examples:[]};import{addHeader as v,ChannelType as a,formatMessages as QJ,formatPosts as FJ,getEntityDetails as NJ,logger as mJ}from"@elizaos/core";var kJ={name:"SHORT_TERM_MEMORY",description:"Adaptive conversation context with smart summarization",position:95,get:async(K,W,Q)=>{try{let Y=K.getService("memory");if(!Y)return{data:{summaries:[],recentMessages:[],mode:"disabled"},values:{},text:""};let{roomId:J}=W,Z=Y.getConfig();if(await K.countMemories(J,!1,"messages")<Z.shortTermSummarizationThreshold){let A=K.getConversationLength(),[V,$,F]=await Promise.all([NJ({runtime:K,roomId:J}),K.getRoom(J),K.getMemories({tableName:"messages",roomId:J,count:A,unique:!1})]),N=F.filter((P)=>P.content?.type==="action_result"&&P.metadata?.type==="action_result"),j=F.filter((P)=>!(P.content?.type==="action_result"&&P.metadata?.type==="action_result")),B=$?.type?$.type===a.FEED||$.type===a.THREAD:!1,[O,G]=await Promise.all([QJ({messages:j,entities:V}),FJ({messages:j,entities:V,conversationHeader:!1})]),L="";if(N.length>0){let P=new Map;for(let w of N){let S=String(w.content?.runId||"unknown");if(!P.has(S))P.set(S,[]);P.get(S)?.push(w)}let M=Array.from(P.entries()).slice(-3).map(([w,S])=>{let WJ=S.sort((x,c)=>(x.createdAt||0)-(c.createdAt||0)),YJ=WJ[0]?.content?.planThought||"",PJ=WJ.map((x)=>{let c=x.content?.actionName||"Unknown",qJ=x.content?.actionStatus||"unknown",ZJ=x.content?.planStep||"",o=x.content?.text||"",_J=x.content?.error||"",d=` - ${c} (${qJ})`;if(ZJ)d+=` [${ZJ}]`;if(_J)d+=`: Error - ${_J}`;else if(o&&o!==`Executed action: ${c}`)d+=`: ${o}`;return d}).join(`
140
+ `);return`**Action Run ${w.slice(0,8)}**${YJ?` - "${YJ}"`:""}
112
141
  ${PJ}`}).join(`
113
142
 
114
- `);N=S?C("# Recent Action Executions",S):""}let q=A&&A.length>0?C("# Posts in Thread",A):"",E=O&&O.length>0?C("# Conversation Messages",O):"";if(!q&&!E&&F.length===0&&!Q.content.text)return{data:{summaries:[],recentMessages:[],actionResults:[],mode:"full_conversation"},values:{sessionSummaries:"",recentMessages:"",recentActionResults:""},text:"No recent messages available"};let T="No recent message available.";if(F.length>0){let H=[...F].sort((x,h)=>(h.createdAt||0)-(x.createdAt||0))[0],S=JJ({messages:[H],entities:V});if(S)T=S}let I=Q.metadata,b=V.find((H)=>H.id===Q.entityId)?.names[0]||I?.entityName||"Unknown User",z=Q.content.text,f=!!z?.trim(),HJ=f?C("# Received Message",`${b}: ${z}`):"",kJ=f?C("# Focus your response",`You are replying to the above message from **${b}**. Keep your answer relevant to that message. Do not repeat earlier replies unless the sender asks again.`):"",LJ=[X?q:E,N,E||q||Q.content.text?HJ:"",E||q||Q.content.text?kJ:""].filter(Boolean).join(`
143
+ `);L=M?v("# Recent Action Executions",M):""}let D=G&&G.length>0?v("# Posts in Thread",G):"",U=O&&O.length>0?v("# Conversation Messages",O):"";if(!D&&!U&&j.length===0&&!W.content.text)return{data:{summaries:[],recentMessages:[],actionResults:[],mode:"full_conversation"},values:{recentMessage:"No recent message available."},text:"No recent messages available"};let R="No recent message available.";if(j.length>0){let P=[...j].sort((w,S)=>(S.createdAt||0)-(w.createdAt||0))[0],M=QJ({messages:[P],entities:V});if(M)R=M}let C=W.metadata,T=V.find((P)=>P.id===W.entityId)?.names[0]||C?.entityName||"Unknown User",b=W.content.text,f=!!b?.trim(),h=f?v("# Received Message",`${T}: ${b}`):"",p=f?v("# Focus your response",`You are replying to the above message from **${T}**. Keep your answer relevant to that message. Do not repeat earlier replies unless the sender asks again.`):"",HJ=[B?D:U,L,U||D||W.content.text?h:"",U||D||W.content.text?p:""].filter(Boolean).join(`
115
144
 
116
- `);return{data:{summaries:[],recentMessages:F,actionResults:B,mode:"full_conversation"},values:{sessionSummaries:"",recentMessages:X?q:E,recentActionResults:N,recentMessage:T},text:LJ}}else{let U=await W.getCurrentSessionSummary(K),V=U?.lastMessageOffset||0,_=await J.getMemories({tableName:"messages",roomId:K,count:Z.shortTermRetainRecent,unique:!1,start:V}),j=await FJ({runtime:J,roomId:K}),B=await J.getRoom(K),F=B?.type?B.type===i.FEED||B.type===i.THREAD:!1,X="";if(_.length>0){let z=_.filter((f)=>!(f.content?.type==="action_result"&&f.metadata?.type==="action_result"));if(F)X=OJ({messages:z,entities:j,conversationHeader:!1});else X=JJ({messages:z,entities:j});if(X)X=C("# Recent Messages",X)}let O="";if(U){let z=`${U.messageCount} messages`,f=new Date(U.startTime).toLocaleDateString();if(O=`**Previous Conversation** (${z}, ${f})
117
- `,O+=U.summary,U.topics&&U.topics.length>0)O+=`
118
- *Topics: ${U.topics.join(", ")}*`;O=C("# Conversation Summary",O)}let A=Q.metadata,N=j.find((z)=>z.id===Q.entityId)?.names[0]||A?.entityName||"Unknown User",q=Q.content.text,E=!!q?.trim(),T=E?C("# Received Message",`${N}: ${q}`):"",I=E?C("# Focus your response",`You are replying to the above message from **${N}**. Keep your answer relevant to that message.`):"",b=[O,X,E?T:"",E?I:""].filter(Boolean).join(`
145
+ `);return{data:{summaries:[],recentMessages:j,actionResults:N,mode:"full_conversation"},values:{...(B?D:U)&&{recentMessages:B?D:U},...D&&{recentPosts:D},...L&&{recentActionResults:L},...R&&{recentMessage:R},...h&&{receivedMessageHeader:h},...p&&{focusHeader:p}},text:HJ}}else{let A=await Y.getCurrentSessionSummary(J),V=A?.lastMessageOffset||0,$=await K.getMemories({tableName:"messages",roomId:J,count:Z.shortTermRetainRecent,unique:!1,start:V}),F=await NJ({runtime:K,roomId:J}),N=await K.getRoom(J),j=N?.type?N.type===a.FEED||N.type===a.THREAD:!1,B="";if($.length>0){let b=$.filter((f)=>!(f.content?.type==="action_result"&&f.metadata?.type==="action_result"));if(j)B=FJ({messages:b,entities:F,conversationHeader:!1});else B=QJ({messages:b,entities:F});if(B)B=v("# Recent Messages",B)}let O="";if(A){let b=`${A.messageCount} messages`,f=new Date(A.startTime).toLocaleDateString();if(O=`**Previous Conversation** (${b}, ${f})
146
+ `,O+=A.summary,A.topics&&A.topics.length>0)O+=`
147
+ *Topics: ${A.topics.join(", ")}*`;O=v("# Conversation Summary",O)}let G=W.metadata,L=F.find((b)=>b.id===W.entityId)?.names[0]||G?.entityName||"Unknown User",D=W.content.text,U=!!D?.trim(),R=U?v("# Received Message",`${L}: ${D}`):"",C=U?v("# Focus your response",`You are replying to the above message from **${L}**. Keep your answer relevant to that message.`):"",T=[O,B,U?R:"",U?C:""].filter(Boolean).join(`
119
148
 
120
- `);return{data:{summaries:U?[U]:[],recentMessages:_,mode:"summarized"},values:{sessionSummaries:O,recentMessages:X},text:b}}}catch(W){return mJ.error({error:W},"Error in shortTermMemoryProvider:"),{data:{summaries:[],recentMessages:[],mode:"error"},values:{sessionSummaries:"",recentMessages:""},text:"Error retrieving conversation context."}}}};import{logger as sJ,addHeader as tJ}from"@elizaos/core";var EJ={name:"LONG_TERM_MEMORY",description:"Persistent facts and preferences about the user",position:50,get:async(J,Q,Y)=>{try{let W=J.getService("memory");if(!W)return{data:{memories:[]},values:{longTermMemories:""},text:""};let{entityId:K}=Q;if(K===J.agentId)return{data:{memories:[]},values:{longTermMemories:""},text:""};let Z=await W.getLongTermMemories(K,void 0,25);if(Z.length===0)return{data:{memories:[]},values:{longTermMemories:""},text:""};let $=await W.getFormattedLongTermMemories(K),U=tJ("# What I Know About You",$),V=new Map;for(let j of Z){let B=V.get(j.category)||0;V.set(j.category,B+1)}let _=Array.from(V.entries()).map(([j,B])=>`${j}: ${B}`).join(", ");return{data:{memories:Z,categoryCounts:Object.fromEntries(V)},values:{longTermMemories:U,memoryCategories:_},text:U}}catch(W){return sJ.error({error:W},"Error in longTermMemoryProvider:"),{data:{memories:[]},values:{longTermMemories:""},text:""}}}};var rJ={name:"memory",description:"Advanced memory management with conversation summarization and long-term persistent memory",services:[w],evaluators:[jJ,BJ],providers:[EJ,NJ],schema:r},eJ=rJ;export{k as sessionSummaries,rJ as memoryPlugin,VJ as memoryAccessLogs,G as longTermMemories,eJ as default,w as MemoryService,e as LongTermMemoryCategory};
149
+ `);return{data:{summaries:A?[A]:[],recentMessages:$,mode:"summarized"},values:{...O&&{sessionSummaries:O},...B&&{recentMessages:B},...R&&{receivedMessageHeader:R},...C&&{focusHeader:C}},text:T}}}catch(Y){return mJ.error({error:Y},"Error in shortTermMemoryProvider:"),{data:{summaries:[],recentMessages:[],mode:"error"},values:{},text:"Error retrieving conversation context."}}}};import{logger as tJ,addHeader as sJ}from"@elizaos/core";var LJ={name:"LONG_TERM_MEMORY",description:"Persistent facts and preferences about the user",position:50,get:async(K,W,Q)=>{try{let Y=K.getService("memory");if(!Y)return{data:{memories:[]},values:{longTermMemories:""},text:""};let{entityId:J}=W;if(J===K.agentId)return{data:{memories:[]},values:{longTermMemories:""},text:""};let Z=await Y.getLongTermMemories(J,void 0,25);if(Z.length===0)return{data:{memories:[]},values:{longTermMemories:""},text:""};let _=await Y.getFormattedLongTermMemories(J),A=sJ("# What I Know About You",_),V=new Map;for(let F of Z){let N=V.get(F.category)||0;V.set(F.category,N+1)}let $=Array.from(V.entries()).map(([F,N])=>`${F}: ${N}`).join(", ");return{data:{memories:Z,categoryCounts:Object.fromEntries(V)},values:{longTermMemories:A,memoryCategories:$},text:A}}catch(Y){return tJ.error({error:Y},"Error in longTermMemoryProvider:"),{data:{memories:[]},values:{longTermMemories:""},text:""}}}};var rJ={name:"memory",description:"Advanced memory management with conversation summarization and long-term persistent memory",services:[l],evaluators:[OJ,EJ],providers:[LJ,kJ],schema:JJ},eJ=rJ;export{k as sessionSummaries,rJ as memoryPlugin,jJ as memoryAccessLogs,X as longTermMemories,eJ as default,l as MemoryService,KJ as LongTermMemoryCategory};
121
150
 
122
- //# debugId=25F372E27183540F64756E2164756E21
151
+ //# debugId=BA2C12424D56A98E64756E2164756E21