@elizaos/plugin-memory 1.0.5 → 2.0.1

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.
Files changed (36) hide show
  1. package/README.md +339 -207
  2. package/dist/browser/index.browser.js +348 -151
  3. package/dist/browser/index.browser.js.map +23 -13
  4. package/dist/cjs/index.node.cjs +2200 -1047
  5. package/dist/cjs/index.node.js.map +23 -13
  6. package/dist/evaluators/consolidation.d.ts +19 -0
  7. package/dist/evaluators/summarization.d.ts +5 -24
  8. package/dist/index.d.ts +152 -30
  9. package/dist/node/index.node.js +2242 -1084
  10. package/dist/node/index.node.js.map +23 -13
  11. package/dist/prompts/consolidation.d.ts +35 -0
  12. package/dist/prompts/summarization.d.ts +25 -0
  13. package/dist/providers/action-results.d.ts +2 -0
  14. package/dist/providers/long-term-memory.d.ts +18 -11
  15. package/dist/providers/recent-conversation-summary.d.ts +2 -0
  16. package/dist/repositories/conversation-summary.d.ts +33 -0
  17. package/dist/repositories/index.d.ts +17 -0
  18. package/dist/repositories/long-term-memory.d.ts +53 -0
  19. package/dist/schemas/conversation-summaries.d.ts +494 -0
  20. package/dist/schemas/index.d.ts +16 -6
  21. package/dist/schemas/long-term-memories.d.ts +308 -70
  22. package/dist/services/memory-service.d.ts +95 -51
  23. package/dist/types/index.d.ts +299 -55
  24. package/dist/utils/db-mapping.d.ts +20 -0
  25. package/dist/utils/decay-scoring.d.ts +41 -0
  26. package/dist/utils/embedding.d.ts +21 -0
  27. package/dist/utils/formatting.d.ts +17 -0
  28. package/dist/utils/index.d.ts +17 -0
  29. package/dist/utils/search-merging.d.ts +18 -0
  30. package/dist/utils/token-counter.d.ts +53 -0
  31. package/package.json +83 -1
  32. package/dist/actions/remember.d.ts +0 -11
  33. package/dist/evaluators/long-term-extraction.d.ts +0 -8
  34. package/dist/providers/short-term-memory.d.ts +0 -19
  35. package/dist/schemas/memory-access-logs.d.ts +0 -154
  36. package/dist/schemas/session-summaries.d.ts +0 -283
@@ -1,151 +1,348 @@
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
-
5
- `)}}import{logger as z,ModelType as cJ,composePromptFromState as BJ}from"@elizaos/core";var dJ=`# Task: Summarize Conversation
6
-
7
- You are analyzing a conversation to create a concise summary that captures the key points, topics, and important details.
8
-
9
- # Recent Messages
10
- {{recentMessages}}
11
-
12
- # Instructions
13
- Generate a summary that:
14
- 1. Captures the main topics discussed
15
- 2. Highlights key information shared
16
- 3. Notes any decisions made or questions asked
17
- 4. Maintains context for future reference
18
- 5. Is concise but comprehensive
19
-
20
- **IMPORTANT**: Keep the summary under 2500 tokens. Be comprehensive but concise.
21
-
22
- Also extract:
23
- - **Topics**: List of main topics discussed (comma-separated)
24
- - **Key Points**: Important facts or decisions (bullet points)
25
-
26
- Respond in this XML format:
27
- <summary>
28
- <text>Your comprehensive summary here</text>
29
- <topics>topic1, topic2, topic3</topics>
30
- <keyPoints>
31
- <point>First key point</point>
32
- <point>Second key point</point>
33
- </keyPoints>
34
- </summary>`,uJ=`# Task: Update and Condense Conversation Summary
35
-
36
- You are updating an existing conversation summary with new messages, while keeping the total summary concise.
37
-
38
- # Existing Summary
39
- {{existingSummary}}
40
-
41
- # Existing Topics
42
- {{existingTopics}}
43
-
44
- # New Messages Since Last Summary
45
- {{newMessages}}
46
-
47
- # Instructions
48
- Update the summary by:
49
- 1. Merging the existing summary with insights from the new messages
50
- 2. Removing redundant or less important details to stay under the token limit
51
- 3. Keeping the most important context and decisions
52
- 4. Adding new topics if they emerge
53
- 5. **CRITICAL**: Keep the ENTIRE updated summary under 2500 tokens
54
-
55
- The goal is a rolling summary that captures the essence of the conversation without growing indefinitely.
56
-
57
- Respond in this XML format:
58
- <summary>
59
- <text>Your updated and condensed summary here</text>
60
- <topics>topic1, topic2, topic3</topics>
61
- <keyPoints>
62
- <point>First key point</point>
63
- <point>Second key point</point>
64
- </keyPoints>
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
-
68
- You are analyzing a conversation to extract ONLY the most important, persistent facts about the user that should be remembered long-term.
69
-
70
- # Recent Messages
71
- {{recentMessages}}
72
-
73
- # Current Long-Term Memories
74
- {{existingMemories}}
75
-
76
- # Memory Categories
77
- 1. **identity**: User's name, role, identity (e.g., "I'm a data scientist")
78
- 2. **expertise**: User's skills, knowledge domains, or unfamiliarity with topics
79
- 3. **projects**: Ongoing projects, past interactions, recurring topics
80
- 4. **preferences**: Communication style, format preferences, verbosity, etc.
81
- 5. **data_sources**: Frequently used files, databases, APIs
82
- 6. **goals**: Broader intentions (e.g., "preparing for interview")
83
- 7. **constraints**: User-defined rules or limitations
84
- 8. **definitions**: Custom terms, acronyms, glossaries
85
- 9. **behavioral_patterns**: How the user tends to interact
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
-
114
- # Instructions
115
- Extract ONLY truly important NEW information that meets the strict criteria above. For each item:
116
- - Determine which category it belongs to
117
- - Write a clear, factual statement
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.
122
-
123
- If there are no new long-term facts to extract, respond with <memories></memories>
124
-
125
- Respond in this XML format:
126
- <memories>
127
- <memory>
128
- <category>identity</category>
129
- <content>User is a software engineer specializing in backend development</content>
130
- <confidence>0.95</confidence>
131
- </memory>
132
- <memory>
133
- <category>preferences</category>
134
- <content>Prefers code examples over lengthy explanations</content>
135
- <confidence>0.85</confidence>
136
- </memory>
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}"`:""}
141
- ${PJ}`}).join(`
142
-
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(`
144
-
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(`
148
-
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};
150
-
151
- //# debugId=BA2C12424D56A98E64756E2164756E21
1
+ var nJ=Object.defineProperty;var iJ=(J,Q)=>{for(var W in Q)nJ(J,W,{get:Q[W],enumerable:!0,configurable:!0,set:($)=>Q[W]=()=>$})};import{Service as GQ,logger as F,ModelType as o,parseKeyValueXml as YQ,parseBooleanFromText as jQ}from"@elizaos/core";import{BM25 as NQ}from"@elizaos/core";var e={384:"dim384",512:"dim512",768:"dim768",1024:"dim1024",1536:"dim1536",3072:"dim3072"},_J;(($)=>{$.EPISODIC="EPISODIC";$.SEMANTIC="SEMANTIC";$.PROCEDURAL="PROCEDURAL"})(_J||={});var tJ;(($)=>{$.EXPONENTIAL="EXPONENTIAL";$.LINEAR="LINEAR";$.NONE="NONE"})(tJ||={});import{logger as h}from"@elizaos/core";import{eq as H,and as $J,desc as XJ,sql as ZJ,cosineDistance as eJ,gte as LJ,or as JQ,isNull as QQ}from"drizzle-orm";var QJ={};iJ(QJ,{longTermMemoryEmbeddings:()=>D,longTermMemories:()=>A,conversationSummaryEmbeddings:()=>R,conversationSummaries:()=>k});import{sql as kJ}from"drizzle-orm";import{pgTable as PJ,text as d,integer as oJ,jsonb as OJ,real as VJ,index as C,varchar as f,timestamp as JJ,boolean as aJ,vector as v,foreignKey as mJ}from"drizzle-orm/pg-core";import{VECTOR_DIMS as S}from"@elizaos/core";var A=PJ("long_term_memories",{id:f("id",{length:36}).primaryKey(),agentId:f("agent_id",{length:36}).notNull(),entityId:f("entity_id",{length:36}).notNull(),roomId:f("room_id",{length:36}),type:d("type").notNull(),content:d("content").notNull(),embeddingContext:d("embedding_context").notNull(),confidence:VJ("confidence").notNull().default(1),decayRate:VJ("decay_rate").notNull().default(0.01),decayFunction:d("decay_function").notNull().default("EXPONENTIAL"),createdAt:JJ("created_at").default(kJ`now()`).notNull(),lastAccessedAt:JJ("last_accessed_at"),accessCount:oJ("access_count").default(0).notNull(),isActive:aJ("is_active").default(!0).notNull(),source:OJ("source").notNull().default({}),metadata:OJ("metadata").notNull().default({}),supersedesId:f("supersedes_id",{length:36})},(J)=>({agentEntityIdx:C("ltm_agent_entity_idx").on(J.agentId,J.entityId),typeIdx:C("ltm_type_idx").on(J.type),roomIdx:C("ltm_room_idx").on(J.roomId),activeIdx:C("ltm_active_idx").on(J.isActive),confidenceIdx:C("ltm_confidence_idx").on(J.confidence),createdAtIdx:C("ltm_created_at_idx").on(J.createdAt),lastAccessedIdx:C("ltm_last_accessed_idx").on(J.lastAccessedAt),agentEntityActiveConfidenceIdx:C("ltm_agent_entity_active_conf_idx").on(J.agentId,J.entityId,J.isActive,J.confidence)})),D=PJ("long_term_memory_embeddings",{id:f("id",{length:36}).primaryKey(),memoryId:f("memory_id",{length:36}).notNull().references(()=>A.id,{onDelete:"cascade"}),dim384:v("dim_384",{dimensions:S.SMALL}),dim512:v("dim_512",{dimensions:S.MEDIUM}),dim768:v("dim_768",{dimensions:S.LARGE}),dim1024:v("dim_1024",{dimensions:S.XL}),dim1536:v("dim_1536",{dimensions:S.XXL}),dim3072:v("dim_3072",{dimensions:S.XXXL}),createdAt:JJ("created_at").default(kJ`now()`).notNull()},(J)=>[C("idx_ltm_embedding_memory_id").on(J.memoryId),mJ({name:"fk_ltm_embedding_memory",columns:[J.memoryId],foreignColumns:[A.id]}).onDelete("cascade")]);import{sql as BJ}from"drizzle-orm";import{pgTable as qJ,text as sJ,integer as n,jsonb as HJ,index as E,varchar as w,timestamp as u,vector as b,foreignKey as rJ}from"drizzle-orm/pg-core";import{VECTOR_DIMS as M}from"@elizaos/core";var k=qJ("conversation_summaries",{id:w("id",{length:36}).primaryKey(),agentId:w("agent_id",{length:36}).notNull(),entityId:w("entity_id",{length:36}).notNull(),roomId:w("room_id",{length:36}).notNull(),level:n("level").notNull().default(1),parentSummaryId:w("parent_summary_id",{length:36}),content:sJ("content").notNull(),tokenCount:n("token_count").notNull(),startTime:u("start_time").notNull(),endTime:u("end_time").notNull(),sourceCount:n("source_count").notNull(),sourceIds:HJ("source_ids").notNull().default([]),createdAt:u("created_at").default(BJ`now()`).notNull(),lastAccessedAt:u("last_accessed_at"),accessCount:n("access_count").default(0).notNull(),metadata:HJ("metadata").notNull().default({})},(J)=>({agentEntityRoomIdx:E("cs_agent_entity_room_idx").on(J.agentId,J.entityId,J.roomId),levelIdx:E("cs_level_idx").on(J.level),parentIdx:E("cs_parent_idx").on(J.parentSummaryId),timeRangeIdx:E("cs_time_range_idx").on(J.startTime,J.endTime),createdAtIdx:E("cs_created_at_idx").on(J.createdAt),lastAccessedIdx:E("cs_last_accessed_idx").on(J.lastAccessedAt),entityRoomLevelTimeIdx:E("cs_entity_room_level_time_idx").on(J.entityId,J.roomId,J.level,J.createdAt)})),R=qJ("conversation_summary_embeddings",{id:w("id",{length:36}).primaryKey(),summaryId:w("summary_id",{length:36}).notNull().references(()=>k.id,{onDelete:"cascade"}),dim384:b("dim_384",{dimensions:M.SMALL}),dim512:b("dim_512",{dimensions:M.MEDIUM}),dim768:b("dim_768",{dimensions:M.LARGE}),dim1024:b("dim_1024",{dimensions:M.XL}),dim1536:b("dim_1536",{dimensions:M.XXL}),dim3072:b("dim_3072",{dimensions:M.XXXL}),createdAt:u("created_at").default(BJ`now()`).notNull()},(J)=>[E("idx_cs_embedding_summary_id").on(J.summaryId),rJ({name:"fk_cs_embedding_summary",columns:[J.summaryId],foreignColumns:[k.id]}).onDelete("cascade")]);function i(J){return{id:J.id,agentId:J.agentId,entityId:J.entityId,roomId:J.roomId,type:J.type,content:J.content,embeddingContext:J.embeddingContext,embedding:J.embedding,confidence:J.confidence,decayRate:J.decayRate,decayFunction:J.decayFunction,createdAt:J.createdAt,lastAccessedAt:J.lastAccessedAt,accessCount:J.accessCount,isActive:J.isActive,source:J.source,metadata:J.metadata,supersedesId:J.supersedesId}}function WJ(J){return{id:J.id,agentId:J.agentId,entityId:J.entityId,roomId:J.roomId,level:J.level,parentSummaryId:J.parentSummaryId,content:J.content,embedding:J.embedding,tokenCount:J.tokenCount,startTime:J.startTime,endTime:J.endTime,sourceCount:J.sourceCount,sourceIds:J.sourceIds,createdAt:J.createdAt,lastAccessedAt:J.lastAccessedAt,accessCount:J.accessCount,metadata:J.metadata||{}}}class KJ{runtime;embeddingDimension;constructor(J,Q){this.runtime=J;this.embeddingDimension=Q}async getDb(){let J=this.runtime.adapter||this.runtime,Q=J.db;if(!Q)throw Error("Database not available");try{if(!await J.isReady()){if(h.warn("[LongTermMemoryRepository] Database not ready, attempting reconnect..."),await new Promise((Z)=>setTimeout(Z,1000)),await J.isReady()===!1)throw Error("Database connection lost and could not reconnect")}}catch(W){throw h.error("[LongTermMemoryRepository] Database health check failed:",W),Error("Database connection health check failed")}return Q}async insert(J,Q){let W=await this.getDb(),$=crypto.randomUUID(),Z=new Date,X={id:$,createdAt:Z,lastAccessedAt:null,accessCount:0,isActive:!0,embedding:Q||[],...J};return await W.transaction(async(G)=>{if(await G.insert(A).values({id:X.id,agentId:X.agentId,entityId:X.entityId,roomId:X.roomId||null,type:X.type,content:X.content,embeddingContext:X.embeddingContext,confidence:X.confidence,decayRate:X.decayRate,decayFunction:X.decayFunction,createdAt:Z,lastAccessedAt:null,accessCount:0,isActive:!0,source:X.source,metadata:X.metadata,supersedesId:X.supersedesId||null}),Q&&this.embeddingDimension){let K={id:crypto.randomUUID(),memoryId:$,createdAt:Z};K[this.embeddingDimension]=Q,await G.insert(D).values(K)}}),h.info({id:X.id,type:X.type,entityId:X.entityId,confidence:X.confidence},"Stored new long-term memory"),X}async findById(J){let W=await(await this.getDb()).select().from(A).where(H(A.id,J)).limit(1);if(W.length===0)return null;return i(W[0])}async update(J,Q,W){let $=await this.getDb(),Z={};if(Q.content!==void 0)Z.content=Q.content;if(Q.embeddingContext!==void 0)Z.embeddingContext=Q.embeddingContext;if(Q.confidence!==void 0)Z.confidence=Q.confidence;if(Q.decayRate!==void 0)Z.decayRate=Q.decayRate;if(Q.decayFunction!==void 0)Z.decayFunction=Q.decayFunction;if(Q.lastAccessedAt!==void 0)Z.lastAccessedAt=Q.lastAccessedAt;if(Q.accessCount!==void 0)Z.accessCount=Q.accessCount;if(Q.isActive!==void 0)Z.isActive=Q.isActive;if(Q.source!==void 0)Z.source=Q.source;if(Q.metadata!==void 0)Z.metadata=Q.metadata;if(Q.supersedesId!==void 0)Z.supersedesId=Q.supersedesId;await $.transaction(async(X)=>{if(await X.update(A).set(Z).where(H(A.id,J)),W&&this.embeddingDimension){let G={};G[this.embeddingDimension]=W,await X.update(D).set(G).where(H(D.memoryId,J))}}),h.info({id:J},"Updated long-term memory")}async delete(J){await(await this.getDb()).delete(A).where(H(A.id,J)),h.info({id:J},"Deleted long-term memory")}async findByEntity(J,Q,W=20,$=!1){let Z=await this.getDb(),X=[H(A.agentId,this.runtime.agentId),H(A.entityId,J)];if(!$)X.push(H(A.isActive,!0));if(Q)X.push(H(A.type,Q));return(await Z.select().from(A).where($J(...X)).orderBy(XJ(A.confidence),XJ(A.createdAt)).limit(W)).map((K)=>i(K))}async vectorSearch(J,Q,W=0.3){if(!this.embeddingDimension)return h.warn("Embedding dimension not set, skipping vector search"),[];let $=await this.getDb();try{let Z=ZJ`1 - (${eJ(D[this.embeddingDimension],Q)})`,X=[H(A.agentId,this.runtime.agentId),H(A.entityId,J.entityId),ZJ`${D[this.embeddingDimension]} IS NOT NULL`,LJ(Z,W)];if(J.minConfidence)X.push(LJ(A.confidence,J.minConfidence));if(!J.includeInactive)X.push(H(A.isActive,!0));if(J.type)X.push(H(A.type,J.type));if(J.roomId)X.push(JQ(H(A.roomId,J.roomId),QQ(A.roomId)));return(await $.select({memory:A,embedding:D[this.embeddingDimension],similarity:Z}).from(A).innerJoin(D,H(D.memoryId,A.id)).where($J(...X)).orderBy(XJ(Z)).limit(J.limit||20)).map((K)=>({...i(K.memory),embedding:K.embedding,relevanceScore:K.similarity,activationScore:0,finalScore:0}))}catch(Z){return h.error("Failed to execute vector search:",JSON.stringify(Z)),[]}}async fetchAllActive(){return(await(await this.getDb()).select().from(A).where($J(H(A.agentId,this.runtime.agentId),H(A.isActive,!0)))).map((W)=>({id:W.id,content:W.content,embeddingContext:W.embeddingContext}))}async updateAccessMetadata(J){if(J.length===0)return;let Q=await this.getDb(),W=new Date;try{for(let $ of J)await Q.update(A).set({lastAccessedAt:W,accessCount:ZJ`${A.accessCount} + 1`}).where(H(A.id,$));h.debug({count:J.length},"Updated access metadata")}catch($){h.error({error:$},"Failed to update access metadata")}}}import{logger as x}from"@elizaos/core";import{eq as I,and as zJ,desc as DJ,sql as GJ,cosineDistance as WQ}from"drizzle-orm";class YJ{runtime;embeddingDimension;constructor(J,Q){this.runtime=J;this.embeddingDimension=Q}async getDb(){let J=this.runtime.adapter||this.runtime,Q=J.db;if(!Q)throw Error("Database not available");try{if(!await J.isReady()){if(x.warn("[ConversationSummaryRepository] Database not ready, attempting reconnect..."),await new Promise((Z)=>setTimeout(Z,1000)),await J.isReady()===!1)throw Error("Database connection lost and could not reconnect")}}catch(W){throw x.error("[ConversationSummaryRepository] Database health check failed:",W),Error("Database connection health check failed")}return Q}async insert(J,Q){let W=await this.getDb(),$=crypto.randomUUID(),Z=new Date,X={id:$,createdAt:Z,lastAccessedAt:null,accessCount:0,embedding:Q||[],...J};return await W.transaction(async(G)=>{if(await G.insert(k).values({id:X.id,agentId:X.agentId,entityId:X.entityId,roomId:X.roomId,level:X.level,parentSummaryId:X.parentSummaryId||null,content:X.content,tokenCount:X.tokenCount,startTime:X.startTime,endTime:X.endTime,sourceCount:X.sourceCount,sourceIds:X.sourceIds,createdAt:Z,lastAccessedAt:null,accessCount:0,metadata:X.metadata}),Q&&this.embeddingDimension){let K={id:crypto.randomUUID(),summaryId:$,createdAt:Z};K[this.embeddingDimension]=Q,await G.insert(R).values(K)}}),x.info({id:X.id,level:X.level,tokenCount:X.tokenCount,sourceCount:X.sourceCount},"Stored conversation summary"),X}async findByLevel(J,Q){return(await(await this.getDb()).select().from(k).where(zJ(I(k.agentId,this.runtime.agentId),I(k.roomId,J),I(k.level,Q))).orderBy(DJ(k.createdAt))).map((Z)=>WJ(Z))}async vectorSearch(J,Q,W,$=5){if(!this.embeddingDimension)return x.warn("Embedding dimension not set, skipping summary search"),[];let Z=await this.getDb();try{let X=GJ`1 - (${WQ(R[this.embeddingDimension],W)})`;return(await Z.select({summary:k,embedding:R[this.embeddingDimension],similarity:X}).from(k).innerJoin(R,I(R.summaryId,k.id)).where(zJ(I(k.agentId,this.runtime.agentId),I(k.entityId,J),I(k.roomId,Q),GJ`${R[this.embeddingDimension]} IS NOT NULL`)).orderBy(DJ(X)).limit($*2)).map((K)=>({...WJ(K.summary),embedding:K.embedding}))}catch(X){return x.error("Failed to search summaries:",JSON.stringify(X)),[]}}async updateAccessMetadata(J){if(J.length===0)return;let Q=await this.getDb(),W=new Date;try{for(let $ of J)await Q.update(k).set({lastAccessedAt:W,accessCount:GJ`${k.accessCount} + 1`}).where(I(k.id,$));x.debug({count:J.length},"Updated summary access metadata")}catch($){x.error({error:$},"Failed to update summary access metadata")}}}import{ModelType as $Q,logger as XQ}from"@elizaos/core";async function p(J,Q){try{return await J.useModel($Q.TEXT_EMBEDDING,Q)}catch(W){return XQ.error({error:W},"Failed to generate embedding"),Array(1536).fill(0)}}function y(J){return J.map((Q)=>Number.isFinite(Q)?Number(Q.toFixed(6)):0)}function ZQ(J,Q,W){switch(J){case"EXPONENTIAL":return Math.exp(-Q*W);case"LINEAR":return Math.max(0,1-Q*W);case"NONE":return 1;default:return 1}}function KQ(J){return 1+Math.log(1+J)*0.1}function CJ(J){let Q=Date.now();return J.map((W)=>{let $=W.lastAccessedAt?.getTime()||W.createdAt.getTime(),Z=(Q-$)/86400000,X=ZQ(W.decayFunction,W.decayRate,Z),G=KQ(W.accessCount),K=W.confidence*X*G,Y=W.relevanceScore*K;return{...W,activationScore:K,finalScore:Y}})}function RJ(J,Q){let W=new Map;for(let $ of J)W.set($.id,$);for(let $ of Q)if(W.has($.id)){let Z=W.get($.id);Z.relevanceScore=(Z.relevanceScore+$.relevanceScore)/2}else W.set($.id,$);return Array.from(W.values())}function hJ(J){if(J.length===0)return"";let Q=new Map;for(let $ of J){if(!Q.has($.type))Q.set($.type,[]);Q.get($.type).push($)}let W=[];if(Q.has("SEMANTIC")){let Z=Q.get("SEMANTIC").map((X)=>`- ${X.content} (confidence: ${X.confidence.toFixed(2)})`).join(`
2
+ `);W.push(`**Semantic Knowledge (Facts)**:
3
+ ${Z}`)}if(Q.has("EPISODIC")){let Z=Q.get("EPISODIC").map((X)=>`- ${X.content} (${X.createdAt.toLocaleDateString()})`).join(`
4
+ `);W.push(`**Episodic Memory (Events)**:
5
+ ${Z}`)}if(Q.has("PROCEDURAL")){let Z=Q.get("PROCEDURAL").map((X)=>`- ${X.content}`).join(`
6
+ `);W.push(`**Procedural Knowledge (Skills)**:
7
+ ${Z}`)}return W.join(`
8
+
9
+ `)}function t(J){if(!J||J.length===0)return 0;let Q=J.length;return Math.ceil(Q/4)}function YW(J){return J.reduce((Q,W)=>Q+t(W),0)}function jJ(J,Q,W,$=10){let Z=[],X=0;for(let G of J){let K=W(G),Y=t(K)+$;if(X+Y>Q)break;Z.push(G),X+=Y}return Z}function jW(J){if(J<1000)return`${J} tokens`;else if(J<1e6)return`${(J/1000).toFixed(1)}K tokens`;else return`${(J/1e6).toFixed(1)}M tokens`}class c extends GQ{static serviceType="memory";bm25Index=null;embeddingDimension;isInitialized=!1;longTermMemoryRepo;conversationSummaryRepo;capabilityDescription="State-of-the-art cognitive memory system with episodic, semantic, and procedural memory";static defaultConfig={consolidationThreshold:12,minConfidence:0.7,enableVectorSearch:!0,enableBM25:!0,retrievalLimit:5,tokenBudget:1000,defaultDecayRates:{EPISODIC:0.05,SEMANTIC:0.01,PROCEDURAL:0.02},enableContradictionDetection:!0,summarization:{enabled:!0,messagesPerSummary:7,summariesPerLevel:5,maxDepth:3,summaryTokenBudget:500}};constructor(J){super(J);this.config={...c.defaultConfig}}static async start(J){let Q=new c(J);return await Q.initialize(J),Q}async stop(){F.info("MemoryService stopped")}async initialize(J){if(this.runtime=J,this.loadConfiguration(),await this.ensureEmbeddingDimension(),this.longTermMemoryRepo=new KJ(J,this.embeddingDimension),this.conversationSummaryRepo=new YJ(J,this.embeddingDimension),F.info({config:this.config},"MemoryService initialized"),this.config.enableBM25)await this.rebuildBM25Index();this.isInitialized=!0}loadConfiguration(){let J=this.runtime.getSetting("MEMORY_CONSOLIDATION_THRESHOLD");if(J)this.config.consolidationThreshold=parseInt(J,10);let Q=this.runtime.getSetting("MEMORY_MIN_CONFIDENCE");if(Q)this.config.minConfidence=parseFloat(Q);let W=this.runtime.getSetting("MEMORY_ENABLE_VECTOR_SEARCH");if(F.debug({enableVector:W,type:typeof W,defaultValue:this.config.enableVectorSearch},"Loading MEMORY_ENABLE_VECTOR_SEARCH setting"),W!==void 0&&W!==null&&W!=="")this.config.enableVectorSearch=W==="true"||W===!0,F.info({enabled:this.config.enableVectorSearch},"Vector search explicitly configured via environment variable");else F.info({enabled:this.config.enableVectorSearch},"Vector search using default configuration");let $=this.runtime.getSetting("MEMORY_ENABLE_BM25");if(F.debug({enableBM25:$,type:typeof $,defaultValue:this.config.enableBM25},"Loading MEMORY_ENABLE_BM25 setting"),$!==void 0&&$!==null&&$!=="")this.config.enableBM25=$==="true"||$===!0,F.info({enabled:this.config.enableBM25},"BM25 search explicitly configured via environment variable");else F.info({enabled:this.config.enableBM25},"BM25 search using default configuration");let Z=this.runtime.getSetting("MEMORY_RETRIEVAL_LIMIT");if(Z)this.config.retrievalLimit=parseInt(Z,10);let X=this.runtime.getSetting("MEMORY_TOKEN_BUDGET");if(X)this.config.tokenBudget=parseInt(X,10);let G=this.runtime.getSetting("MEMORY_SUMMARY_ENABLED");if(F.debug({summaryEnabled:G,type:typeof G,defaultValue:this.config.summarization?.enabled},"Loading MEMORY_SUMMARY_ENABLED setting"),G!==void 0&&G!==null&&G!=="")this.config.summarization.enabled=G==="true"||G===!0,F.info({enabled:this.config.summarization.enabled},"Summarization explicitly configured via environment variable");else F.info({enabled:this.config.summarization.enabled},"Summarization using default configuration");let K=this.runtime.getSetting("MEMORY_MESSAGES_PER_SUMMARY");if(K)this.config.summarization.messagesPerSummary=parseInt(K,10);let Y=this.runtime.getSetting("MEMORY_SUMMARIES_PER_LEVEL");if(Y)this.config.summarization.summariesPerLevel=parseInt(Y,10);let j=this.runtime.getSetting("MEMORY_SUMMARY_MAX_DEPTH");if(j)this.config.summarization.maxDepth=parseInt(j,10);let N=this.runtime.getSetting("MEMORY_SUMMARY_TOKEN_BUDGET");if(N)this.config.summarization.summaryTokenBudget=parseInt(N,10)}async ensureEmbeddingDimension(){try{if(!this.runtime.getModel(o.TEXT_EMBEDDING)){F.warn("No TEXT_EMBEDDING model registered. Embeddings will not be generated.");return}let Q=await this.runtime.useModel(o.TEXT_EMBEDDING,{text:"test"});if(!Q||!Array.isArray(Q))throw Error("Invalid embedding received from model");let W=Q.length,$=e[W];if(!$)throw Error(`Unsupported embedding dimension: ${W}. Supported dimensions: ${Object.keys(e).join(", ")}`);this.embeddingDimension=$,F.info(`Memory embedding dimension set to ${W} (${$})`)}catch(J){throw F.error("Failed to ensure embedding dimension:",JSON.stringify(J)),J}}getConfig(){return{...this.config}}updateConfig(J){if(this.config={...this.config,...J},J.enableBM25!==void 0){if(J.enableBM25&&!this.bm25Index)this.rebuildBM25Index();else if(!J.enableBM25)this.bm25Index=null}}async storeLongTermMemory(J){let Q;if(this.embeddingDimension)try{let $=await p(this.runtime,J.embeddingContext);Q=y($)}catch($){F.warn("Failed to generate embedding for long-term memory:",JSON.stringify($))}let W=await this.longTermMemoryRepo.insert(J,Q);if(this.config.enableBM25&&this.bm25Index)await this.rebuildBM25Index();return W}async getLongTermMemory(J){return this.longTermMemoryRepo.findById(J)}async updateLongTermMemory(J,Q){let W;if(Q.embeddingContext!==void 0&&this.embeddingDimension)try{let $=await p(this.runtime,Q.embeddingContext);W=y($)}catch($){F.warn("Failed to regenerate embedding:",JSON.stringify($))}await this.longTermMemoryRepo.update(J,Q,W)}async deleteLongTermMemory(J){await this.longTermMemoryRepo.delete(J)}async getLongTermMemories(J,Q,W=20,$=!1){return this.longTermMemoryRepo.findByEntity(J,Q,W,$)}async handleContradiction(J,Q){let W=await this.searchLongTermMemories({entityId:J,query:Q.content,type:Q.type,limit:5,includeInactive:!1});if(W.length===0){await this.storeLongTermMemory(Q);return}let $=await this.detectContradiction(Q,W);if($){F.info({oldMemoryId:$.id,newContent:Q.content},"Contradiction detected, superseding old memory"),await this.updateLongTermMemory($.id,{isActive:!1});let Z=await this.storeLongTermMemory({...Q,supersedesId:$.id});F.info({newMemoryId:Z.id},"Stored superseding memory")}else await this.storeLongTermMemory(Q)}async detectContradiction(J,Q){let W=`# TASK: Contradiction Detection
10
+
11
+ You are analyzing whether a new long-term memory contradicts any existing long-term memories.
12
+
13
+ ## New Long-Term Memory:
14
+ "${J.content}"
15
+
16
+ ## Existing Long-Term Memories:
17
+ ${Q.map(($,Z)=>`${Z+1}. "${$.content}" (confidence: ${$.confidence}, created: ${$.createdAt.toISOString()})`).join(`
18
+ `)}
19
+
20
+ ## Instructions:
21
+ Determine if the new long-term memory directly contradicts any of the existing long-term memories. A contradiction means the statements cannot both be true.
22
+
23
+ Examples of contradictions:
24
+ - "User likes blue" vs "User hates blue"
25
+ - "User lives in Paris" vs "User lives in London"
26
+
27
+ Examples of non-contradictions (these are compatible):
28
+ - "User likes blue" vs "User likes blue only for clothes" (nuance, not contradiction)
29
+ - "User was in Paris" vs "User moved to London" (state change over time)
30
+
31
+ ## Output Format:
32
+ Return an XML response:
33
+
34
+ <response>
35
+ <hasContradiction>true or false</hasContradiction>
36
+ <contradictingMemoryIndex>number or null</contradictingMemoryIndex>
37
+ <reasoning>Explanation</reasoning>
38
+ </response>
39
+
40
+ If no contradiction is found, set hasContradiction to false and contradictingMemoryIndex to null.`;try{let $=await this.runtime.useModel(o.TEXT_LARGE,{prompt:W,temperature:0.2}),Z=typeof $==="string"?$:JSON.stringify($),X=YQ(Z);if(!X)return F.warn("Failed to parse contradiction detection XML response"),null;let G=jQ(typeof X.hasContradiction==="boolean"?X.hasContradiction?"true":"false":X.hasContradiction),K=null;if(X.contradictingMemoryIndex!==null&&X.contradictingMemoryIndex!=="null"){let Y=parseInt(X.contradictingMemoryIndex,10);if(!isNaN(Y))K=Y}if(G&&K!==null){let Y=Q[K];return F.info({reasoning:X.reasoning},"Contradiction detected"),Y}return null}catch($){return F.error({error:$},"Failed to detect contradiction"),null}}async searchLongTermMemories(J){let Q=J.limit||this.config.retrievalLimit,W=J.tokenBudget||this.config.tokenBudget,$=J.minConfidence!==void 0?J.minConfidence:this.config.minConfidence,Z=J.similarityThreshold!==void 0?J.similarityThreshold:0.3;F.debug({limit:Q,tokenBudget:W,minConfidence:$,similarityThreshold:Z,vectorSearchEnabled:this.config.enableVectorSearch,bm25Enabled:this.config.enableBM25},"Searching long-term memories");let X=[];if(this.config.enableVectorSearch)F.debug("Vector search enabled, searching..."),X=await this.vectorSearch(J,Z);F.debug({vectorResults:X.length},"Vector search results");let G=[];if(this.config.enableBM25)G=await this.bm25Search(J);let Y=RJ(X,G).filter((O)=>O.confidence>=$),N=CJ(Y).sort((O,P)=>P.finalScore-O.finalScore),U=N.slice(0,Q),_=jJ(U,W,(O)=>O.content,15);return F.debug({totalResults:N.length,afterCountLimit:U.length,afterTokenBudget:_.length,tokenBudget:W,estimatedTokens:_.reduce((O,P)=>O+t(P.content)+15,0)},"Applied token budget to memory retrieval"),await this.longTermMemoryRepo.updateAccessMetadata(_.map((O)=>O.id)),_}async vectorSearch(J,Q=0.3){if(!this.embeddingDimension)return F.warn("Embedding dimension not set, skipping vector search"),[];try{let W=await p(this.runtime,J.query),$=y(W);if(!$||!Array.isArray($))return F.warn("Failed to generate query embedding"),[];return await this.longTermMemoryRepo.vectorSearch(J,$,Q)}catch(W){return F.error("Failed to execute vector search:",JSON.stringify(W)),[]}}async bm25Search(J){if(!this.bm25Index)return[];try{let W=this.bm25Index.search(J.query,J.limit||20).map(async(Z)=>{let X=this.bm25Index.documents[Z.index];if(!X||!X.id)return F.warn({resultIndex:Z.index},"BM25 result has no document ID"),null;let G=await this.getLongTermMemory(X.id);if(!G)return null;if(G.entityId!==J.entityId)return null;if(!J.includeInactive&&!G.isActive)return null;if(J.type&&G.type!==J.type)return null;if(J.minConfidence&&G.confidence<J.minConfidence)return null;return{...G,relevanceScore:Z.score,activationScore:0,finalScore:0}});return(await Promise.all(W)).filter((Z)=>Z!==null)}catch(Q){return F.error({error:Q},"BM25 search failed"),[]}}async rebuildBM25Index(){try{let Q=(await this.longTermMemoryRepo.fetchAllActive()).map((W)=>({id:W.id,content:W.content,embeddingContext:W.embeddingContext}));this.bm25Index=new NQ(Q,{k1:1.2,b:0.75,stemming:!0,minLength:2}),F.info({documentCount:Q.length},"Rebuilt BM25 index")}catch(J){F.error({error:J},"Failed to rebuild BM25 index"),this.bm25Index=null}}async getFormattedLongTermMemoriesForContext(J,Q,W){let $=await this.searchLongTermMemories({entityId:J,query:Q,roomId:W,limit:this.config.retrievalLimit});return hJ($)}async storeSummary(J){let Q;if(this.embeddingDimension)try{let W=await p(this.runtime,J.content);Q=y(W)}catch(W){F.warn("Failed to generate embedding for summary:",JSON.stringify(W))}return this.conversationSummaryRepo.insert(J,Q)}async getSummariesByLevel(J,Q){return this.conversationSummaryRepo.findByLevel(J,Q)}async searchSummaries(J){if(!this.embeddingDimension)return F.warn("Embedding dimension not set, skipping summary search"),[];let Q=J.limit||5,W=J.tokenBudget||this.config.summarization?.summaryTokenBudget||500;try{let $=await p(this.runtime,J.query),Z=y($);if(!Z||!Array.isArray(Z))return F.warn("Failed to generate query embedding"),[];let X=await this.conversationSummaryRepo.vectorSearch(J.entityId,J.roomId,Z,Q),G=jJ(X,W,(K)=>K.content,10);return await this.conversationSummaryRepo.updateAccessMetadata(G.map((K)=>K.id)),G}catch($){return F.error("Failed to search summaries:",JSON.stringify($)),[]}}async getMostRecentLevel1Summary(J,Q){try{let W=await this.conversationSummaryRepo.findByLevel(J,1);if(W.length===0)return null;let $=W.filter((Z)=>Z.entityId===Q).sort((Z,X)=>X.endTime.getTime()-Z.endTime.getTime());return $.length>0?$[0]:null}catch(W){return F.error("Failed to get most recent Level 1 summary:",JSON.stringify(W)),null}}}import{logger as L,ModelType as UQ}from"@elizaos/core";var EJ=`You are the "Cortex" — an advanced Memory Extraction Engine.
41
+ Your function is to parse conversation logs and extract persistent facts into a structured database format.
42
+
43
+ # CORE DIRECTIVE: "Subject-First" Extraction
44
+ You must rephrase memories to focus on the *topic*, not the user. This optimizes vector retrieval.
45
+ - BAD: "User likes to trade Bitcoin." (Too generic)
46
+ - GOOD: "Bitcoin (BTC) is a preferred trading asset." (Topic-focused)
47
+
48
+ # COMPRESSION RULES (CRITICAL)
49
+ 1. **Aggressive Filtering**: Most user chatter is noise. If it won't be relevant in 30 days, DO NOT extract it.
50
+ 2. **Merge & Dedupe**: Do not create three separate memories for one topic. Combine them.
51
+ - *Input:* "I like Red. I also like Blue. And Green."
52
+ - *Output:* "Red, Blue, and Green are the preferred colors."
53
+ 3. **Conflict Resolution**: If a new fact contradicts an old one, mark 'isContradiction' as true.
54
+
55
+ # OUTPUT FORMAT
56
+ Phase 1: [ANALYSIS]
57
+ - List extracted points.
58
+ - MARK items as [TRANSIENT] (Ignore) or [MERGE] (Combine).
59
+ - Refine the final wording.
60
+
61
+ Phase 2: [MEMORIES]
62
+ Format: \`MEM|TYPE|CATEGORY|CONFIDENCE|IS_CONTRADICTION|CONTENT\`
63
+
64
+ Types: EPISODIC, SEMANTIC, PROCEDURAL
65
+ Categories: bio, health, finance, preferences, relationships, skills, work
66
+ `;function IJ(J){return`# INPUT DATA
67
+ **Reference Date:** ${new Date().toISOString()} (Use this to resolve relative dates like "yesterday" or "next Friday")
68
+
69
+ <conversation_log>
70
+ ${J}
71
+ </conversation_log>
72
+
73
+ # FEW-SHOT EXAMPLES (DENSE INPUTS)
74
+
75
+ <example_1_finance_consolidation>
76
+ Input: "Okay, market is looking bad. I'm closing my ETH long. Too risky. Also, can you check the weather in Tokyo? I might fly there. Actually, cancel all my limit orders on Solana too, I want to go all cash for the weekend."
77
+ Output:
78
+ [ANALYSIS]
79
+ - "Market looking bad" -> Context, not memory.
80
+ - "Closing ETH long" -> Actionable preference change.
81
+ - "Check weather" -> [TRANSIENT] Ignore.
82
+ - "Fly to Tokyo" -> [TRANSIENT] "Might" implies uncertainty. Ignore until confirmed.
83
+ - "Cancel SOL orders" -> Actionable strategy.
84
+ - "Go all cash" -> High-level strategy.
85
+ - MERGE: Combine ETH close, SOL cancel, and Cash strategy into one record.
86
+ [MEMORIES]
87
+ MEM|PROCEDURAL|finance|0.95|true|Portfolio Strategy: All positions (ETH, SOL) liquidated; Cash-only stance adopted for weekend.
88
+ </example_1_finance_consolidation>
89
+
90
+ <example_2_companion_emotional>
91
+ Input: "I had a huge fight with my sister, Jenny. She's so controlling. I don't want to talk about her anymore. Let's play a game. Maybe chess? Actually no, I hate chess, it's boring. Let's do a quiz."
92
+ Output:
93
+ [ANALYSIS]
94
+ - "Fight with sister Jenny" -> Relationship dynamic.
95
+ - "She's controlling" -> Character attribute.
96
+ - "Don't want to talk about her" -> Boundary/Preference.
97
+ - "Play a game" -> [TRANSIENT] Immediate desire.
98
+ - "Hate chess" -> Negative Preference.
99
+ - "Do a quiz" -> [TRANSIENT] Immediate desire.
100
+ - MERGE: Combine Jenny details. Separate Chess preference.
101
+ [MEMORIES]
102
+ MEM|EPISODIC|relationships|0.9|false|Jenny (sister) is characterized as controlling; currently a sensitive topic to be avoided.
103
+ MEM|SEMANTIC|preferences|0.95|false|Chess is a disliked activity (described as boring).
104
+ </example_2_companion_emotional>
105
+
106
+ <example_3_coding_stack>
107
+ Input: "This node_modules folder is huge. I'm done with NPM. From now on we only use Bun for all projects. It's faster. Also, help me debug this loop. It's printing 'undefined'."
108
+ Output:
109
+ [ANALYSIS]
110
+ - "node_modules huge" -> Rationale.
111
+ - "Done with NPM" -> Deprecation.
112
+ - "Use Bun" -> New Standard.
113
+ - "Debug this loop" -> [TRANSIENT] Immediate task.
114
+ - MERGE: Bun adoption and NPM rejection.
115
+ [MEMORIES]
116
+ MEM|PROCEDURAL|skills|0.95|true|Bun is the mandated package manager; NPM usage is deprecated/forbidden.
117
+ </example_3_coding_stack>
118
+
119
+ <example_4_health_routine>
120
+ Input: "I ate a burger today, felt kinda heavy. I think I'm going to start intermittent fasting. 16/8 window. Start eating at 12pm, stop at 8pm. Remind me to drink water."
121
+ Output:
122
+ [ANALYSIS]
123
+ - "Ate a burger" -> [TRANSIENT] One-off meal.
124
+ - "Felt heavy" -> [TRANSIENT] Temporary sensation.
125
+ - "Start intermittent fasting" -> New Health Protocol.
126
+ - "16/8 window, 12-8" -> Specific details of protocol.
127
+ - "Remind me to drink water" -> [TRANSIENT] Command.
128
+ - MERGE: All fasting details into one concise protocol.
129
+ [MEMORIES]
130
+ MEM|PROCEDURAL|health|0.9|false|Intermittent Fasting (16/8 protocol) adopted: Eating window restricted to 12pm-8pm.
131
+ </example_4_health_routine>
132
+
133
+ <example_5_work_milestones>
134
+ Input: "Meeting went well. The client, Apex Corp, agreed to the $50k budget. But they want the deadline moved to March 1st. Can you write a thank you note? Oh, and I need to update my resume."
135
+ Output:
136
+ [ANALYSIS]
137
+ - "Meeting went well" -> [TRANSIENT] Sentiment.
138
+ - "Apex Corp" -> Client Entity.
139
+ - "$50k budget" -> Financial Fact.
140
+ - "Deadline March 1st" -> Project Constraint.
141
+ - "Write note" -> [TRANSIENT] Task.
142
+ - "Update resume" -> [TRANSIENT] Generic task unless specific details given.
143
+ - MERGE: Client details, budget, and deadline.
144
+ [MEMORIES]
145
+ MEM|SEMANTIC|work|1.0|false|Apex Corp project secured: $50k budget with March 1st deadline.
146
+ </example_5_work_milestones>
147
+
148
+ # EXTRACTION CHECKLIST
149
+ 1. **Search for STATE CHANGES**: Did the user move, change jobs, break up, or alter a portfolio? These are high-value.
150
+ 2. **Search for HARD CONSTRAINTS**: Look for phrases like "Never do X", "Always use Y", "I hate Z".
151
+ 3. **COMPRESSION**:
152
+ - You have received a long conversation.
153
+ - **MERGE** related details into single, dense records.
154
+ - **IGNORE** all small talk, greetings, and transient requests.
155
+ 4. **QUALITY CONTROL**: If a fact feels temporary or weak, **DO NOT** extract it. Silence is better than noise.
156
+
157
+ Begin the [ANALYSIS] phase now.`}function PW(J,Q){return`Does this new memory contradict any existing memories?
158
+
159
+ New: "${J}"
160
+
161
+ Existing:
162
+ ${Q.map((W,$)=>`${$+1}. "${W.content}" (confidence: ${W.confidence})`).join(`
163
+ `)}
164
+
165
+ A contradiction means both statements cannot be true simultaneously.
166
+
167
+ TRUE contradictions:
168
+ - "User likes blue" vs "User hates blue"
169
+ - "User lives in Paris" vs "User lives in London"
170
+ - "User is vegetarian" vs "User eats meat"
171
+
172
+ NOT contradictions:
173
+ - "User likes blue" vs "User likes blue for clothes" (nuance)
174
+ - "User was in Paris" vs "User moved to London" (time change)
175
+ - "User likes Python" vs "User likes JavaScript" (not exclusive)
176
+
177
+ <response>
178
+ <hasContradiction>true or false</hasContradiction>
179
+ <contradictingIndex>number or null</contradictingIndex>
180
+ <reasoning>Brief explanation</reasoning>
181
+ </response>`}var l=new Map,fJ={name:"CONSOLIDATION",similes:["MEMORY_CONSOLIDATION","EXTRACT_FACTS","MEMORY_BUFFER"],description:"Buffers conversation messages and performs periodic consolidation to extract persistent facts using LLM analysis. Distinguishes transient intents from long-term knowledge.",validate:async(J,Q)=>{if(!l.has(Q.roomId))l.set(Q.roomId,[]);l.get(Q.roomId).push(Q);let W=J.getService("memory");if(!W)return!1;let $=W.getConfig(),Z=l.get(Q.roomId).length,X=Z>=$.consolidationThreshold;if(X)L.info({roomId:Q.roomId,bufferSize:Z,threshold:$.consolidationThreshold},"Consolidation threshold reached");return X},handler:async(J,Q)=>{let W=Q.roomId;try{let $=J.getService("memory");if(!$){L.warn("Memory service not available for consolidation");return}let Z=l.get(W)||[];if(Z.length===0)return;L.info({roomId:W,messageCount:Z.length},"Starting memory consolidation");let X=Z.map((Y,j)=>{let N=typeof Y.content==="string"?Y.content:Y.content.text||JSON.stringify(Y.content);return`[${j+1}] ${Y.entityId}: ${N}`}).join(`
182
+ `),G=IJ(X),K=J.character.system;try{J.character.system=EJ,L.debug("Calling LLM for memory extraction");let Y=await J.useModel(UQ.TEXT_LARGE,{prompt:G,temperature:0.3}),j=FQ(Y);L.debug({reasoning:j.reasoningTrace,extracted:j.extractedMemories.length},"Extraction complete");let N=$.getConfig(),U=j.extractedMemories.filter((_)=>_.confidence>=N.minConfidence);L.info({total:j.extractedMemories.length,valid:U.length,minConfidence:N.minConfidence},"Filtered extracted memories");for(let _ of U)await AQ(J,$,W,Z,_);l.set(W,[]),L.info({roomId:W,stored:U.length},"Memory consolidation complete")}finally{J.character.system=K}}catch($){L.error({error:$,roomId:W},"Consolidation evaluator failed")}},examples:[]};function FQ(J){try{let Q=typeof J==="string"?J:JSON.stringify(J),W=Q.match(/\[ANALYSIS\](.*?)(?:\[MEMORIES\]|$)/s),$=W?W[1].trim():"",Z=Q.match(/\[MEMORIES\](.*?)$/s),X=Z?Z[1].trim():"",G=[];if(X){let K=X.split(`
183
+ `);for(let Y of K){let j=Y.trim();if(!j||!j.startsWith("MEM|"))continue;let N=j.split("|");if(N.length<6){L.warn({line:j},"Skipping malformed memory line (insufficient fields)");continue}let U=N[1].trim(),_=N[2].trim(),O=N[3].trim(),P=N[4].trim(),q=N.slice(5).join("|").trim();if(!["EPISODIC","SEMANTIC","PROCEDURAL"].includes(U)){L.warn({type:U,line:j},"Invalid memory type");continue}if(!_){L.warn({line:j},"Missing category");continue}let V=parseFloat(O);if(isNaN(V)||V<0||V>1){L.warn({confidenceStr:O,line:j},"Invalid confidence value");continue}let z=P.toLowerCase()==="true";if(!q){L.warn({line:j},"Missing content");continue}let r={category:_};G.push({type:U,content:q,confidence:V,isContradiction:z,metadata:r})}}return{reasoningTrace:$,transientSummary:"",extractedMemories:G}}catch(Q){return L.error({error:Q},"Failed to parse consolidation response"),{reasoningTrace:"Parse error",transientSummary:"",extractedMemories:[]}}}async function AQ(J,Q,W,$,Z){let X=$[0]?.entityId||J.agentId,G=_Q(Z),K=Q.getConfig(),Y=K.defaultDecayRates[Z.type],j={agentId:J.agentId,entityId:X,roomId:W,type:Z.type,content:Z.content,embeddingContext:G,confidence:Z.confidence,decayRate:Y,decayFunction:"EXPONENTIAL",source:{sessionId:W,messageId:Z.sourceMessageId,textSnippet:Z.content.substring(0,200)},metadata:Z.metadata||{}};if(K.enableContradictionDetection&&Z.isContradiction)await Q.handleContradiction(X,j);else await Q.storeLongTermMemory(j)}function _Q(J){let Q={EPISODIC:"Event",SEMANTIC:"Fact",PROCEDURAL:"Skill"}[J.type],W=J.metadata?.category||"general";return`[${Q} about ${W}]: ${J.content}`}import{logger as B,ModelType as vJ}from"@elizaos/core";var wJ=`You are "Chronos", a master summarizer.
184
+ Your function is to condense conversation logs into concise, subject-first narrative summaries.
185
+
186
+ # CORE DIRECTIVE: "Subject-First" Summarization
187
+ You must rephrase the narrative to focus on the *topic*, not the user. This optimizes vector retrieval.
188
+ - BAD: "User asked about Python." (Too generic)
189
+ - GOOD: "Python programming inquiries were addressed." (Topic-focused)
190
+
191
+ # COMPRESSION RULES
192
+ 1. **Be Concise**: Target 2-4 sentences. Maximum 100 words.
193
+ 2. **Be Factual**: No interpretation, no speculation. Only what actually happened.
194
+ 3. **Be Narrative**: Write as a story, not a bullet list.
195
+ 4. **Preserve Key Facts**: If the user revealed important information (preferences, identity, needs), include it.
196
+ 5. **Exclude Trivia**: Skip greetings, acknowledgments, and filler conversation.
197
+
198
+ # OUTPUT FORMAT
199
+ Phase 1: [ANALYSIS]
200
+ - Identify key topics.
201
+ - Draft the summary.
202
+ - Refine wording to be subject-first.
203
+
204
+ Phase 2: [RESULT]
205
+ Format: \`SUMM|TAGS|CONTENT\`
206
+ - TAGS: Comma-separated list of key topics (lowercase)
207
+ - CONTENT: The narrative summary text (must be a single line, no newlines)
208
+ `;function NJ(J,Q){return`${Q?`
209
+ # PREVIOUS SUMMARY
210
+ <previous_summary>
211
+ ${Q}
212
+ </previous_summary>
213
+
214
+ **Note**: The above is what was discussed before. Ensure your new summary:
215
+ - Does not duplicate information already captured in the previous summary
216
+ - Focuses only on the NEW conversation below
217
+ - Maintains continuity (e.g., "Conversation continued with...")
218
+ `:""}
219
+ # INPUT DATA
220
+ <messages>
221
+ ${J}
222
+ </messages>
223
+
224
+ # FEW-SHOT EXAMPLES
225
+
226
+ <example_1_task_oriented>
227
+ Input:
228
+ [Message 1] User: I need help deploying my React app to Vercel
229
+ [Message 2] Agent: Sure! First, make sure you have the Vercel CLI installed...
230
+ [Message 3] User: Done. What's next?
231
+ [Message 4] Agent: Run 'vercel' in your project directory...
232
+ [Message 5] User: It worked! Thanks!
233
+
234
+ Output:
235
+ [ANALYSIS]
236
+ - Topic: React app deployment to Vercel.
237
+ - Action: CLI installation and deployment.
238
+ - Outcome: Success.
239
+ - Draft: User requested help... -> React app deployment...
240
+ [RESULT]
241
+ SUMM|deployment,react,vercel,cli|React app deployment to Vercel was successfully completed following CLI installation and configuration guidance.
242
+ </example_1_task_oriented>
243
+
244
+ <example_2_identity_revelation>
245
+ Input:
246
+ [Message 1] User: I'm working on a side project in my spare time
247
+ [Message 2] Agent: That's great! What kind of project?
248
+ [Message 3] User: A machine learning app for analyzing stock data. I'm a data scientist by profession.
249
+ [Message 4] Agent: Interesting! Are you using Python?
250
+ [Message 5] User: Yeah, mostly PyTorch and pandas.
251
+
252
+ Output:
253
+ [ANALYSIS]
254
+ - Identity: Data scientist.
255
+ - Project: Stock data analysis (ML).
256
+ - Tech Stack: Python, PyTorch, pandas.
257
+ - Draft: User discussed... -> Stock data analysis project...
258
+ [RESULT]
259
+ SUMM|machine learning,data science,python,stocks|Stock data analysis project (Machine Learning) utilizing Python (PyTorch, pandas) is in development by a data scientist.
260
+ </example_2_identity_revelation>
261
+
262
+ <example_3_chitchat>
263
+ Input:
264
+ [Message 1] User: Hey, how's it going?
265
+ [Message 2] Agent: I'm doing well, thanks for asking! How can I help you today?
266
+ [Message 3] User: Just saying hi
267
+ [Message 4] Agent: Nice to hear from you!
268
+
269
+ Output:
270
+ [ANALYSIS]
271
+ - Content: Greetings only.
272
+ - Substance: None.
273
+ [RESULT]
274
+ SUMM|greeting,casual|Casual greeting exchanged; no substantive topics discussed.
275
+ </example_3_chitchat>
276
+
277
+ Begin the [ANALYSIS] phase now.`}var xJ=`You are "Chronos", a Meta-Summarization Agent.
278
+ Your task is to compress multiple conversation summaries into a single, higher-level summary.
279
+
280
+ # MISSION
281
+ Transform a list of conversation summaries into one concise meta-summary that captures:
282
+ 1. **Overarching themes** across the summaries
283
+ 2. **Key events or milestones** (e.g., "User onboarded", "Project completed")
284
+ 3. **Evolving context** (e.g., "User's preferences shifted from X to Y")
285
+
286
+ # RULES
287
+ - **Subject-First**: Focus on the topic, not the user.
288
+ - **Abstract Higher**: Don't repeat specifics from each summary. Find the pattern.
289
+ - **Chronological Flow**: Maintain temporal order if it matters.
290
+ - **Preserve Critical Facts**: If summaries mention important identity or preferences, keep them.
291
+
292
+ # OUTPUT FORMAT
293
+ Phase 1: [ANALYSIS]
294
+ - Identify themes and milestones.
295
+ - Combine related points.
296
+ - Refine to subject-first.
297
+
298
+ Phase 2: [RESULT]
299
+ Format: \`SUMM|TAGS|CONTENT\`
300
+ - TAGS: Comma-separated list of key topics (lowercase)
301
+ - CONTENT: The meta-summary text (must be a single line, no newlines)
302
+ `;function TJ(J){return`# INPUT DATA
303
+ <summaries>
304
+ ${J}
305
+ </summaries>
306
+
307
+ # FEW-SHOT EXAMPLES
308
+
309
+ <example_1_meta_summary>
310
+ Input:
311
+ <summary1>Stock data analysis project (Machine Learning) utilizing Python (PyTorch, pandas) is in development by a data scientist.</summary1>
312
+ <summary2>Flask and Vercel were suggested for ML model deployment to a web app.</summary2>
313
+ <summary3>CORS configuration issues were resolved, leading to successful deployment.</summary3>
314
+
315
+ Output:
316
+ [ANALYSIS]
317
+ - Theme: ML App Development & Deployment.
318
+ - Flow: Development -> Stack Choice -> Deployment -> Troubleshooting -> Success.
319
+ - Draft: User, a data scientist... -> Machine learning stock analysis app...
320
+ [RESULT]
321
+ SUMM|data science,machine learning,python,deployment,flask,vercel|Machine learning stock analysis app (Python/PyTorch) was developed and successfully deployed to Vercel using Flask after resolving CORS configuration issues.
322
+ </example_1_meta_summary>
323
+
324
+ Begin the [ANALYSIS] phase now.`}function UJ(J){return Math.ceil(J.length/4)}var g=new Map,SJ={name:"SUMMARIZATION",similes:["HIERARCHICAL_SUMMARIZATION","EPISODIC_COMPRESSION","CONVERSATION_SUMMARY"],description:"Hierarchical conversation summarization that compresses message history into multi-level narrative summaries for token-efficient long-term episodic memory.",validate:async(J,Q)=>{let W=J.getService("memory");if(!W)return!1;let $=W.getConfig();if(!$.summarization?.enabled)return B.debug("Summarization is not enabled"),!1;if(!g.has(Q.roomId))g.set(Q.roomId,0);let Z=g.get(Q.roomId)+1;g.set(Q.roomId,Z);let X=$.summarization.messagesPerSummary;B.debug({currentCount:Z,threshold:X,messageId:Q.id,entityId:Q.entityId,roomId:Q.roomId},"Message counted for summarization (user + agent messages)");let G=Z>=X;if(G)B.info({roomId:Q.roomId,messageCount:Z,threshold:X},"Summarization threshold reached (Level 1) - triggering summarization");return G},handler:async(J,Q)=>{let W=J.getService("memory");if(!W){B.warn("MemoryService not available for summarization");return}if(!W.getConfig().summarization?.enabled)return;let Z=g.get(Q.roomId)||0;if(Z===0)return;B.info({roomId:Q.roomId,messageCount:Z},"Starting Level 1 summarization - pulling messages from database");try{let X=await W.getMostRecentLevel1Summary(Q.roomId,Q.entityId),G=await OQ(J,Q.roomId,X?.endTime);if(G.length===0){B.warn({roomId:Q.roomId},"No messages found for summarization");return}let K=await VQ(J,W,G,Q.roomId,X);if(K)B.info({summaryId:K.id,tokenCount:K.tokenCount,messageCount:G.length,startTime:K.startTime,endTime:K.endTime},"Created Level 1 summary from database messages"),g.set(Q.roomId,0),await MJ(J,W,K.roomId,K.level)}catch(X){B.error({error:X,roomId:Q.roomId},"Failed to create summary")}},examples:[]};async function OQ(J,Q,W){let $=await J.getMemories({tableName:"messages",roomId:Q,count:1000,unique:!1}),Z=$.filter((G)=>!(G.content?.type==="action_result"&&G.metadata?.type==="action_result")),X=Z;if(W)X=Z.filter((G)=>{if(!G.createdAt)return!1;return new Date(G.createdAt)>W});return X.sort((G,K)=>(G.createdAt||0)-(K.createdAt||0)),B.debug({roomId:Q,totalMessages:$.length,dialogueMessages:Z.length,filteredMessages:X.length,lastSummaryEndTime:W?.toISOString()},"Fetched messages for summarization"),X}function bJ(J){try{let Q=typeof J==="string"?J:JSON.stringify(J),W=Q.match(/\[ANALYSIS\](.*?)(?:\[RESULT\]|$)/s),$=W?W[1].trim():"",Z=Q.match(/\[RESULT\](.*?)$/s),X=Z?Z[1].trim():"",G="",K="";if(X){let Y=X.split(`
325
+ `);for(let j of Y){let N=j.trim();if(N.startsWith("SUMM|")){let U=N.split("|");if(U.length>=3){K=U[1].trim(),G=U.slice(2).join("|").trim();break}}}}return{summary:G,keyTopics:K,reasoningTrace:$}}catch(Q){return B.error({error:Q},"Failed to parse summarization response"),{summary:"",keyTopics:"",reasoningTrace:""}}}async function VQ(J,Q,W,$,Z){let X=W.map((Y,j)=>{let N=typeof Y.content==="string"?Y.content:Y.content.text||"",U=Y.entityId===J.agentId?"Agent":"User";return`[${Y.createdAt?new Date(Y.createdAt).toISOString():"Unknown time"}] ${U}: ${N}`}).join(`
326
+ `),G;if(Z)G=NJ(X,Z.content);else G=NJ(X);let K=J.character.system;try{J.character.system=wJ,B.debug("Calling LLM for Level 1 summarization with timestamped conversation log");let Y=await J.useModel(vJ.TEXT_LARGE,{prompt:G,temperature:0.3});J.character.system=K;let{summary:j,keyTopics:N,reasoningTrace:U}=bJ(Y);if(!j)return B.warn({reasoningTrace:U},"No summary extracted from LLM response"),null;let _=UJ(j),O=W[0].createdAt?new Date(W[0].createdAt):new Date,P=W[W.length-1].createdAt?new Date(W[W.length-1].createdAt):new Date,q={agentId:J.agentId,entityId:W[0].entityId,roomId:$,level:1,parentSummaryId:void 0,content:j,tokenCount:_,startTime:O,endTime:P,sourceCount:W.length,sourceIds:W.map((V)=>V.id),metadata:{keyTopics:N,hasPreviousSummary:!!Z}};return await Q.storeSummary(q)}catch(Y){return B.error({error:Y},"Failed to call LLM for Level 1 summarization"),J.character.system=K,null}}async function MJ(J,Q,W,$){let Z=Q.getConfig();if(!Z.summarization)return;if($>=Z.summarization.maxDepth){B.debug({currentLevel:$,maxDepth:Z.summarization.maxDepth},"Max depth reached");return}let X=await Q.getSummariesByLevel(W,$),G=Z.summarization.summariesPerLevel;if(X.length<G)return;if(B.info({level:$,count:X.length,nextLevel:$+1},`Triggering Level ${$+1} summarization`),await kQ(J,Q,X,W,$+1))await MJ(J,Q,W,$+1)}async function kQ(J,Q,W,$,Z){let X=W.map((Y,j)=>`<summary${j+1}>${Y.content}</summary${j+1}>`).join(`
327
+ `),G=TJ(X),K=J.character.system;try{J.character.system=xJ;let Y=await J.useModel(vJ.TEXT_LARGE,{prompt:G,temperature:0.3});J.character.system=K;let{summary:j,keyTopics:N,reasoningTrace:U}=bJ(Y);if(!j)return B.warn({reasoningTrace:U},"No higher-level summary extracted from LLM response"),null;let _=UJ(j),O=new Date(Math.min(...W.map((V)=>V.startTime.getTime()))),P=new Date(Math.max(...W.map((V)=>V.endTime.getTime()))),q={agentId:J.agentId,entityId:W[0].entityId,roomId:$,level:Z,parentSummaryId:void 0,content:j,tokenCount:_,startTime:O,endTime:P,sourceCount:W.length,sourceIds:W.map((V)=>V.id),metadata:{keyTopics:N,compressedSummaries:W.length}};return await Q.storeSummary(q)}catch(Y){return B.error({error:Y,level:Z},"Failed to create higher-level summary"),J.character.system=K,null}}import{logger as a,addHeader as FJ}from"@elizaos/core";var pJ={name:"LONG_TERM_MEMORY",description:"User knowledge and facts (semantic + procedural memory)",position:80,get:async(J,Q,W)=>{try{let $=J.getService("memory");if(!$)return a.warn("Memory service not available"),{data:{},values:{},text:""};let{entityId:Z,roomId:X}=Q,G=typeof Q.content==="string"?Q.content:Q.content.text||JSON.stringify(Q.content);a.debug({entityId:Z,roomId:X,queryLength:G.length},"Retrieving unified memories");let K=$.getConfig(),[Y,j,N]=await Promise.all([$.searchLongTermMemories({entityId:Z,query:G,roomId:X,type:"SEMANTIC",limit:K.retrievalLimit,minConfidence:K.minConfidence,similarityThreshold:0.15}),$.searchLongTermMemories({entityId:Z,query:G,roomId:X,type:"PROCEDURAL",limit:Math.floor(K.retrievalLimit/2),minConfidence:K.minConfidence,similarityThreshold:0.15}),$.searchLongTermMemories({entityId:Z,query:G,roomId:X,type:"EPISODIC",limit:K.retrievalLimit,minConfidence:K.minConfidence,similarityThreshold:0.15})]),U=[];if(Y.length>0){let V=Y.map((z)=>`- ${z.content} (confidence: ${z.confidence.toFixed(2)}, strength: ${z.activationScore.toFixed(2)})`).join(`
328
+ `);U.push(FJ("## Semantic Knowledge (Facts)",V))}if(j.length>0){let V=j.map((z)=>`- ${z.content}`).join(`
329
+ `);U.push(FJ("## Procedural Knowledge (Skills & Patterns)",V))}if(N.length>0){let V=N.map((z)=>`- ${z.content} (occurred: ${z.createdAt?new Date(z.createdAt).toLocaleDateString():"Unknown"})`).join(`
330
+ `);U.push(FJ("## Significant Past Events",V))}let _=U.join(`
331
+
332
+ `),O={semanticMemories:Y,proceduralMemories:j,episodicMemories:N,config:{retrievalLimit:K.retrievalLimit,tokenBudget:K.tokenBudget}},P={longTermMemories:_},q=_;return a.info({semanticCount:Y.length,proceduralCount:j.length,episodicCount:N.length},"Retrieved long-term memory facts"),{data:O,values:P,text:q}}catch($){return a.error({error:$},"Failed to retrieve long-term memories"),{data:{},values:{longTermMemories:""},text:""}}}};import{addHeader as m,ChannelType as s,formatMessages as PQ,formatPosts as HQ,getEntityDetails as BQ,logger as T}from"@elizaos/core";var yJ=(J)=>({overlapUserMessageCount:parseInt(J.getSetting("CONTEXT_OVERLAP_USER_MESSAGES")||"2",10)});async function qQ(J,Q){let[W,$,Z]=await Promise.all([BQ({runtime:J,roomId:Q}),J.getRoom(Q),J.getMemories({tableName:"messages",roomId:Q,count:100,unique:!1})]);return{entities:W,room:$,allMessages:Z}}function LQ(J){let Q=J.filter((W)=>!(W.content?.type==="action_result"&&W.metadata?.type==="action_result"));return Q.sort((W,$)=>(W.createdAt||0)-($.createdAt||0)),Q}async function zQ(J,Q,W,$){let Z="",X=-1,G=J.getService("memory");if(!G?.searchSummaries)return{compressedHistoryText:Z,lastSummarizedIndex:X};try{let K=await G.searchSummaries({entityId:Q.entityId,roomId:Q.roomId,query:typeof Q.content==="string"?Q.content:Q.content.text||"",limit:3,tokenBudget:500});if(K.length===0)return{compressedHistoryText:Z,lastSummarizedIndex:X};X=DQ(K,W);let Y=K.map((N)=>{return`**[${N.level===1?"Recent Session":`Overview (L${N.level})`}]** ${N.content}`}).join(`
333
+
334
+ `),j=`# Conversation History (Compressed)
335
+ **Session Started:** ${AJ($)}`;Z=m(j,Y),T.debug({summaryCount:K.length,totalTokens:K.reduce((N,U)=>N+U.tokenCount,0),lastSummarizedIndex:X},"Using hierarchical summaries for compressed history")}catch(K){T.warn({error:K},"Failed to retrieve summaries")}return{compressedHistoryText:Z,lastSummarizedIndex:X}}function DQ(J,Q){let W=J.filter((Z)=>Z.level===1);if(W.length===0)return-1;let $=new Set;W.forEach((Z)=>{Z.sourceIds.forEach((X)=>$.add(X))});for(let Z=Q.length-1;Z>=0;Z--)if($.has(Q[Z].id))return T.debug({lastSummarizedIndex:Z,totalMessages:Q.length,summarizedCount:$.size},"Determined last summarized message index"),Z;return-1}function CQ(J,Q,W,$,Z){let X;if(W>=0&&$){let G=Q.slice(0,W+1),Y=G.filter((U)=>U.entityId!==J.agentId).slice(-Z),j=Q.slice(W+1),N=W+1;if(Y.length>0){let U=Y[0].id,_=Q.findIndex((O)=>O.id===U);if(_>=0)N=_}X=Q.slice(N),T.debug({lastSummarizedIndex:W,summarizedMessageCount:G.length,overlapStartIndex:N,overlapSize:W+1-N,newUnsummarizedCount:j.length,bufferSize:X.length,totalDialogueMessages:Q.length,overlapUserMessageCount:Z},`Dynamic buffer: [overlap: last ${Z} user msgs from summary] + [all new unsummarized messages]`)}else X=Q,T.debug({bufferSize:X.length,totalMessages:Q.length},"Using full conversation: no summaries yet");return{bufferMessages:X,lastSummarizedIndex:W}}function AJ(J){return new Date(J).toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1})}function RQ(J){return J.replace(/\s*\[[\w\-]+\]/g,"").replace(/\s*\([^)]*'s internal thought:[^)]*\)/gi,"").split(`
336
+ `).map((Q)=>Q.trim()).join(`
337
+ `).replace(/\n{3,}/g,`
338
+
339
+ `)}async function hQ(J,Q,W,$){let Z=W?.type?W.type===s.FEED||W.type===s.THREAD:!1,[X,G]=await Promise.all([PQ({messages:J,entities:Q}),HQ({messages:J,entities:Q,conversationHeader:!1})]),K=(Z?G:X)||"";K=RQ(K);let Y=J.length>0?J[0].createdAt:null,j=J.length>0?J[J.length-1].createdAt:null,N=`# Recent Messages (Last ${J.length})`;if(Y&&j)N+=`
340
+ **Time Range:** ${AJ(Y)} - ${AJ(j)}`;return K?m(N,K):""}function EQ(J,Q){let W=J.metadata,$=Q.find((Y)=>Y.id===J.entityId)?.names[0]||W?.entityName||"Unknown User",Z=J.content.text,X=!!Z?.trim(),G=X?m("# Current Message",`**From ${$}:** ${Z}`):"",K=X?m("# Response Focus",`Reply to **${$}**'s current message above. Stay relevant to their question. Don't repeat previous responses unless asked again.`):"";return{receivedMessageHeader:G,focusHeader:K}}function IQ(J,Q,W,$){return[J,Q,W,$].filter(Boolean).join(`
341
+
342
+ `)}var cJ={name:"RECENT_CONVERSATION_SUMMARY",description:"Intelligent context management combining recent messages with hierarchical summaries for optimal token efficiency",position:100,get:async(J,Q)=>{try{let{roomId:W}=Q,$=yJ(J),{entities:Z,room:X,allMessages:G}=await qQ(J,W),K=LQ(G),Y=K.length>0?K[0].createdAt||Date.now():Date.now(),{compressedHistoryText:j,lastSummarizedIndex:N}=await zQ(J,Q,K,Y),U=!!j,{bufferMessages:_}=CQ(J,K,N,U,$.overlapUserMessageCount),O=await hQ(_,Z,X,Y),{receivedMessageHeader:P,focusHeader:q}=EQ(Q,Z),V=IQ(j,O,P,q),z={dialogueMessages:_,messageCount:K.length,lastSummarizedIndex:N,config:$},r=X?.type?X.type===s.FEED||X.type===s.THREAD:!1,dJ={compressedHistory:j,recentMessages:O,receivedMessage:P,focusInstruction:q,recentPosts:r?O:""};return T.info({messageCount:K.length,bufferSize:_.length,hasSummaries:U,lastSummarizedIndex:N,estimatedTokens:Math.ceil(V.length/4),overlapUserMessageCount:$.overlapUserMessageCount},"Recent context assembled"),{data:z,values:dJ,text:V}}catch(W){return T.error({error:W},"Error in recentContextProvider"),{data:{dialogueMessages:[],messageCount:0,lastSummarizedIndex:-1,config:yJ(J)},values:{compressedHistory:"",recentMessages:"",receivedMessage:"",focusInstruction:"",recentPosts:""},text:"Error retrieving context."}}}};import{addHeader as fQ,logger as lJ}from"@elizaos/core";var gJ=(J)=>({limit:parseInt(J.getSetting("CONTEXT_ACTION_RESULTS_LIMIT")||"3",10)});function wQ(J,Q){if(J.length===0)return"";let W=new Map;for(let Z of J){let X=String(Z.content?.runId||"unknown");if(!W.has(X))W.set(X,[]);W.get(X).push(Z)}let $=Array.from(W.entries()).slice(-Q).map(([Z,X])=>{let G=X.sort((j,N)=>(j.createdAt||0)-(N.createdAt||0)),K=G[0]?.content?.planThought||"",Y=G.map((j)=>{let N=j.content?.actionName||"Unknown",U=j.content?.actionStatus||"unknown",_=j.content?.planStep||"",O=j.content?.text||"",P=j.content?.error||"",q=` - ${N} (${U})`;if(_)q+=` [${_}]`;if(P)q+=`: Error - ${P}`;else if(O&&O!==`Executed action: ${N}`)q+=`: ${O}`;return q}).join(`
343
+ `);return`**Action Run ${Z.slice(0,8)}**${K?` - "${K}"`:""}
344
+ ${Y}`}).join(`
345
+
346
+ `);return $?fQ("# Recent Action Executions",$):""}var uJ={name:"ACTION_RESULTS",description:"Recent action executions with their outcomes (tool memory)",position:101,get:async(J,Q)=>{try{let{roomId:W}=Q,$=gJ(J),X=(await J.getMemories({tableName:"messages",roomId:W,count:50,unique:!1})).filter((K)=>K.content?.type==="action_result"&&K.metadata?.type==="action_result");X.sort((K,Y)=>(K.createdAt||0)-(Y.createdAt||0));let G=wQ(X,$.limit);return lJ.debug({actionResultCount:X.length,limit:$.limit},"Action results provider assembled"),{data:{actionResults:X,config:$},values:{recentActionResults:G},text:G}}catch(W){return lJ.error({error:W},"Error in actionResultsProvider"),{data:{actionResults:[],config:gJ(J)},values:{recentActionResults:""},text:""}}}};var xQ={name:"memory",description:"State-of-the-art cognitive memory system with episodic, semantic, and procedural memory, featuring hybrid retrieval (Vector + BM25 + Graph), exponential decay, contextual embeddings, and contradiction detection",services:[c],evaluators:[fJ,SJ],providers:[pJ,cJ,uJ],schema:QJ},TQ=xQ;export{jJ as trimToTokenBudget,cJ as recentContextProvider,RJ as mergeSearchResults,xQ as memoryPlugin,i as mapDbRowToLongTermMemory,WJ as mapDbRowToConversationSummary,pJ as longTermMemoryProvider,D as longTermMemoryEmbeddings,A as longTermMemories,p as generateEmbedding,jW as formatTokenCount,hJ as formatMemoriesForContext,UJ as estimateTokensInSummary,YW as estimateTokenCountForArray,t as estimateTokenCount,TQ as default,R as conversationSummaryEmbeddings,k as conversationSummaries,y as cleanEmbedding,ZQ as calculateDecayFactor,KQ as calculateAccessBoost,NJ as buildLevel1SummaryPrompt,TJ as buildHigherLevelSummaryPrompt,IJ as buildExtractionPrompt,PW as buildContradictionPrompt,CJ as applyDecayScoring,uJ as actionResultsProvider,wJ as SUMMARIZATION_SYSTEM_PROMPT,_J as MemoryType,c as MemoryService,e as MEMORY_DIMENSION_MAP,KJ as LongTermMemoryRepository,xJ as HIGHER_LEVEL_SUMMARIZATION_SYSTEM_PROMPT,tJ as DecayFunction,YJ as ConversationSummaryRepository,EJ as CONSOLIDATION_SYSTEM_PROMPT};
347
+
348
+ //# debugId=9601D2A9C282652E64756E2164756E21