@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.
- package/README.md +339 -207
- package/dist/browser/index.browser.js +348 -151
- package/dist/browser/index.browser.js.map +23 -13
- package/dist/cjs/index.node.cjs +2200 -1047
- package/dist/cjs/index.node.js.map +23 -13
- package/dist/evaluators/consolidation.d.ts +19 -0
- package/dist/evaluators/summarization.d.ts +5 -24
- package/dist/index.d.ts +152 -30
- package/dist/node/index.node.js +2242 -1084
- package/dist/node/index.node.js.map +23 -13
- package/dist/prompts/consolidation.d.ts +35 -0
- package/dist/prompts/summarization.d.ts +25 -0
- package/dist/providers/action-results.d.ts +2 -0
- package/dist/providers/long-term-memory.d.ts +18 -11
- package/dist/providers/recent-conversation-summary.d.ts +2 -0
- package/dist/repositories/conversation-summary.d.ts +33 -0
- package/dist/repositories/index.d.ts +17 -0
- package/dist/repositories/long-term-memory.d.ts +53 -0
- package/dist/schemas/conversation-summaries.d.ts +494 -0
- package/dist/schemas/index.d.ts +16 -6
- package/dist/schemas/long-term-memories.d.ts +308 -70
- package/dist/services/memory-service.d.ts +95 -51
- package/dist/types/index.d.ts +299 -55
- package/dist/utils/db-mapping.d.ts +20 -0
- package/dist/utils/decay-scoring.d.ts +41 -0
- package/dist/utils/embedding.d.ts +21 -0
- package/dist/utils/formatting.d.ts +17 -0
- package/dist/utils/index.d.ts +17 -0
- package/dist/utils/search-merging.d.ts +18 -0
- package/dist/utils/token-counter.d.ts +53 -0
- package/package.json +83 -1
- package/dist/actions/remember.d.ts +0 -11
- package/dist/evaluators/long-term-extraction.d.ts +0 -8
- package/dist/providers/short-term-memory.d.ts +0 -19
- package/dist/schemas/memory-access-logs.d.ts +0 -154
- package/dist/schemas/session-summaries.d.ts +0 -283
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/services/memory-service.ts", "../../src/schemas/long-term-memories.ts", "../../src/schemas/
|
|
3
|
+
"sources": ["../../src/services/memory-service.ts", "../../src/types/index.ts", "../../src/repositories/long-term-memory.ts", "../../src/schemas/long-term-memories.ts", "../../src/schemas/conversation-summaries.ts", "../../src/utils/db-mapping.ts", "../../src/repositories/conversation-summary.ts", "../../src/utils/embedding.ts", "../../src/utils/decay-scoring.ts", "../../src/utils/search-merging.ts", "../../src/utils/formatting.ts", "../../src/utils/token-counter.ts", "../../src/evaluators/consolidation.ts", "../../src/prompts/consolidation.ts", "../../src/evaluators/summarization.ts", "../../src/prompts/summarization.ts", "../../src/providers/long-term-memory.ts", "../../src/providers/recent-conversation-summary.ts", "../../src/providers/action-results.ts", "../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {\n type IAgentRuntime,\n Service,\n type UUID,\n logger,\n type ServiceTypeName,\n} from '@elizaos/core';\nimport { eq, and, desc, sql, cosineDistance, gte } from 'drizzle-orm';\nimport {\n type LongTermMemory,\n type SessionSummary,\n type MemoryConfig,\n LongTermMemoryCategory,\n} from '../types/index';\nimport { longTermMemories, sessionSummaries } from '../schemas/index';\n\n/**\n * Memory Service\n * Manages both short-term (session summaries) and long-term (persistent facts) memory\n */\nexport class MemoryService extends Service {\n static serviceType: ServiceTypeName = 'memory' as ServiceTypeName;\n\n private sessionMessageCounts: Map<UUID, number>;\n private memoryConfig: MemoryConfig;\n private lastExtractionCheckpoints: Map<string, number>; // Track last extraction per entity-room pair\n\n capabilityDescription =\n 'Advanced memory management with short-term summarization and long-term persistent facts';\n\n constructor(runtime?: IAgentRuntime) {\n super(runtime);\n this.sessionMessageCounts = new Map();\n this.lastExtractionCheckpoints = new Map();\n this.memoryConfig = {\n shortTermSummarizationThreshold: 16, // Start summarization at 16 messages\n shortTermRetainRecent: 10,\n shortTermSummarizationInterval: 10, // Update summary every 10 new messages\n longTermExtractionEnabled: true,\n longTermVectorSearchEnabled: false,\n longTermConfidenceThreshold: 0.7,\n longTermExtractionThreshold: 20, // Minimum messages before starting extraction\n longTermExtractionInterval: 5, // Run extraction every N messages after threshold\n summaryModelType: 'TEXT_LARGE',\n summaryMaxTokens: 2500,\n summaryMaxNewMessages: 20, // Cap new messages in update to prevent context bloat\n };\n }\n\n static async start(runtime: IAgentRuntime): Promise<Service> {\n const service = new MemoryService(runtime);\n await service.initialize(runtime);\n return service;\n }\n\n async stop(): Promise<void> {\n // No cleanup needed for this service\n logger.info('MemoryService stopped');\n }\n\n async initialize(runtime: IAgentRuntime): Promise<void> {\n this.runtime = runtime;\n\n // Load configuration from runtime settings\n const threshold = runtime.getSetting('MEMORY_SUMMARIZATION_THRESHOLD');\n if (threshold) {\n this.memoryConfig.shortTermSummarizationThreshold = parseInt(threshold, 10);\n }\n\n const retainRecent = runtime.getSetting('MEMORY_RETAIN_RECENT');\n if (retainRecent) {\n this.memoryConfig.shortTermRetainRecent = parseInt(retainRecent, 10);\n }\n\n const summarizationInterval = runtime.getSetting('MEMORY_SUMMARIZATION_INTERVAL');\n if (summarizationInterval) {\n this.memoryConfig.shortTermSummarizationInterval = parseInt(summarizationInterval, 10);\n }\n\n const maxNewMessages = runtime.getSetting('MEMORY_MAX_NEW_MESSAGES');\n if (maxNewMessages) {\n this.memoryConfig.summaryMaxNewMessages = parseInt(maxNewMessages, 10);\n }\n\n const longTermEnabled = runtime.getSetting('MEMORY_LONG_TERM_ENABLED');\n // Only override default if explicitly set to 'false'\n if (longTermEnabled === 'false') {\n this.memoryConfig.longTermExtractionEnabled = false;\n } else if (longTermEnabled === 'true') {\n this.memoryConfig.longTermExtractionEnabled = true;\n }\n // Otherwise keep the default value (true)\n\n const confidenceThreshold = runtime.getSetting('MEMORY_CONFIDENCE_THRESHOLD');\n if (confidenceThreshold) {\n this.memoryConfig.longTermConfidenceThreshold = parseFloat(confidenceThreshold);\n }\n\n const extractionThreshold = runtime.getSetting('MEMORY_EXTRACTION_THRESHOLD');\n if (extractionThreshold) {\n this.memoryConfig.longTermExtractionThreshold = parseInt(extractionThreshold, 10);\n }\n\n const extractionInterval = runtime.getSetting('MEMORY_EXTRACTION_INTERVAL');\n if (extractionInterval) {\n this.memoryConfig.longTermExtractionInterval = parseInt(extractionInterval, 10);\n }\n\n logger.info(\n {\n summarizationThreshold: this.memoryConfig.shortTermSummarizationThreshold,\n summarizationInterval: this.memoryConfig.shortTermSummarizationInterval,\n maxNewMessages: this.memoryConfig.summaryMaxNewMessages,\n retainRecent: this.memoryConfig.shortTermRetainRecent,\n longTermEnabled: this.memoryConfig.longTermExtractionEnabled,\n extractionThreshold: this.memoryConfig.longTermExtractionThreshold,\n extractionInterval: this.memoryConfig.longTermExtractionInterval,\n confidenceThreshold: this.memoryConfig.longTermConfidenceThreshold,\n },\n 'MemoryService initialized'\n );\n }\n\n /**\n * Get the Drizzle database instance\n */\n private getDb(): any {\n const db = (this.runtime as any).db;\n if (!db) {\n throw new Error('Database not available');\n }\n return db;\n }\n\n /**\n * Get configuration\n */\n getConfig(): MemoryConfig {\n return { ...this.memoryConfig };\n }\n\n /**\n * Update configuration\n */\n updateConfig(updates: Partial<MemoryConfig>): void {\n this.memoryConfig = { ...this.memoryConfig, ...updates };\n }\n\n /**\n * Track message count for a room\n */\n incrementMessageCount(roomId: UUID): number {\n const current = this.sessionMessageCounts.get(roomId) || 0;\n const newCount = current + 1;\n this.sessionMessageCounts.set(roomId, newCount);\n return newCount;\n }\n\n /**\n * Reset message count for a room\n */\n resetMessageCount(roomId: UUID): void {\n this.sessionMessageCounts.set(roomId, 0);\n }\n\n /**\n * Check if summarization is needed for a room\n */\n async shouldSummarize(roomId: UUID): Promise<boolean> {\n const count = await this.runtime.countMemories(roomId, false, 'messages');\n return count >= this.memoryConfig.shortTermSummarizationThreshold;\n }\n\n /**\n * Generate cache key for tracking extraction checkpoints per entity-room pair\n */\n private getExtractionKey(entityId: UUID, roomId: UUID): string {\n return `memory:extraction:${entityId}:${roomId}`;\n }\n\n /**\n * Get the last extraction checkpoint for an entity in a room\n * Uses the cache table via adapter\n */\n async getLastExtractionCheckpoint(entityId: UUID, roomId: UUID): Promise<number> {\n const key = this.getExtractionKey(entityId, roomId);\n\n // Check in-memory cache first\n const cached = this.lastExtractionCheckpoints.get(key);\n if (cached !== undefined) {\n return cached;\n }\n\n // Check database cache table via adapter\n try {\n const checkpoint = await this.runtime.getCache<number>(key);\n const messageCount = checkpoint ?? 0;\n\n // Cache it in memory for faster access\n this.lastExtractionCheckpoints.set(key, messageCount);\n\n return messageCount;\n } catch (error) {\n logger.warn({ error }, 'Failed to get extraction checkpoint from cache');\n return 0;\n }\n }\n\n /**\n * Set the last extraction checkpoint for an entity in a room\n * Uses the cache table via adapter\n */\n async setLastExtractionCheckpoint(\n entityId: UUID,\n roomId: UUID,\n messageCount: number\n ): Promise<void> {\n const key = this.getExtractionKey(entityId, roomId);\n\n // Update in-memory cache\n this.lastExtractionCheckpoints.set(key, messageCount);\n\n // Persist to database cache table via adapter\n try {\n await this.runtime.setCache(key, messageCount);\n logger.debug(\n `Set extraction checkpoint for ${entityId} in room ${roomId} at message count ${messageCount}`\n );\n } catch (error) {\n logger.error({ error }, 'Failed to persist extraction checkpoint to cache');\n }\n }\n\n /**\n * Check if long-term extraction should run based on message count and interval\n */\n async shouldRunExtraction(\n entityId: UUID,\n roomId: UUID,\n currentMessageCount: number\n ): Promise<boolean> {\n const threshold = this.memoryConfig.longTermExtractionThreshold;\n const interval = this.memoryConfig.longTermExtractionInterval;\n \n // Don't run extraction until we reach the minimum threshold\n if (currentMessageCount < threshold) {\n logger.debug(\n {\n entityId,\n roomId,\n currentMessageCount,\n threshold,\n shouldRun: false,\n },\n 'Extraction check: below threshold'\n );\n return false;\n }\n\n const lastCheckpoint = await this.getLastExtractionCheckpoint(entityId, roomId);\n\n // Calculate the current checkpoint (e.g., if interval=5: 20, 25, 30, 35...)\n const currentCheckpoint = Math.floor(currentMessageCount / interval) * interval;\n\n // Run if we're at or past a checkpoint and haven't processed this checkpoint yet\n const shouldRun = currentMessageCount >= threshold && currentCheckpoint > lastCheckpoint;\n\n logger.debug(\n {\n entityId,\n roomId,\n currentMessageCount,\n threshold,\n interval,\n lastCheckpoint,\n currentCheckpoint,\n shouldRun,\n },\n 'Extraction check'\n );\n\n return shouldRun;\n }\n\n /**\n * Store a long-term memory\n */\n async storeLongTermMemory(\n memory: Omit<LongTermMemory, 'id' | 'createdAt' | 'updatedAt'>\n ): Promise<LongTermMemory> {\n const db = this.getDb();\n\n const id = crypto.randomUUID() as UUID;\n const now = new Date();\n\n const newMemory: LongTermMemory = {\n id,\n createdAt: now,\n updatedAt: now,\n accessCount: 0,\n ...memory,\n };\n\n try {\n await db.insert(longTermMemories).values({\n id: newMemory.id,\n agentId: newMemory.agentId,\n entityId: newMemory.entityId,\n category: newMemory.category,\n content: newMemory.content,\n metadata: newMemory.metadata || {},\n embedding: newMemory.embedding,\n confidence: newMemory.confidence,\n source: newMemory.source,\n accessCount: newMemory.accessCount,\n createdAt: now,\n updatedAt: now,\n lastAccessedAt: newMemory.lastAccessedAt,\n });\n } catch (error) {\n logger.error({ error }, 'Failed to store long-term memory');\n throw error;\n }\n\n logger.info(`Stored long-term memory: ${newMemory.category} for entity ${newMemory.entityId}`);\n return newMemory;\n }\n\n /**\n * Retrieve long-term memories for an entity\n */\n async getLongTermMemories(\n entityId: UUID,\n category?: LongTermMemoryCategory,\n limit: number = 10\n ): Promise<LongTermMemory[]> {\n const db = this.getDb();\n\n const conditions = [\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, entityId),\n ];\n\n if (category) {\n conditions.push(eq(longTermMemories.category, category));\n }\n\n const results = await db\n .select()\n .from(longTermMemories)\n .where(and(...conditions))\n .orderBy(desc(longTermMemories.confidence), desc(longTermMemories.updatedAt))\n .limit(limit);\n\n return results.map((row) => ({\n id: row.id as UUID,\n agentId: row.agentId as UUID,\n entityId: row.entityId as UUID,\n category: row.category as LongTermMemoryCategory,\n content: row.content,\n metadata: row.metadata as Record<string, unknown>,\n embedding: row.embedding as number[],\n confidence: row.confidence as number,\n source: row.source as string,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n lastAccessedAt: row.lastAccessedAt,\n accessCount: row.accessCount as number,\n }));\n }\n\n /**\n * Update a long-term memory\n * Enforces multi-tenancy by verifying agentId and entityId\n */\n async updateLongTermMemory(\n id: UUID,\n entityId: UUID,\n updates: Partial<Omit<LongTermMemory, 'id' | 'agentId' | 'entityId' | 'createdAt'>>\n ): Promise<void> {\n const db = this.getDb();\n\n const updateData: any = {\n updatedAt: new Date(),\n };\n\n if (updates.content !== undefined) {\n updateData.content = updates.content;\n }\n\n if (updates.metadata !== undefined) {\n updateData.metadata = updates.metadata;\n }\n\n if (updates.confidence !== undefined) {\n updateData.confidence = updates.confidence;\n }\n\n if (updates.embedding !== undefined) {\n updateData.embedding = updates.embedding;\n }\n\n if (updates.lastAccessedAt !== undefined) {\n updateData.lastAccessedAt = updates.lastAccessedAt;\n }\n\n if (updates.accessCount !== undefined) {\n updateData.accessCount = updates.accessCount;\n }\n\n // Enforce multi-tenancy: only update if agentId and entityId match\n await db\n .update(longTermMemories)\n .set(updateData)\n .where(\n and(\n eq(longTermMemories.id, id),\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, entityId)\n )\n );\n\n logger.info(`Updated long-term memory: ${id} for entity ${entityId}`);\n }\n\n /**\n * Delete a long-term memory\n * Enforces multi-tenancy by verifying agentId and entityId\n */\n async deleteLongTermMemory(id: UUID, entityId: UUID): Promise<void> {\n const db = this.getDb();\n\n // Enforce multi-tenancy: only delete if agentId and entityId match\n await db\n .delete(longTermMemories)\n .where(\n and(\n eq(longTermMemories.id, id),\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, entityId)\n )\n );\n\n logger.info(`Deleted long-term memory: ${id} for entity ${entityId}`);\n }\n\n /**\n * Get the current session summary for a room (latest one)\n */\n async getCurrentSessionSummary(roomId: UUID): Promise<SessionSummary | null> {\n const db = this.getDb();\n\n const results = await db\n .select()\n .from(sessionSummaries)\n .where(\n and(eq(sessionSummaries.agentId, this.runtime.agentId), eq(sessionSummaries.roomId, roomId))\n )\n .orderBy(desc(sessionSummaries.updatedAt))\n .limit(1);\n\n if (results.length === 0) {\n return null;\n }\n\n const row = results[0];\n return {\n id: row.id as UUID,\n agentId: row.agentId as UUID,\n roomId: row.roomId as UUID,\n entityId: row.entityId as UUID | undefined,\n summary: row.summary,\n messageCount: row.messageCount,\n lastMessageOffset: row.lastMessageOffset,\n startTime: row.startTime,\n endTime: row.endTime,\n topics: (row.topics as string[]) || [],\n metadata: row.metadata as Record<string, unknown>,\n embedding: row.embedding as number[],\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n /**\n * Store a session summary (initial creation)\n */\n async storeSessionSummary(\n summary: Omit<SessionSummary, 'id' | 'createdAt' | 'updatedAt'>\n ): Promise<SessionSummary> {\n const db = this.getDb();\n\n const id = crypto.randomUUID() as UUID;\n const now = new Date();\n\n const newSummary: SessionSummary = {\n id,\n createdAt: now,\n updatedAt: now,\n ...summary,\n };\n\n await db.insert(sessionSummaries).values({\n id: newSummary.id,\n agentId: newSummary.agentId,\n roomId: newSummary.roomId,\n entityId: newSummary.entityId || null,\n summary: newSummary.summary,\n messageCount: newSummary.messageCount,\n lastMessageOffset: newSummary.lastMessageOffset,\n startTime: newSummary.startTime,\n endTime: newSummary.endTime,\n topics: newSummary.topics || [],\n metadata: newSummary.metadata || {},\n embedding: newSummary.embedding,\n createdAt: now,\n updatedAt: now,\n });\n\n logger.info(`Stored session summary for room ${newSummary.roomId}`);\n return newSummary;\n }\n\n /**\n * Update an existing session summary\n * Enforces multi-tenancy by verifying agentId\n */\n async updateSessionSummary(\n id: UUID,\n roomId: UUID,\n updates: Partial<Omit<SessionSummary, 'id' | 'agentId' | 'roomId' | 'createdAt' | 'updatedAt'>>\n ): Promise<void> {\n const db = this.getDb();\n\n const updateData: any = {\n updatedAt: new Date(),\n };\n\n if (updates.summary !== undefined) {\n updateData.summary = updates.summary;\n }\n\n if (updates.messageCount !== undefined) {\n updateData.messageCount = updates.messageCount;\n }\n\n if (updates.lastMessageOffset !== undefined) {\n updateData.lastMessageOffset = updates.lastMessageOffset;\n }\n\n if (updates.endTime !== undefined) {\n updateData.endTime = updates.endTime;\n }\n\n if (updates.topics !== undefined) {\n updateData.topics = updates.topics;\n }\n\n if (updates.metadata !== undefined) {\n updateData.metadata = updates.metadata;\n }\n\n if (updates.embedding !== undefined) {\n updateData.embedding = updates.embedding;\n }\n\n // Enforce multi-tenancy: only update if agentId and roomId match\n await db\n .update(sessionSummaries)\n .set(updateData)\n .where(\n and(\n eq(sessionSummaries.id, id),\n eq(sessionSummaries.agentId, this.runtime.agentId),\n eq(sessionSummaries.roomId, roomId)\n )\n );\n\n logger.info(`Updated session summary: ${id} for room ${roomId}`);\n }\n\n /**\n * Get session summaries for a room\n */\n async getSessionSummaries(roomId: UUID, limit: number = 5): Promise<SessionSummary[]> {\n const db = this.getDb();\n\n const results = await db\n .select()\n .from(sessionSummaries)\n .where(\n and(eq(sessionSummaries.agentId, this.runtime.agentId), eq(sessionSummaries.roomId, roomId))\n )\n .orderBy(desc(sessionSummaries.updatedAt))\n .limit(limit);\n\n return results.map((row) => ({\n id: row.id as UUID,\n agentId: row.agentId as UUID,\n roomId: row.roomId as UUID,\n entityId: row.entityId as UUID | undefined,\n summary: row.summary,\n messageCount: row.messageCount,\n lastMessageOffset: row.lastMessageOffset,\n startTime: row.startTime,\n endTime: row.endTime,\n topics: (row.topics as string[]) || [],\n metadata: row.metadata as Record<string, unknown>,\n embedding: row.embedding as number[],\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n }));\n }\n\n /**\n * Search long-term memories by semantic similarity (if embeddings are available)\n */\n async searchLongTermMemories(\n entityId: UUID,\n queryEmbedding: number[],\n limit: number = 5,\n matchThreshold: number = 0.7\n ): Promise<LongTermMemory[]> {\n if (!this.memoryConfig.longTermVectorSearchEnabled) {\n logger.warn('Vector search is not enabled, falling back to recent memories');\n return this.getLongTermMemories(entityId, undefined, limit);\n }\n\n const db = this.getDb();\n\n try {\n // Clean the vector to ensure all numbers are finite and properly formatted\n const cleanVector = queryEmbedding.map((n) =>\n Number.isFinite(n) ? Number(n.toFixed(6)) : 0\n );\n\n // Calculate similarity using Drizzle's cosineDistance\n const similarity = sql<number>`1 - (${cosineDistance(\n longTermMemories.embedding,\n cleanVector\n )})`;\n\n const conditions = [\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, entityId),\n sql`${longTermMemories.embedding} IS NOT NULL`,\n ];\n\n // Add similarity threshold if specified\n if (matchThreshold > 0) {\n conditions.push(gte(similarity, matchThreshold));\n }\n\n const results = await db\n .select({\n memory: longTermMemories,\n similarity,\n })\n .from(longTermMemories)\n .where(and(...conditions))\n .orderBy(desc(similarity))\n .limit(limit);\n\n return results.map((row) => ({\n id: row.memory.id as UUID,\n agentId: row.memory.agentId as UUID,\n entityId: row.memory.entityId as UUID,\n category: row.memory.category as LongTermMemoryCategory,\n content: row.memory.content,\n metadata: row.memory.metadata as Record<string, unknown>,\n embedding: row.memory.embedding as number[],\n confidence: row.memory.confidence as number,\n source: row.memory.source as string,\n createdAt: row.memory.createdAt,\n updatedAt: row.memory.updatedAt,\n lastAccessedAt: row.memory.lastAccessedAt,\n accessCount: row.memory.accessCount as number,\n similarity: row.similarity,\n }));\n } catch (error) {\n logger.warn({ error }, 'Vector search failed, falling back to recent memories');\n return this.getLongTermMemories(entityId, undefined, limit);\n }\n }\n\n /**\n * Get all long-term memories formatted for context\n */\n async getFormattedLongTermMemories(entityId: UUID): Promise<string> {\n const memories = await this.getLongTermMemories(entityId, undefined, 20);\n\n if (memories.length === 0) {\n return '';\n }\n\n // Group by category\n const grouped = new Map<LongTermMemoryCategory, LongTermMemory[]>();\n\n for (const memory of memories) {\n if (!grouped.has(memory.category)) {\n grouped.set(memory.category, []);\n }\n grouped.get(memory.category)?.push(memory);\n }\n\n // Format each category\n const sections: string[] = [];\n\n for (const [category, categoryMemories] of grouped.entries()) {\n const categoryName = category\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n const items = categoryMemories.map((m) => `- ${m.content}`).join('\\n');\n sections.push(`**${categoryName}**:\\n${items}`);\n }\n\n return sections.join('\\n\\n');\n }\n}\n",
|
|
6
|
-
"import { sql } from 'drizzle-orm';\nimport {\n pgTable,\n text,\n integer,\n jsonb,\n real,\n index,\n varchar,\n timestamp,\n} from 'drizzle-orm/pg-core';\n\n/**\n * Long-term memory storage table\n * Stores persistent facts about users across all conversations\n */\nexport const longTermMemories = pgTable(\n 'long_term_memories',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n agentId: varchar('agent_id', { length: 36 }).notNull(),\n entityId: varchar('entity_id', { length: 36 }).notNull(),\n category: text('category').notNull(),\n content: text('content').notNull(),\n metadata: jsonb('metadata'),\n embedding: real('embedding').array(),\n confidence: real('confidence').default(1.0),\n source: text('source'),\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n updatedAt: timestamp('updated_at')\n .default(sql`now()`)\n .notNull(),\n lastAccessedAt: timestamp('last_accessed_at'),\n accessCount: integer('access_count').default(0),\n },\n (table) => ({\n agentEntityIdx: index('long_term_memories_agent_entity_idx').on(table.agentId, table.entityId),\n categoryIdx: index('long_term_memories_category_idx').on(table.category),\n confidenceIdx: index('long_term_memories_confidence_idx').on(table.confidence),\n createdAtIdx: index('long_term_memories_created_at_idx').on(table.createdAt),\n })\n);\n",
|
|
7
|
-
"import { sql } from 'drizzle-orm';\nimport {\n pgTable,\n text,\n integer,\n jsonb,\n real,\n index,\n varchar,\n timestamp,\n} from 'drizzle-orm/pg-core';\n\n/**\n * Session summaries table\n * Stores condensed summaries of conversation sessions\n */\nexport const sessionSummaries = pgTable(\n 'session_summaries',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n agentId: varchar('agent_id', { length: 36 }).notNull(),\n roomId: varchar('room_id', { length: 36 }).notNull(),\n entityId: varchar('entity_id', { length: 36 }),\n summary: text('summary').notNull(),\n messageCount: integer('message_count').notNull(),\n lastMessageOffset: integer('last_message_offset').notNull().default(0),\n startTime: timestamp('start_time').notNull(),\n endTime: timestamp('end_time').notNull(),\n topics: jsonb('topics'),\n metadata: jsonb('metadata'),\n embedding: real('embedding').array(),\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n updatedAt: timestamp('updated_at')\n .default(sql`now()`)\n .notNull(),\n },\n (table) => ({\n agentRoomIdx: index('session_summaries_agent_room_idx').on(table.agentId, table.roomId),\n entityIdx: index('session_summaries_entity_idx').on(table.entityId),\n startTimeIdx: index('session_summaries_start_time_idx').on(table.startTime),\n })\n);\n",
|
|
8
|
-
"import { sql } from 'drizzle-orm';\nimport {
|
|
9
|
-
"import {\n type IAgentRuntime,\n type Memory,\n type Evaluator,\n logger,\n ModelType,\n composePromptFromState,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\nimport type { SummaryResult } from '../types/index';\n\n/**\n * Template for generating initial conversation summary\n */\nconst initialSummarizationTemplate = `# Task: Summarize Conversation\n\nYou are analyzing a conversation to create a concise summary that captures the key points, topics, and important details.\n\n# Recent Messages\n{{recentMessages}}\n\n# Instructions\nGenerate a summary that:\n1. Captures the main topics discussed\n2. Highlights key information shared\n3. Notes any decisions made or questions asked\n4. Maintains context for future reference\n5. Is concise but comprehensive\n\n**IMPORTANT**: Keep the summary under 2500 tokens. Be comprehensive but concise.\n\nAlso extract:\n- **Topics**: List of main topics discussed (comma-separated)\n- **Key Points**: Important facts or decisions (bullet points)\n\nRespond in this XML format:\n<summary>\n <text>Your comprehensive summary here</text>\n <topics>topic1, topic2, topic3</topics>\n <keyPoints>\n <point>First key point</point>\n <point>Second key point</point>\n </keyPoints>\n</summary>`;\n\n/**\n * Template for updating/condensing an existing summary\n */\nconst updateSummarizationTemplate = `# Task: Update and Condense Conversation Summary\n\nYou are updating an existing conversation summary with new messages, while keeping the total summary concise.\n\n# Existing Summary\n{{existingSummary}}\n\n# Existing Topics\n{{existingTopics}}\n\n# New Messages Since Last Summary\n{{newMessages}}\n\n# Instructions\nUpdate the summary by:\n1. Merging the existing summary with insights from the new messages\n2. Removing redundant or less important details to stay under the token limit\n3. Keeping the most important context and decisions\n4. Adding new topics if they emerge\n5. **CRITICAL**: Keep the ENTIRE updated summary under 2500 tokens\n\nThe goal is a rolling summary that captures the essence of the conversation without growing indefinitely.\n\nRespond in this XML format:\n<summary>\n <text>Your updated and condensed summary here</text>\n <topics>topic1, topic2, topic3</topics>\n <keyPoints>\n <point>First key point</point>\n <point>Second key point</point>\n </keyPoints>\n</summary>`;\n\n/**\n * Parse XML summary response\n */\nfunction parseSummaryXML(xml: string): SummaryResult {\n const summaryMatch = xml.match(/<text>([\\s\\S]*?)<\\/text>/);\n const topicsMatch = xml.match(/<topics>([\\s\\S]*?)<\\/topics>/);\n const keyPointsMatches = xml.matchAll(/<point>([\\s\\S]*?)<\\/point>/g);\n\n const summary = summaryMatch ? summaryMatch[1].trim() : 'Summary not available';\n const topics = topicsMatch\n ? topicsMatch[1]\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean)\n : [];\n const keyPoints = Array.from(keyPointsMatches).map((match) => match[1].trim());\n\n return { summary, topics, keyPoints };\n}\n\n/**\n * Short-term Memory Summarization Evaluator\n *\n * Automatically generates and updates conversation summaries when conversations\n * exceed the configured threshold (default: 16 messages).\n *\n * BEHAVIOR:\n * - Monitors message count per room\n * - Creates initial summary when count >= threshold (e.g., 16 messages)\n * - Updates summary at regular intervals (e.g., every 10 new messages)\n * - Condenses existing summary with new messages to stay under token limit\n * - Tracks offset to avoid re-processing messages\n * - Caps new messages per update to prevent context bloat (default: 20)\n *\n * OPTIMIZATION:\n * - Only triggers LLM when crossing threshold or interval boundaries\n * - Processes only NEW messages since last update\n * - Maintains rolling summary (fixed size, not ever-growing)\n * - LLM is instructed to merge and condense, keeping under 2500 tokens\n *\n * INTEGRATION:\n * Works with shortTermMemoryProvider which:\n * - Shows full conversation when < threshold (no summarization needed)\n * - Shows summaries + recent messages when >= threshold (optimized context)\n *\n * This creates an adaptive system that starts with full context and seamlessly\n * transitions to efficient summarization as conversations grow.\n */\nexport const summarizationEvaluator: Evaluator = {\n name: 'MEMORY_SUMMARIZATION',\n description: 'Automatically summarizes conversations to optimize context usage',\n similes: ['CONVERSATION_SUMMARY', 'CONTEXT_COMPRESSION', 'MEMORY_OPTIMIZATION'],\n alwaysRun: true,\n\n validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => {\n // Only run after actual messages (not during generation or on empty messages)\n if (!message.content?.text) {\n logger.debug('Skipping summarization: no message text');\n return false;\n }\n\n const memoryService = runtime.getService('memory') as MemoryService | null;\n if (!memoryService) {\n logger.debug('Skipping summarization: memory service not available');\n return false;\n }\n\n const config = memoryService.getConfig();\n const currentMessageCount = await runtime.countMemories(message.roomId, false, 'messages');\n\n // Get existing summary to check if we need initial or update\n const existingSummary = await memoryService.getCurrentSessionSummary(message.roomId);\n \n if (!existingSummary) {\n // No summary yet - create initial summary when threshold is reached\n const shouldSummarize = currentMessageCount >= config.shortTermSummarizationThreshold;\n logger.debug(\n {\n roomId: message.roomId,\n currentMessageCount,\n threshold: config.shortTermSummarizationThreshold,\n shouldSummarize,\n reason: 'initial_summary_check',\n },\n 'Summarization validation check'\n );\n return shouldSummarize;\n } else {\n // Summary exists - check if we have enough new messages since last update\n const newMessageCount = currentMessageCount - existingSummary.lastMessageOffset;\n const shouldUpdate = newMessageCount >= config.shortTermSummarizationInterval;\n \n logger.debug(\n {\n roomId: message.roomId,\n currentMessageCount,\n lastOffset: existingSummary.lastMessageOffset,\n newMessageCount,\n interval: config.shortTermSummarizationInterval,\n shouldUpdate,\n reason: 'summary_update_check',\n },\n 'Summarization validation check'\n );\n return shouldUpdate;\n }\n },\n\n handler: async (runtime: IAgentRuntime, message: Memory): Promise<void> => {\n const memoryService = runtime.getService('memory') as MemoryService;\n if (!memoryService) {\n logger.error('MemoryService not found');\n return;\n }\n\n const config = memoryService.getConfig();\n const { roomId } = message;\n\n try {\n logger.info(`Starting summarization for room ${roomId}`);\n\n // Get the current summary (if any)\n const existingSummary = await memoryService.getCurrentSessionSummary(roomId);\n const lastOffset = existingSummary?.lastMessageOffset || 0;\n\n // Get total message count\n const totalMessageCount = await runtime.countMemories(roomId, false, 'messages');\n\n // Calculate how many new messages we have\n const newMessageCount = totalMessageCount - lastOffset;\n \n // Cap the number of new messages to prevent context bloat\n const maxNewMessages = config.summaryMaxNewMessages || 50;\n const messagesToFetch = Math.min(newMessageCount, maxNewMessages);\n \n if (messagesToFetch === 0) {\n logger.debug('No new messages to summarize');\n return;\n }\n\n // Log if we're hitting the cap\n if (newMessageCount > maxNewMessages) {\n logger.warn(\n `Capping new messages at ${maxNewMessages} (${newMessageCount} available). Oldest messages will be skipped.`\n );\n }\n\n // Get new messages since last offset\n const newMessages = await runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: messagesToFetch,\n unique: false,\n start: lastOffset,\n });\n\n if (newMessages.length === 0) {\n logger.debug('No new messages retrieved');\n return;\n }\n\n // Sort by timestamp\n const sortedMessages = newMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));\n\n // Format messages for summarization\n const formattedMessages = sortedMessages\n .map((msg) => {\n const sender = msg.entityId === runtime.agentId ? runtime.character.name : 'User';\n return `${sender}: ${msg.content.text || '[non-text message]'}`;\n })\n .join('\\n');\n\n // Generate or update summary using LLM\n const state = await runtime.composeState(message);\n let prompt: string;\n let template: string;\n\n if (existingSummary) {\n // Update existing summary\n template = updateSummarizationTemplate;\n prompt = composePromptFromState({\n state: {\n ...state,\n existingSummary: existingSummary.summary,\n existingTopics: existingSummary.topics?.join(', ') || 'None',\n newMessages: formattedMessages,\n },\n template,\n });\n } else {\n // Create initial summary\n template = initialSummarizationTemplate;\n prompt = composePromptFromState({\n state: {\n ...state,\n recentMessages: formattedMessages,\n },\n template,\n });\n }\n\n const response = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt,\n maxTokens: config.summaryMaxTokens || 2500,\n });\n\n const summaryResult = parseSummaryXML(response);\n\n logger.info(\n `${existingSummary ? 'Updated' : 'Generated'} summary: ${summaryResult.summary.substring(0, 100)}...`\n );\n\n // Calculate new offset (current total)\n const newOffset = totalMessageCount;\n\n // Get timing info\n const firstMessage = sortedMessages[0];\n const lastMessage = sortedMessages[sortedMessages.length - 1];\n\n const startTime = existingSummary\n ? existingSummary.startTime\n : firstMessage?.createdAt && firstMessage.createdAt > 0\n ? new Date(firstMessage.createdAt)\n : new Date();\n const endTime =\n lastMessage?.createdAt && lastMessage.createdAt > 0\n ? new Date(lastMessage.createdAt)\n : new Date();\n\n if (existingSummary) {\n // Update existing summary\n await memoryService.updateSessionSummary(existingSummary.id, roomId, {\n summary: summaryResult.summary,\n messageCount: existingSummary.messageCount + sortedMessages.length,\n lastMessageOffset: newOffset,\n endTime,\n topics: summaryResult.topics,\n metadata: {\n keyPoints: summaryResult.keyPoints,\n },\n });\n\n logger.info(\n `Updated summary for room ${roomId}: ${sortedMessages.length} new messages processed (offset: ${lastOffset} → ${newOffset})`\n );\n } else {\n // Create new summary\n await memoryService.storeSessionSummary({\n agentId: runtime.agentId,\n roomId,\n entityId: message.entityId !== runtime.agentId ? message.entityId : undefined,\n summary: summaryResult.summary,\n messageCount: sortedMessages.length,\n lastMessageOffset: newOffset,\n startTime,\n endTime,\n topics: summaryResult.topics,\n metadata: {\n keyPoints: summaryResult.keyPoints,\n },\n });\n\n logger.info(\n `Created new summary for room ${roomId}: ${sortedMessages.length} messages summarized (offset: 0 → ${newOffset})`\n );\n }\n\n // Note: We do NOT delete messages - they stay in the database\n // The offset tracks what's been summarized\n } catch (error) {\n logger.error({ error }, 'Error during summarization:');\n }\n },\n\n examples: [],\n};\n",
|
|
10
|
-
"import
|
|
11
|
-
"import type { UUID } from '@elizaos/core';\
|
|
12
|
-
"import {\n addHeader,\n ChannelType,\n CustomMetadata,\n formatMessages,\n formatPosts,\n getEntityDetails,\n type Entity,\n type IAgentRuntime,\n type Memory,\n type Provider,\n type State,\n logger,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\n\n/**\n * Short-term Memory Provider\n *\n * Adaptive conversation context provider that optimizes based on conversation length:\n *\n * SHORT CONVERSATIONS (< threshold, default 5 messages):\n * - Shows full message history with complete context\n * - No summarization overhead for brief chats\n *\n * LONG CONVERSATIONS (>= threshold):\n * - Shows summaries of older conversation segments\n * - Shows recent unsummarized messages in full\n * - Optimizes context window while preserving information\n *\n * This provider can REPLACE recentMessagesProvider when plugin-memory is active,\n * providing superior context management for both short and long conversations.\n */\nexport const shortTermMemoryProvider: Provider = {\n name: 'SHORT_TERM_MEMORY',\n description: 'Adaptive conversation context with smart summarization',\n position: 95, // Run before recentMessagesProvider (100) to potentially replace it\n\n get: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n try {\n const memoryService = runtime.getService('memory') as MemoryService | null;\n if (!memoryService) {\n // No memory service - return empty\n return {\n data: { summaries: [], recentMessages: [], mode: 'disabled' },\n values: {},\n text: '',\n };\n }\n\n const { roomId } = message;\n const config = memoryService.getConfig();\n\n // Get total message count to determine mode\n const totalMessageCount = await runtime.countMemories(roomId, false, 'messages');\n\n // ADAPTIVE LOGIC: Use full messages for short conversations, summaries for long ones\n if (totalMessageCount < config.shortTermSummarizationThreshold) {\n // ========== SHORT CONVERSATION MODE ==========\n // Just show all messages - no summarization needed\n\n const conversationLength = runtime.getConversationLength();\n\n // Fetch all necessary data in parallel\n const [entitiesData, room, recentMessagesData] = await Promise.all([\n getEntityDetails({ runtime, roomId }),\n runtime.getRoom(roomId),\n runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: conversationLength,\n unique: false,\n }),\n ]);\n\n // Separate action results from dialogue messages\n const actionResultMessages = recentMessagesData.filter(\n (msg) => msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result'\n );\n\n const dialogueMessages = recentMessagesData.filter(\n (msg) =>\n !(msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result')\n );\n\n // Determine format based on room type\n const isPostFormat = room?.type\n ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD\n : false;\n\n // Format messages in parallel\n const [formattedRecentMessages, formattedRecentPosts] = await Promise.all([\n formatMessages({\n messages: dialogueMessages,\n entities: entitiesData,\n }),\n formatPosts({\n messages: dialogueMessages,\n entities: entitiesData,\n conversationHeader: false,\n }),\n ]);\n\n // Format action results if any\n let actionResultsText = '';\n if (actionResultMessages.length > 0) {\n const groupedByRun = new Map<string, Memory[]>();\n\n for (const mem of actionResultMessages) {\n const runId: string = String(mem.content?.runId || 'unknown');\n if (!groupedByRun.has(runId)) {\n groupedByRun.set(runId, []);\n }\n groupedByRun.get(runId)?.push(mem);\n }\n\n const formattedActionResults = Array.from(groupedByRun.entries())\n .slice(-3) // Show last 3 runs\n .map(([runId, memories]) => {\n const sortedMemories = memories.sort(\n (a: Memory, b: Memory) => (a.createdAt || 0) - (b.createdAt || 0)\n );\n\n const thought = sortedMemories[0]?.content?.planThought || '';\n const runText = sortedMemories\n .map((mem: Memory) => {\n const actionName = mem.content?.actionName || 'Unknown';\n const status = mem.content?.actionStatus || 'unknown';\n const planStep = mem.content?.planStep || '';\n const text = mem.content?.text || '';\n const error = mem.content?.error || '';\n\n let memText = ` - ${actionName} (${status})`;\n if (planStep) memText += ` [${planStep}]`;\n if (error) {\n memText += `: Error - ${error}`;\n } else if (text && text !== `Executed action: ${actionName}`) {\n memText += `: ${text}`;\n }\n\n return memText;\n })\n .join('\\n');\n\n return `**Action Run ${runId.slice(0, 8)}**${\n thought ? ` - \"${thought}\"` : ''\n }\\n${runText}`;\n })\n .join('\\n\\n');\n\n actionResultsText = formattedActionResults\n ? addHeader('# Recent Action Executions', formattedActionResults)\n : '';\n }\n\n // Create formatted text with headers\n const recentPosts =\n formattedRecentPosts && formattedRecentPosts.length > 0\n ? addHeader('# Posts in Thread', formattedRecentPosts)\n : '';\n\n const recentMessages =\n formattedRecentMessages && formattedRecentMessages.length > 0\n ? addHeader('# Conversation Messages', formattedRecentMessages)\n : '';\n\n // Handle empty conversation case\n if (\n !recentPosts &&\n !recentMessages &&\n dialogueMessages.length === 0 &&\n !message.content.text\n ) {\n return {\n data: {\n summaries: [],\n recentMessages: [],\n actionResults: [],\n mode: 'full_conversation',\n },\n values: {\n recentMessage: 'No recent message available.',\n },\n text: 'No recent messages available',\n };\n }\n\n // Get most recent message for context\n let recentMessage = 'No recent message available.';\n if (dialogueMessages.length > 0) {\n const mostRecentMessage = [...dialogueMessages].sort(\n (a, b) => (b.createdAt || 0) - (a.createdAt || 0)\n )[0];\n\n const formattedSingleMessage = formatMessages({\n messages: [mostRecentMessage],\n entities: entitiesData,\n });\n\n if (formattedSingleMessage) {\n recentMessage = formattedSingleMessage;\n }\n }\n\n // Build received message header\n const metaData = message.metadata as CustomMetadata;\n const senderName =\n entitiesData.find((entity: Entity) => entity.id === message.entityId)?.names[0] ||\n metaData?.entityName ||\n 'Unknown User';\n const receivedMessageContent = message.content.text;\n const hasReceivedMessage = !!receivedMessageContent?.trim();\n\n const receivedMessageHeader = hasReceivedMessage\n ? addHeader('# Received Message', `${senderName}: ${receivedMessageContent}`)\n : '';\n\n const focusHeader = hasReceivedMessage\n ? addHeader(\n '# Focus your response',\n `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message. Do not repeat earlier replies unless the sender asks again.`\n )\n : '';\n\n // Combine all sections\n const text = [\n isPostFormat ? recentPosts : recentMessages,\n actionResultsText,\n recentMessages || recentPosts || message.content.text ? receivedMessageHeader : '',\n recentMessages || recentPosts || message.content.text ? focusHeader : '',\n ]\n .filter(Boolean)\n .join('\\n\\n');\n\n return {\n data: {\n summaries: [],\n recentMessages: dialogueMessages,\n actionResults: actionResultMessages,\n mode: 'full_conversation',\n },\n values: {\n ...((isPostFormat ? recentPosts : recentMessages) && {\n recentMessages: isPostFormat ? recentPosts : recentMessages,\n }),\n ...(recentPosts && { recentPosts }),\n ...(actionResultsText && { recentActionResults: actionResultsText }),\n ...(recentMessage && { recentMessage }),\n ...(receivedMessageHeader && { receivedMessageHeader }),\n ...(focusHeader && { focusHeader }),\n },\n text,\n };\n } else {\n // ========== LONG CONVERSATION MODE ==========\n // Use summaries + recent unsummarized messages\n\n const currentSummary = await memoryService.getCurrentSessionSummary(roomId);\n const lastOffset = currentSummary?.lastMessageOffset || 0;\n\n // Get recent unsummarized messages (after the last summary offset)\n const unsummarizedMessages = await runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: config.shortTermRetainRecent,\n unique: false,\n start: lastOffset,\n });\n\n // Get entity details for formatting\n const entitiesData = await getEntityDetails({ runtime, roomId });\n const room = await runtime.getRoom(roomId);\n\n // Determine format\n const isPostFormat = room?.type\n ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD\n : false;\n\n // Format unsummarized messages\n let recentMessagesText = '';\n if (unsummarizedMessages.length > 0) {\n const dialogueMessages = unsummarizedMessages.filter(\n (msg) =>\n !(msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result')\n );\n\n if (isPostFormat) {\n recentMessagesText = formatPosts({\n messages: dialogueMessages,\n entities: entitiesData,\n conversationHeader: false,\n });\n } else {\n recentMessagesText = formatMessages({\n messages: dialogueMessages,\n entities: entitiesData,\n });\n }\n\n if (recentMessagesText) {\n recentMessagesText = addHeader('# Recent Messages', recentMessagesText);\n }\n }\n\n // Format summary\n let summaryText = '';\n if (currentSummary) {\n const messageRange = `${currentSummary.messageCount} messages`;\n const timeRange = new Date(currentSummary.startTime).toLocaleDateString();\n\n summaryText = `**Previous Conversation** (${messageRange}, ${timeRange})\\n`;\n summaryText += currentSummary.summary;\n\n if (currentSummary.topics && currentSummary.topics.length > 0) {\n summaryText += `\\n*Topics: ${currentSummary.topics.join(', ')}*`;\n }\n\n summaryText = addHeader('# Conversation Summary', summaryText);\n }\n\n // Build received message header\n const metaData = message.metadata as CustomMetadata;\n const senderName =\n entitiesData.find((entity: Entity) => entity.id === message.entityId)?.names[0] ||\n metaData?.entityName ||\n 'Unknown User';\n const receivedMessageContent = message.content.text;\n const hasReceivedMessage = !!receivedMessageContent?.trim();\n\n const receivedMessageHeader = hasReceivedMessage\n ? addHeader('# Received Message', `${senderName}: ${receivedMessageContent}`)\n : '';\n\n const focusHeader = hasReceivedMessage\n ? addHeader(\n '# Focus your response',\n `You are replying to the above message from **${senderName}**. Keep your answer relevant to that message.`\n )\n : '';\n\n // Combine sections\n const text = [\n summaryText,\n recentMessagesText,\n hasReceivedMessage ? receivedMessageHeader : '',\n hasReceivedMessage ? focusHeader : '',\n ]\n .filter(Boolean)\n .join('\\n\\n');\n\n return {\n data: {\n summaries: currentSummary ? [currentSummary] : [],\n recentMessages: unsummarizedMessages,\n mode: 'summarized',\n },\n values: {\n ...(summaryText && { sessionSummaries: summaryText }),\n ...(recentMessagesText && { recentMessages: recentMessagesText }),\n ...(receivedMessageHeader && { receivedMessageHeader }),\n ...(focusHeader && { focusHeader }),\n },\n text,\n };\n }\n } catch (error) {\n logger.error({ error }, 'Error in shortTermMemoryProvider:');\n return {\n data: { summaries: [], recentMessages: [], mode: 'error' },\n values: {},\n text: 'Error retrieving conversation context.',\n };\n }\n },\n};\n",
|
|
13
|
-
"import {
|
|
14
|
-
"import type {
|
|
5
|
+
"import {\n type IAgentRuntime,\n Service,\n type UUID,\n logger,\n type ServiceTypeName,\n ModelType,\n parseKeyValueXml,\n parseBooleanFromText,\n} from '@elizaos/core';\nimport { BM25 } from '@elizaos/core';\nimport type { Metadata } from '@elizaos/core';\nimport {\n type LongTermMemory,\n type LongTermMemoryConfig,\n type LongTermMemorySearchParams,\n type LongTermMemoryRetrievalResult,\n type ExtractedLongTermMemory,\n type ConversationSummary,\n MemoryType,\n type EmbeddingDimensionColumn,\n MEMORY_DIMENSION_MAP,\n} from '../types/index';\nimport { LongTermMemoryRepository, ConversationSummaryRepository } from '../repositories/index';\nimport {\n generateEmbedding,\n cleanEmbedding,\n applyDecayScoring,\n mergeSearchResults,\n formatMemoriesForContext,\n} from '../utils/index';\nimport { trimToTokenBudget, estimateTokenCount } from '../utils/token-counter';\n\n/**\n * Long-Term Memory Service - State-of-the-Art Cognitive Memory System\n *\n * Research: Based on comprehensive analysis in refactor.md\n *\n * This service implements:\n * 1. Three-tier long-term memory taxonomy (Episodic, Semantic, Procedural)\n * 2. Memory consolidation pipeline (transient filtering)\n * 3. Hybrid retrieval (Vector + BM25 + Graph)\n * 4. Exponential decay for long-term memory forgetting\n * 5. Contextual embeddings for superior retrieval\n * 6. Contradiction detection and resolution\n *\n * Architecture Philosophy:\n * - Async consolidation: Don't block the conversation loop\n * - Decay-weighted scoring: Recent and frequently accessed long-term memories score higher\n * - Graph-guided retrieval: Use relations for context\n * - Confidence-based filtering: Only store high-quality extractions\n */\nexport class MemoryService extends Service {\n static serviceType: ServiceTypeName = 'memory' as ServiceTypeName;\n\n declare config: LongTermMemoryConfig & Metadata;\n private bm25Index: BM25 | null = null;\n private embeddingDimension?: EmbeddingDimensionColumn;\n private isInitialized = false;\n\n // Repositories\n private longTermMemoryRepo!: LongTermMemoryRepository;\n private conversationSummaryRepo!: ConversationSummaryRepository;\n\n capabilityDescription =\n 'State-of-the-art cognitive memory system with episodic, semantic, and procedural memory';\n\n /**\n * Default configuration based on research recommendations\n * Research: Section 6 \"Implementation Strategy\"\n */\n private static defaultConfig: LongTermMemoryConfig & Metadata = {\n consolidationThreshold: 12,\n minConfidence: 0.7,\n enableVectorSearch: true,\n enableBM25: true,\n retrievalLimit: 5,\n tokenBudget: 1000,\n defaultDecayRates: {\n [MemoryType.EPISODIC]: 0.05,\n [MemoryType.SEMANTIC]: 0.01,\n [MemoryType.PROCEDURAL]: 0.02,\n },\n enableContradictionDetection: true,\n summarization: {\n enabled: true,\n messagesPerSummary: 7,\n summariesPerLevel: 5,\n maxDepth: 3,\n summaryTokenBudget: 500,\n },\n };\n\n constructor(runtime?: IAgentRuntime) {\n super(runtime);\n this.config = { ...MemoryService.defaultConfig };\n }\n\n static async start(runtime: IAgentRuntime): Promise<Service> {\n const service = new MemoryService(runtime);\n await service.initialize(runtime);\n return service;\n }\n\n async stop(): Promise<void> {\n logger.info('MemoryService stopped');\n }\n\n async initialize(runtime: IAgentRuntime): Promise<void> {\n this.runtime = runtime;\n\n // Load configuration from runtime settings\n this.loadConfiguration();\n\n // Ensure embedding dimension is set dynamically based on the model\n await this.ensureEmbeddingDimension();\n\n // Initialize repositories\n this.longTermMemoryRepo = new LongTermMemoryRepository(runtime, this.embeddingDimension);\n this.conversationSummaryRepo = new ConversationSummaryRepository(\n runtime,\n this.embeddingDimension\n );\n\n logger.info({ config: this.config }, 'MemoryService initialized');\n\n // Initialize BM25 index if enabled\n if (this.config.enableBM25) {\n await this.rebuildBM25Index();\n }\n\n this.isInitialized = true;\n }\n\n /**\n * Load configuration from runtime settings\n */\n private loadConfiguration(): void {\n const threshold = this.runtime.getSetting('MEMORY_CONSOLIDATION_THRESHOLD');\n if (threshold) {\n this.config.consolidationThreshold = parseInt(threshold, 10);\n }\n\n const minConfidence = this.runtime.getSetting('MEMORY_MIN_CONFIDENCE');\n if (minConfidence) {\n this.config.minConfidence = parseFloat(minConfidence);\n }\n\n const enableVector = this.runtime.getSetting('MEMORY_ENABLE_VECTOR_SEARCH');\n logger.debug(\n {\n enableVector,\n type: typeof enableVector,\n defaultValue: this.config.enableVectorSearch,\n },\n 'Loading MEMORY_ENABLE_VECTOR_SEARCH setting'\n );\n if (enableVector !== undefined && enableVector !== null && enableVector !== '') {\n this.config.enableVectorSearch = enableVector === 'true' || enableVector === true;\n logger.info(\n { enabled: this.config.enableVectorSearch },\n 'Vector search explicitly configured via environment variable'\n );\n } else {\n logger.info(\n { enabled: this.config.enableVectorSearch },\n 'Vector search using default configuration'\n );\n }\n\n const enableBM25 = this.runtime.getSetting('MEMORY_ENABLE_BM25');\n logger.debug(\n {\n enableBM25,\n type: typeof enableBM25,\n defaultValue: this.config.enableBM25,\n },\n 'Loading MEMORY_ENABLE_BM25 setting'\n );\n if (enableBM25 !== undefined && enableBM25 !== null && enableBM25 !== '') {\n this.config.enableBM25 = enableBM25 === 'true' || enableBM25 === true;\n logger.info(\n { enabled: this.config.enableBM25 },\n 'BM25 search explicitly configured via environment variable'\n );\n } else {\n logger.info({ enabled: this.config.enableBM25 }, 'BM25 search using default configuration');\n }\n\n const retrievalLimit = this.runtime.getSetting('MEMORY_RETRIEVAL_LIMIT');\n if (retrievalLimit) {\n this.config.retrievalLimit = parseInt(retrievalLimit, 10);\n }\n\n const tokenBudget = this.runtime.getSetting('MEMORY_TOKEN_BUDGET');\n if (tokenBudget) {\n this.config.tokenBudget = parseInt(tokenBudget, 10);\n }\n\n // Hierarchical Summarization Configuration\n const summaryEnabled = this.runtime.getSetting('MEMORY_SUMMARY_ENABLED');\n logger.debug(\n {\n summaryEnabled,\n type: typeof summaryEnabled,\n defaultValue: this.config.summarization?.enabled,\n },\n 'Loading MEMORY_SUMMARY_ENABLED setting'\n );\n if (summaryEnabled !== undefined && summaryEnabled !== null && summaryEnabled !== '') {\n this.config.summarization!.enabled = summaryEnabled === 'true' || summaryEnabled === true;\n logger.info(\n { enabled: this.config.summarization!.enabled },\n 'Summarization explicitly configured via environment variable'\n );\n } else {\n logger.info(\n { enabled: this.config.summarization!.enabled },\n 'Summarization using default configuration'\n );\n }\n\n const messagesPerSummary = this.runtime.getSetting('MEMORY_MESSAGES_PER_SUMMARY');\n if (messagesPerSummary) {\n this.config.summarization!.messagesPerSummary = parseInt(messagesPerSummary, 10);\n }\n\n const summariesPerLevel = this.runtime.getSetting('MEMORY_SUMMARIES_PER_LEVEL');\n if (summariesPerLevel) {\n this.config.summarization!.summariesPerLevel = parseInt(summariesPerLevel, 10);\n }\n\n const maxDepth = this.runtime.getSetting('MEMORY_SUMMARY_MAX_DEPTH');\n if (maxDepth) {\n this.config.summarization!.maxDepth = parseInt(maxDepth, 10);\n }\n\n const summaryTokenBudget = this.runtime.getSetting('MEMORY_SUMMARY_TOKEN_BUDGET');\n if (summaryTokenBudget) {\n this.config.summarization!.summaryTokenBudget = parseInt(summaryTokenBudget, 10);\n }\n }\n\n /**\n * Ensure embedding dimension is set dynamically based on the model\n */\n private async ensureEmbeddingDimension(): Promise<void> {\n try {\n const embeddingModel = this.runtime.getModel(ModelType.TEXT_EMBEDDING);\n if (!embeddingModel) {\n logger.warn('No TEXT_EMBEDDING model registered. Embeddings will not be generated.');\n return;\n }\n\n // Generate a test embedding to determine dimension\n const testEmbedding = await this.runtime.useModel(ModelType.TEXT_EMBEDDING, {\n text: 'test',\n });\n\n if (!testEmbedding || !Array.isArray(testEmbedding)) {\n throw new Error('Invalid embedding received from model');\n }\n\n const dimension = testEmbedding.length;\n const dimensionColumn = MEMORY_DIMENSION_MAP[dimension];\n\n if (!dimensionColumn) {\n throw new Error(\n `Unsupported embedding dimension: ${dimension}. Supported dimensions: ${Object.keys(MEMORY_DIMENSION_MAP).join(', ')}`\n );\n }\n\n this.embeddingDimension = dimensionColumn;\n logger.info(`Memory embedding dimension set to ${dimension} (${dimensionColumn})`);\n } catch (error) {\n logger.error('Failed to ensure embedding dimension:', JSON.stringify(error));\n throw error;\n }\n }\n\n /**\n * Get current configuration\n */\n getConfig(): LongTermMemoryConfig {\n return { ...this.config };\n }\n\n /**\n * Update configuration\n */\n updateConfig(updates: Partial<LongTermMemoryConfig>): void {\n this.config = { ...this.config, ...updates };\n\n // Rebuild BM25 if it was toggled\n if (updates.enableBM25 !== undefined) {\n if (updates.enableBM25 && !this.bm25Index) {\n this.rebuildBM25Index();\n } else if (!updates.enableBM25) {\n this.bm25Index = null;\n }\n }\n }\n\n // =============================================================================\n // PART 1: STORAGE & BASIC CRUD\n // =============================================================================\n\n /**\n * Store a new long-term memory\n *\n * Research: Section 3.2.1 \"Contextual Embeddings\"\n */\n async storeLongTermMemory(\n memory: Omit<\n LongTermMemory,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount' | 'isActive' | 'embedding'\n >\n ): Promise<LongTermMemory> {\n // Generate contextual embedding\n let embedding: number[] | undefined;\n if (this.embeddingDimension) {\n try {\n const rawEmbedding = await generateEmbedding(this.runtime, memory.embeddingContext);\n embedding = cleanEmbedding(rawEmbedding);\n } catch (error) {\n logger.warn('Failed to generate embedding for long-term memory:', JSON.stringify(error));\n }\n }\n\n const stored = await this.longTermMemoryRepo.insert(memory, embedding);\n\n // Update BM25 index if enabled\n if (this.config.enableBM25 && this.bm25Index) {\n await this.rebuildBM25Index();\n }\n\n return stored;\n }\n\n /**\n * Retrieve long-term memory by ID\n */\n async getLongTermMemory(id: UUID): Promise<LongTermMemory | null> {\n return this.longTermMemoryRepo.findById(id);\n }\n\n /**\n * Update an existing long-term memory\n *\n * Research: Section 4.3.2 \"Resolution Strategies\"\n */\n async updateLongTermMemory(\n id: UUID,\n updates: Partial<Omit<LongTermMemory, 'id' | 'agentId' | 'createdAt'>>\n ): Promise<void> {\n let newEmbedding: number[] | undefined;\n\n // Regenerate embedding if context changed\n if (updates.embeddingContext !== undefined && this.embeddingDimension) {\n try {\n const rawEmbedding = await generateEmbedding(this.runtime, updates.embeddingContext);\n newEmbedding = cleanEmbedding(rawEmbedding);\n } catch (error) {\n logger.warn('Failed to regenerate embedding:', JSON.stringify(error));\n }\n }\n\n await this.longTermMemoryRepo.update(id, updates, newEmbedding);\n }\n\n /**\n * Delete a long-term memory (hard delete)\n */\n async deleteLongTermMemory(id: UUID): Promise<void> {\n await this.longTermMemoryRepo.delete(id);\n }\n\n /**\n * Get all long-term memories for an entity (with basic filtering)\n */\n async getLongTermMemories(\n entityId: UUID,\n type?: MemoryType,\n limit: number = 20,\n includeInactive: boolean = false\n ): Promise<LongTermMemory[]> {\n return this.longTermMemoryRepo.findByEntity(entityId, type, limit, includeInactive);\n }\n\n // =============================================================================\n // PART 2: CONTRADICTION HANDLING\n // =============================================================================\n\n /**\n * Handle contradictory long-term memory\n *\n * Research: Section 4.3 \"Handling Contradictions\"\n */\n async handleContradiction(\n entityId: UUID,\n newMemory: Omit<\n LongTermMemory,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount' | 'isActive' | 'embedding'\n >\n ): Promise<void> {\n // Search for potentially conflicting memories\n const searchResults = await this.searchLongTermMemories({\n entityId,\n query: newMemory.content,\n type: newMemory.type,\n limit: 5,\n includeInactive: false,\n });\n\n if (searchResults.length === 0) {\n await this.storeLongTermMemory(newMemory);\n return;\n }\n\n // Use LLM to check for real contradictions\n const contradictingMemory = await this.detectContradiction(newMemory, searchResults);\n\n if (contradictingMemory) {\n logger.info(\n {\n oldMemoryId: contradictingMemory.id,\n newContent: newMemory.content,\n },\n 'Contradiction detected, superseding old memory'\n );\n\n // Mark old memory as inactive\n await this.updateLongTermMemory(contradictingMemory.id, {\n isActive: false,\n });\n\n // Store new memory with supersedes link\n const stored = await this.storeLongTermMemory({\n ...newMemory,\n supersedesId: contradictingMemory.id,\n });\n\n logger.info({ newMemoryId: stored.id }, 'Stored superseding memory');\n } else {\n await this.storeLongTermMemory(newMemory);\n }\n }\n\n /**\n * Detect if new memory contradicts any existing memory\n *\n * Research: Section 4.3.1 \"Detection Logic\"\n */\n async detectContradiction(\n newMemory: Omit<\n LongTermMemory,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount' | 'isActive' | 'embedding'\n >,\n existingMemories: LongTermMemoryRetrievalResult[]\n ): Promise<LongTermMemory | null> {\n const prompt = `# TASK: Contradiction Detection\n\nYou are analyzing whether a new long-term memory contradicts any existing long-term memories.\n\n## New Long-Term Memory:\n\"${newMemory.content}\"\n\n## Existing Long-Term Memories:\n${existingMemories.map((m, idx) => `${idx + 1}. \"${m.content}\" (confidence: ${m.confidence}, created: ${m.createdAt.toISOString()})`).join('\\n')}\n\n## Instructions:\nDetermine if the new long-term memory directly contradicts any of the existing long-term memories. A contradiction means the statements cannot both be true.\n\nExamples of contradictions:\n- \"User likes blue\" vs \"User hates blue\"\n- \"User lives in Paris\" vs \"User lives in London\"\n\nExamples of non-contradictions (these are compatible):\n- \"User likes blue\" vs \"User likes blue only for clothes\" (nuance, not contradiction)\n- \"User was in Paris\" vs \"User moved to London\" (state change over time)\n\n## Output Format:\nReturn an XML response:\n\n<response>\n<hasContradiction>true or false</hasContradiction>\n<contradictingMemoryIndex>number or null</contradictingMemoryIndex>\n<reasoning>Explanation</reasoning>\n</response>\n\nIf no contradiction is found, set hasContradiction to false and contradictingMemoryIndex to null.`;\n\n try {\n const response = await this.runtime.useModel(ModelType.TEXT_LARGE, {\n prompt,\n temperature: 0.2,\n });\n\n const responseText = typeof response === 'string' ? response : JSON.stringify(response);\n const result = parseKeyValueXml(responseText);\n\n if (!result) {\n logger.warn('Failed to parse contradiction detection XML response');\n return null;\n }\n\n const hasContradiction = parseBooleanFromText(\n typeof result.hasContradiction === 'boolean'\n ? result.hasContradiction\n ? 'true'\n : 'false'\n : result.hasContradiction\n );\n\n let contradictingMemoryIndex: number | null = null;\n if (result.contradictingMemoryIndex !== null && result.contradictingMemoryIndex !== 'null') {\n const parsed = parseInt(result.contradictingMemoryIndex, 10);\n if (!isNaN(parsed)) {\n contradictingMemoryIndex = parsed;\n }\n }\n\n if (hasContradiction && contradictingMemoryIndex !== null) {\n const contradictingMemory = existingMemories[contradictingMemoryIndex];\n logger.info({ reasoning: result.reasoning }, 'Contradiction detected');\n return contradictingMemory;\n }\n\n return null;\n } catch (error) {\n logger.error({ error }, 'Failed to detect contradiction');\n return null;\n }\n }\n\n // ============================================================================\n // PART 3: HYBRID RETRIEVAL (Vector + BM25 + Graph + Decay)\n // ============================================================================\n\n /**\n * Search long-term memories with hybrid retrieval\n *\n * Research: Section 3 \"Retrieval Augmented Generation Strategy\"\n */\n async searchLongTermMemories(\n params: LongTermMemorySearchParams\n ): Promise<LongTermMemoryRetrievalResult[]> {\n const limit = params.limit || this.config.retrievalLimit;\n const tokenBudget = params.tokenBudget || this.config.tokenBudget;\n const minConfidence =\n params.minConfidence !== undefined ? params.minConfidence : this.config.minConfidence;\n const similarityThreshold =\n params.similarityThreshold !== undefined ? params.similarityThreshold : 0.3;\n\n logger.debug(\n {\n limit,\n tokenBudget,\n minConfidence,\n similarityThreshold,\n vectorSearchEnabled: this.config.enableVectorSearch,\n bm25Enabled: this.config.enableBM25,\n },\n 'Searching long-term memories'\n );\n\n // Step 1: Vector search (if enabled)\n let vectorResults: LongTermMemoryRetrievalResult[] = [];\n if (this.config.enableVectorSearch) {\n logger.debug('Vector search enabled, searching...');\n vectorResults = await this.vectorSearch(params, similarityThreshold);\n }\n\n logger.debug({ vectorResults: vectorResults.length }, 'Vector search results');\n\n // Step 2: BM25 search (if enabled)\n let bm25Results: LongTermMemoryRetrievalResult[] = [];\n if (this.config.enableBM25) {\n bm25Results = await this.bm25Search(params);\n }\n\n // Step 3: Merge results\n const mergedResults = mergeSearchResults(vectorResults, bm25Results);\n\n // Step 4: Filter by confidence\n const confidenceFiltered = mergedResults.filter((m) => m.confidence >= minConfidence);\n\n // Step 5: Apply decay scoring\n const decayedResults = applyDecayScoring(confidenceFiltered);\n\n // Step 6: Sort by final score and limit\n const sorted = decayedResults.sort((a, b) => b.finalScore - a.finalScore);\n const topResults = sorted.slice(0, limit);\n\n // Step 7: Enforce token budget\n const budgetedResults = trimToTokenBudget(\n topResults,\n tokenBudget,\n (memory) => memory.content,\n 15\n );\n\n logger.debug(\n {\n totalResults: sorted.length,\n afterCountLimit: topResults.length,\n afterTokenBudget: budgetedResults.length,\n tokenBudget,\n estimatedTokens: budgetedResults.reduce(\n (sum, m) => sum + estimateTokenCount(m.content) + 15,\n 0\n ),\n },\n 'Applied token budget to memory retrieval'\n );\n\n // Step 8: Update access metadata\n await this.longTermMemoryRepo.updateAccessMetadata(budgetedResults.map((r) => r.id));\n\n return budgetedResults;\n }\n\n /**\n * Vector search implementation\n */\n private async vectorSearch(\n params: LongTermMemorySearchParams,\n similarityThreshold: number = 0.3\n ): Promise<LongTermMemoryRetrievalResult[]> {\n if (!this.embeddingDimension) {\n logger.warn('Embedding dimension not set, skipping vector search');\n return [];\n }\n\n try {\n // Generate query embedding\n const rawEmbedding = await generateEmbedding(this.runtime, params.query);\n const queryEmbedding = cleanEmbedding(rawEmbedding);\n\n if (!queryEmbedding || !Array.isArray(queryEmbedding)) {\n logger.warn('Failed to generate query embedding');\n return [];\n }\n\n return await this.longTermMemoryRepo.vectorSearch(\n params,\n queryEmbedding,\n similarityThreshold\n );\n } catch (error) {\n logger.error('Failed to execute vector search:', JSON.stringify(error));\n return [];\n }\n }\n\n /**\n * BM25 search implementation\n */\n private async bm25Search(\n params: LongTermMemorySearchParams\n ): Promise<LongTermMemoryRetrievalResult[]> {\n if (!this.bm25Index) {\n return [];\n }\n\n try {\n const bm25Results = this.bm25Index.search(params.query, params.limit || 20);\n\n const memoryPromises = bm25Results.map(async (result) => {\n const doc = this.bm25Index.documents[result.index];\n if (!doc || !doc.id) {\n logger.warn({ resultIndex: result.index }, 'BM25 result has no document ID');\n return null;\n }\n\n const memory = await this.getLongTermMemory(doc.id as UUID);\n if (!memory) return null;\n\n // Filter by params\n if (memory.entityId !== params.entityId) return null;\n if (!params.includeInactive && !memory.isActive) return null;\n if (params.type && memory.type !== params.type) return null;\n if (params.minConfidence && memory.confidence < params.minConfidence) return null;\n\n return {\n ...memory,\n relevanceScore: result.score,\n activationScore: 0,\n finalScore: 0,\n } as LongTermMemoryRetrievalResult;\n });\n\n const results = await Promise.all(memoryPromises);\n return results.filter((r) => r !== null) as LongTermMemoryRetrievalResult[];\n } catch (error) {\n logger.error({ error }, 'BM25 search failed');\n return [];\n }\n }\n\n /**\n * Rebuild BM25 index from database\n */\n private async rebuildBM25Index(): Promise<void> {\n try {\n const memories = await this.longTermMemoryRepo.fetchAllActive();\n\n const documents = memories.map((row) => ({\n id: row.id,\n content: row.content,\n embeddingContext: row.embeddingContext,\n }));\n\n this.bm25Index = new BM25(documents, {\n k1: 1.2,\n b: 0.75,\n stemming: true,\n minLength: 2,\n });\n\n logger.info({ documentCount: documents.length }, 'Rebuilt BM25 index');\n } catch (error) {\n logger.error({ error }, 'Failed to rebuild BM25 index');\n this.bm25Index = null;\n }\n }\n\n /**\n * Get formatted memories for context injection\n *\n * Research: Section 5.1.3 \"Tier 3: Just-In-Time Injection\"\n */\n async getFormattedLongTermMemoriesForContext(\n entityId: UUID,\n query: string,\n roomId?: UUID\n ): Promise<string> {\n const memories = await this.searchLongTermMemories({\n entityId,\n query,\n roomId,\n limit: this.config.retrievalLimit,\n });\n\n return formatMemoriesForContext(memories);\n }\n\n // ===========================================================================\n // PART 4: HIERARCHICAL CONVERSATION SUMMARIZATION\n // ===========================================================================\n\n /**\n * Store a conversation summary\n *\n * Research: Section 5.1.2 \"Hierarchical Conversation Summarization\"\n */\n async storeSummary(\n summary: Omit<ConversationSummary, 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount'>\n ): Promise<ConversationSummary> {\n // Generate embedding for summary content\n let embedding: number[] | undefined;\n if (this.embeddingDimension) {\n try {\n const rawEmbedding = await generateEmbedding(this.runtime, summary.content);\n embedding = cleanEmbedding(rawEmbedding);\n } catch (error) {\n logger.warn('Failed to generate embedding for summary:', JSON.stringify(error));\n }\n }\n\n return this.conversationSummaryRepo.insert(summary, embedding);\n }\n\n /**\n * Get summaries at a specific level for a room\n */\n async getSummariesByLevel(roomId: UUID, level: number): Promise<ConversationSummary[]> {\n return this.conversationSummaryRepo.findByLevel(roomId, level);\n }\n\n /**\n * Search summaries by semantic similarity\n *\n * Research: Section 5.1.2 \"Tier 2: The Conversation Summary\"\n */\n async searchSummaries(params: {\n entityId: UUID;\n roomId: UUID;\n query: string;\n limit?: number;\n tokenBudget?: number;\n }): Promise<ConversationSummary[]> {\n if (!this.embeddingDimension) {\n logger.warn('Embedding dimension not set, skipping summary search');\n return [];\n }\n\n const limit = params.limit || 5;\n const tokenBudget = params.tokenBudget || this.config.summarization?.summaryTokenBudget || 500;\n\n try {\n // Generate query embedding\n const rawEmbedding = await generateEmbedding(this.runtime, params.query);\n const queryEmbedding = cleanEmbedding(rawEmbedding);\n\n if (!queryEmbedding || !Array.isArray(queryEmbedding)) {\n logger.warn('Failed to generate query embedding');\n return [];\n }\n\n const summaries = await this.conversationSummaryRepo.vectorSearch(\n params.entityId,\n params.roomId,\n queryEmbedding,\n limit\n );\n\n // Apply token budget\n const budgetedSummaries = trimToTokenBudget(summaries, tokenBudget, (s) => s.content, 10);\n\n // Update access metadata\n await this.conversationSummaryRepo.updateAccessMetadata(budgetedSummaries.map((s) => s.id));\n\n return budgetedSummaries;\n } catch (error) {\n logger.error('Failed to search summaries:', JSON.stringify(error));\n return [];\n }\n }\n\n /**\n * Get the most recent Level 1 summary for a room and entity\n * Used to determine which messages have already been summarized\n *\n * @returns The most recent Level 1 summary, or null if none exist\n */\n async getMostRecentLevel1Summary(\n roomId: UUID,\n entityId: UUID\n ): Promise<ConversationSummary | null> {\n try {\n const summaries = await this.conversationSummaryRepo.findByLevel(roomId, 1);\n\n if (summaries.length === 0) {\n return null;\n }\n\n // Filter by entity and sort by endTime (most recent first)\n const entitySummaries = summaries\n .filter((s) => s.entityId === entityId)\n .sort((a, b) => b.endTime.getTime() - a.endTime.getTime());\n\n return entitySummaries.length > 0 ? entitySummaries[0] : null;\n } catch (error) {\n logger.error('Failed to get most recent Level 1 summary:', JSON.stringify(error));\n return null;\n }\n }\n}\n",
|
|
6
|
+
"import type { UUID } from '@elizaos/core';\n\n/**\n * Embedding dimension column type mapping\n */\nexport type EmbeddingDimensionColumn =\n | 'dim384'\n | 'dim512'\n | 'dim768'\n | 'dim1024'\n | 'dim1536'\n | 'dim3072';\n\n/**\n * Dimension map for dynamic embedding support\n */\nexport const MEMORY_DIMENSION_MAP: Record<number, EmbeddingDimensionColumn> = {\n 384: 'dim384',\n 512: 'dim512',\n 768: 'dim768',\n 1024: 'dim1024',\n 1536: 'dim1536',\n 3072: 'dim3072',\n};\n\n/**\n * Memory Type Taxonomy (Based on Cognitive Science)\n *\n * Research: Section 1.1 \"The Cognitive Hierarchy of Agent Memory\"\n * - EPISODIC: Specific events anchored in time and place (conversation logs)\n * - SEMANTIC: Facts and knowledge detached from specific episodes (user preferences, identity)\n * - PROCEDURAL: \"How-to\" knowledge and successful tool execution patterns\n */\nexport enum MemoryType {\n EPISODIC = 'EPISODIC',\n SEMANTIC = 'SEMANTIC',\n PROCEDURAL = 'PROCEDURAL',\n}\n\n/**\n * Decay Function Types\n *\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n * - EXPONENTIAL: Standard forgetting curve (Ebbinghaus)\n * - LINEAR: Simple time-based decay\n * - NONE: Core facts that never decay (identity, core preferences)\n */\nexport enum DecayFunction {\n EXPONENTIAL = 'EXPONENTIAL',\n LINEAR = 'LINEAR',\n NONE = 'NONE',\n}\n\n/**\n * Conversation Summary - Hierarchical Conversation Summarization\n *\n * Research: Section 5.1.2 \"Hierarchical Conversation Summarization\"\n *\n * This implements recursive, multi-level summarization for long conversations:\n * - Level 1: Summary of 50-100 messages\n * - Level 2+: Summary of lower-level summaries (recursive)\n *\n * Benefits:\n * - 10x token compression for very long conversations\n * - Maintains narrative flow without exploding context window\n * - Enables efficient retrieval of past conversation context\n */\nexport interface ConversationSummary {\n /** Unique identifier */\n id: UUID;\n\n /** Agent this summary belongs to */\n agentId: UUID;\n\n /** Entity (user) this summary is about */\n entityId: UUID;\n\n /** Room this summary belongs to */\n roomId: UUID;\n\n /**\n * Hierarchical level\n * - 1: Direct summarization of messages\n * - 2+: Summarization of lower-level summaries\n */\n level: number;\n\n /**\n * Parent summary ID (for tree structure)\n * - null for Level 1 (summarizes messages)\n * - UUID for Level 2+ (summarizes summaries)\n */\n parentSummaryId?: UUID;\n\n /** The summary content (human-readable paragraph) */\n content: string;\n\n /** Vector embedding for semantic search */\n embedding?: number[];\n\n /** Estimated token count of this summary */\n tokenCount: number;\n\n /** Time range this summary covers */\n startTime: Date;\n endTime: Date;\n\n /**\n * Number of source items summarized\n * - Level 1: message count\n * - Level 2+: summary count\n */\n sourceCount: number;\n\n /** IDs of source items (messages or summaries) */\n sourceIds: UUID[];\n\n /** When this summary was created */\n createdAt: Date;\n\n /** Last time this summary was accessed */\n lastAccessedAt: Date | null;\n\n /** How many times retrieved */\n accessCount: number;\n\n /** Flexible metadata (topics, sentiment, etc.) */\n metadata: Record<string, unknown>;\n}\n\n/**\n * Long-Term Memory Entry (The \"Engram\")\n *\n * Research: Section 4.1 \"The SOTA Memory Schema\"\n * This interface represents a single unit of long-term memory with all necessary metadata\n * for cognitive processing, including decay, confidence, and provenance tracking.\n */\nexport interface LongTermMemory {\n /** Unique identifier for this memory */\n id: UUID;\n\n /** Agent this memory belongs to */\n agentId: UUID;\n\n /** Entity (user/agent) this memory is about */\n entityId: UUID;\n\n /** Room/context where this memory was created */\n roomId?: UUID;\n\n /** Memory taxonomy type */\n type: MemoryType;\n\n /** The actual memory content (the fact or event) */\n content: string;\n\n /**\n * Contextualized content for embedding\n * Research: Section 3.2.1 \"Contextual Embeddings\"\n * Example: \"[User preference regarding programming]: I prefer Python over JavaScript\"\n */\n embeddingContext: string;\n\n /** Vector embedding of embeddingContext */\n embedding: number[];\n\n /**\n * Confidence score (0.0 to 1.0)\n * Research: Section 4.1 - Track certainty of extracted facts\n * - 1.0: User explicitly stated or verified\n * - < 1.0: LLM inferred or uncertain\n */\n confidence: number;\n\n /**\n * Decay rate (lambda λ) for exponential decay\n * Research: Section 4.2.2 \"Implementation Strategy\"\n * - ~0: Core facts (name, identity) - very slow decay\n * - 0.01: Mid-term facts (current projects) - fade over weeks\n * - 0.5+: Transient facts (lunch plans) - fade over days\n */\n decayRate: number;\n\n /** Type of decay function to use */\n decayFunction: DecayFunction;\n\n /** When this memory was created */\n createdAt: Date;\n\n /** When this memory was last accessed/retrieved */\n lastAccessedAt: Date | null;\n\n /**\n * How many times this memory has been retrieved\n * Research: Section 4.2.2 - High count = stronger memory (slower decay)\n */\n accessCount: number;\n\n /**\n * Soft delete flag for contradiction handling\n * Research: Section 4.3 \"Handling Contradictions\"\n * When a contradiction is found, old memory is marked inactive\n */\n isActive: boolean;\n\n /**\n * Provenance: Source tracking\n * Research: Section 4.1 \"Provenance / Lineage\"\n */\n source: {\n /** ID of the session where this was extracted */\n sessionId?: string;\n /** ID of the specific message that generated this fact */\n messageId?: string;\n /** Raw text snippet that triggered extraction */\n textSnippet?: string;\n /** Who provided the info (user ID or agent ID) */\n authorId?: string;\n /** Extraction model used (e.g., \"gpt-4-turbo\") */\n extractionModel?: string;\n };\n\n /**\n * Flexible metadata for future extensions\n * Can store: tags, categories, relationships, etc.\n */\n metadata: Record<string, unknown>;\n\n /**\n * Optional: ID of memory this one supersedes (for contradiction resolution)\n * Research: Section 4.3.1 \"Resolution Strategies\"\n */\n supersedesId?: UUID;\n}\n\n/**\n * Memory Configuration\n *\n * Research: Section 6 \"Implementation Strategy\"\n * Simplified configuration focusing on key parameters\n */\nexport interface LongTermMemoryConfig {\n /**\n * Number of messages before triggering consolidation\n * Research: Section 2.3 \"Consolidation Pipeline\"\n * Recommended: 10-20 messages\n */\n consolidationThreshold: number;\n\n /**\n * Minimum confidence to store a memory\n * Research: Section 2.2 \"Extraction Prompt Structure\"\n * Recommended: 0.7\n */\n minConfidence: number;\n\n /**\n * Enable vector search (requires embedding model)\n * Research: Section 3 \"RAG Strategy\"\n */\n enableVectorSearch: boolean;\n\n /**\n * Enable BM25 keyword search\n * Research: Section 3.2.1 - Combines with vector for Contextual Retrieval\n */\n enableBM25: boolean;\n\n /**\n * Number of memories to retrieve during RAG\n * Research: Section 5.1.3 \"Tier 3: Just-In-Time Injection\"\n */\n retrievalLimit: number;\n\n /**\n * Token budget for memory context injection\n * Research: Section 5.1.3 - Only highest-scoring memories within budget\n */\n tokenBudget: number;\n\n /**\n * Default decay rates for different memory types\n * Research: Section 4.2.2 \"Implementation Strategy\"\n */\n defaultDecayRates: {\n [MemoryType.EPISODIC]: number;\n [MemoryType.SEMANTIC]: number;\n [MemoryType.PROCEDURAL]: number;\n };\n\n /**\n * Enable contradiction detection and resolution\n * Research: Section 4.3 \"Handling Contradictions\"\n */\n enableContradictionDetection: boolean;\n\n /**\n * Hierarchical Summarization Configuration (GAP 3 fix)\n * Research: Section 5.1.2 \"Hierarchical Episodic Summarization\"\n */\n summarization?: {\n /** Enable hierarchical summarization */\n enabled: boolean;\n\n /** Number of messages before triggering Level 1 summary */\n messagesPerSummary: number;\n\n /** Number of Level N summaries before creating Level N+1 summary */\n summariesPerLevel: number;\n\n /** Maximum hierarchical depth (prevents infinite recursion) */\n maxDepth: number;\n\n /** Token budget for summary retrieval */\n summaryTokenBudget: number;\n };\n}\n\n/**\n * Extracted Long-Term Memory Result (from consolidation)\n *\n * Research: Section 2.2.2 \"Proposed Extraction Prompt Structure\"\n */\nexport interface ExtractedLongTermMemory {\n /** The memory type classification */\n type: MemoryType;\n\n /** The extracted content */\n content: string;\n\n /** Confidence score (0-1) */\n confidence: number;\n\n /** Whether this contradicts an existing memory */\n isContradiction: boolean;\n\n /** ID of the source message */\n sourceMessageId?: string;\n\n /**\n * Optional: Entity extraction for graph\n * Research: Section 3.1.2 \"Graph Advantages\"\n */\n entities?: {\n subject: string;\n predicate: string;\n object: string;\n };\n\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Consolidation Result\n *\n * Research: Section 2.2.2 \"OUTPUT FORMAT\"\n */\nexport interface ConsolidationResult {\n /** Reasoning trace for debugging */\n reasoningTrace: string;\n\n /** Brief summary of transient events (for episodic log) */\n transientSummary: string;\n\n /** Extracted persistent long-term memories */\n extractedMemories: ExtractedLongTermMemory[];\n}\n\n/**\n * Long-Term Memory Retrieval Result (with decay-adjusted scoring)\n *\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n */\nexport interface LongTermMemoryRetrievalResult extends LongTermMemory {\n /** Relevance score (vector similarity or BM25 score) */\n relevanceScore: number;\n\n /** Time-decayed activation score */\n activationScore: number;\n\n /** Final composite score (relevance * decay * confidence) */\n finalScore: number;\n}\n\n/**\n * Long-Term Memory Search Query Parameters\n */\nexport interface LongTermMemorySearchParams {\n /** Entity to search memories for */\n entityId: UUID;\n\n /** Optional room context filter */\n roomId?: UUID;\n\n /** Query text */\n query: string;\n\n /** Optional memory type filter */\n type?: MemoryType;\n\n /** Maximum results to return */\n limit?: number;\n\n /** Minimum confidence threshold (default: 0.7) */\n minConfidence?: number;\n\n /** Minimum similarity threshold for vector search (default: 0.3) */\n similarityThreshold?: number;\n\n /** Whether to include inactive (superseded) memories */\n includeInactive?: boolean;\n\n /** Token budget for this retrieval (overrides config default) */\n tokenBudget?: number;\n}\n",
|
|
7
|
+
"import type { IAgentRuntime, UUID } from '@elizaos/core';\nimport { logger } from '@elizaos/core';\nimport { eq, and, desc, sql, cosineDistance, gte, or, isNull } from 'drizzle-orm';\nimport { longTermMemories, longTermMemoryEmbeddings } from '../schemas/index';\nimport {\n type LongTermMemory,\n type LongTermMemoryRetrievalResult,\n type LongTermMemorySearchParams,\n type EmbeddingDimensionColumn,\n MemoryType,\n} from '../types/index';\nimport { mapDbRowToLongTermMemory } from '../utils/db-mapping';\n\n/**\n * Long-Term Memory Repository\n *\n * Handles all database operations for long-term memories\n * Provides clean data access layer separated from business logic\n */\nexport class LongTermMemoryRepository {\n constructor(\n private runtime: IAgentRuntime,\n private embeddingDimension?: EmbeddingDimensionColumn\n ) {}\n\n /**\n * Get database instance with health check\n */\n private async getDb(): Promise<any> {\n const adapter = (this.runtime as any).adapter || this.runtime;\n const db = adapter.db;\n\n if (!db) {\n throw new Error('Database not available');\n }\n\n // Health check for long-running operations\n try {\n const isReady = await adapter.isReady();\n if (!isReady) {\n logger.warn('[LongTermMemoryRepository] Database not ready, attempting reconnect...');\n await new Promise((resolve) => setTimeout(resolve, 1000));\n const stillNotReady = await adapter.isReady();\n if (stillNotReady === false) {\n throw new Error('Database connection lost and could not reconnect');\n }\n }\n } catch (error) {\n logger.error('[LongTermMemoryRepository] Database health check failed:', error);\n throw new Error('Database connection health check failed');\n }\n\n return db;\n }\n\n /**\n * Insert a new memory into database\n */\n async insert(\n memory: Omit<\n LongTermMemory,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount' | 'isActive' | 'embedding'\n >,\n embedding?: number[]\n ): Promise<LongTermMemory> {\n const db = await this.getDb();\n const id = crypto.randomUUID() as UUID;\n const now = new Date();\n\n const newMemory: LongTermMemory = {\n id,\n createdAt: now,\n lastAccessedAt: null,\n accessCount: 0,\n isActive: true,\n embedding: embedding || [],\n ...memory,\n };\n\n await db.transaction(async (tx: any) => {\n // Insert memory\n await tx.insert(longTermMemories).values({\n id: newMemory.id,\n agentId: newMemory.agentId,\n entityId: newMemory.entityId,\n roomId: newMemory.roomId || null,\n type: newMemory.type,\n content: newMemory.content,\n embeddingContext: newMemory.embeddingContext,\n confidence: newMemory.confidence,\n decayRate: newMemory.decayRate,\n decayFunction: newMemory.decayFunction,\n createdAt: now,\n lastAccessedAt: null,\n accessCount: 0,\n isActive: true,\n source: newMemory.source,\n metadata: newMemory.metadata,\n supersedesId: newMemory.supersedesId || null,\n });\n\n // Insert embedding if available\n if (embedding && this.embeddingDimension) {\n const embeddingValues: any = {\n id: crypto.randomUUID(),\n memoryId: id,\n createdAt: now,\n };\n embeddingValues[this.embeddingDimension] = embedding;\n await tx.insert(longTermMemoryEmbeddings).values(embeddingValues);\n }\n });\n\n logger.info(\n {\n id: newMemory.id,\n type: newMemory.type,\n entityId: newMemory.entityId,\n confidence: newMemory.confidence,\n },\n 'Stored new long-term memory'\n );\n\n return newMemory;\n }\n\n /**\n * Find memory by ID\n */\n async findById(id: UUID): Promise<LongTermMemory | null> {\n const db = await this.getDb();\n\n const results = await db\n .select()\n .from(longTermMemories)\n .where(eq(longTermMemories.id, id))\n .limit(1);\n\n if (results.length === 0) {\n return null;\n }\n\n return mapDbRowToLongTermMemory(results[0]);\n }\n\n /**\n * Update existing memory\n */\n async update(id: UUID, updates: Partial<LongTermMemory>, newEmbedding?: number[]): Promise<void> {\n const db = await this.getDb();\n\n const updateData: any = {};\n\n if (updates.content !== undefined) updateData.content = updates.content;\n if (updates.embeddingContext !== undefined)\n updateData.embeddingContext = updates.embeddingContext;\n if (updates.confidence !== undefined) updateData.confidence = updates.confidence;\n if (updates.decayRate !== undefined) updateData.decayRate = updates.decayRate;\n if (updates.decayFunction !== undefined) updateData.decayFunction = updates.decayFunction;\n if (updates.lastAccessedAt !== undefined) updateData.lastAccessedAt = updates.lastAccessedAt;\n if (updates.accessCount !== undefined) updateData.accessCount = updates.accessCount;\n if (updates.isActive !== undefined) updateData.isActive = updates.isActive;\n if (updates.source !== undefined) updateData.source = updates.source;\n if (updates.metadata !== undefined) updateData.metadata = updates.metadata;\n if (updates.supersedesId !== undefined) updateData.supersedesId = updates.supersedesId;\n\n await db.transaction(async (tx: any) => {\n // Update memory\n await tx.update(longTermMemories).set(updateData).where(eq(longTermMemories.id, id));\n\n // Update embedding if provided\n if (newEmbedding && this.embeddingDimension) {\n const embeddingUpdate: any = {};\n embeddingUpdate[this.embeddingDimension] = newEmbedding;\n\n await tx\n .update(longTermMemoryEmbeddings)\n .set(embeddingUpdate)\n .where(eq(longTermMemoryEmbeddings.memoryId, id));\n }\n });\n\n logger.info({ id }, 'Updated long-term memory');\n }\n\n /**\n * Delete memory (hard delete)\n */\n async delete(id: UUID): Promise<void> {\n const db = await this.getDb();\n await db.delete(longTermMemories).where(eq(longTermMemories.id, id));\n logger.info({ id }, 'Deleted long-term memory');\n }\n\n /**\n * Find memories by entity with optional filters\n */\n async findByEntity(\n entityId: UUID,\n type?: MemoryType,\n limit: number = 20,\n includeInactive: boolean = false\n ): Promise<LongTermMemory[]> {\n const db = await this.getDb();\n\n const conditions = [\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, entityId),\n ];\n\n if (!includeInactive) {\n conditions.push(eq(longTermMemories.isActive, true));\n }\n\n if (type) {\n conditions.push(eq(longTermMemories.type, type));\n }\n\n const results = await db\n .select()\n .from(longTermMemories)\n .where(and(...conditions))\n .orderBy(desc(longTermMemories.confidence), desc(longTermMemories.createdAt))\n .limit(limit);\n\n return results.map((row) => mapDbRowToLongTermMemory(row));\n }\n\n /**\n * Vector search for memories\n */\n async vectorSearch(\n params: LongTermMemorySearchParams,\n queryEmbedding: number[],\n similarityThreshold: number = 0.3\n ): Promise<LongTermMemoryRetrievalResult[]> {\n if (!this.embeddingDimension) {\n logger.warn('Embedding dimension not set, skipping vector search');\n return [];\n }\n\n const db = await this.getDb();\n\n try {\n // Calculate similarity\n const similarity = sql<number>`1 - (${cosineDistance(\n longTermMemoryEmbeddings[this.embeddingDimension],\n queryEmbedding\n )})`;\n\n const conditions = [\n eq(longTermMemories.agentId, this.runtime.agentId),\n eq(longTermMemories.entityId, params.entityId),\n sql`${longTermMemoryEmbeddings[this.embeddingDimension]} IS NOT NULL`,\n gte(similarity, similarityThreshold),\n ];\n\n if (params.minConfidence) {\n conditions.push(gte(longTermMemories.confidence, params.minConfidence));\n }\n\n if (!params.includeInactive) {\n conditions.push(eq(longTermMemories.isActive, true));\n }\n\n if (params.type) {\n conditions.push(eq(longTermMemories.type, params.type));\n }\n\n if (params.roomId) {\n conditions.push(\n or(eq(longTermMemories.roomId, params.roomId), isNull(longTermMemories.roomId))\n );\n }\n\n const results = await db\n .select({\n memory: longTermMemories,\n embedding: longTermMemoryEmbeddings[this.embeddingDimension],\n similarity,\n })\n .from(longTermMemories)\n .innerJoin(\n longTermMemoryEmbeddings,\n eq(longTermMemoryEmbeddings.memoryId, longTermMemories.id)\n )\n .where(and(...conditions))\n .orderBy(desc(similarity))\n .limit(params.limit || 20);\n\n return results.map((row) => ({\n ...mapDbRowToLongTermMemory(row.memory),\n embedding: row.embedding as number[],\n relevanceScore: row.similarity as number,\n activationScore: 0,\n finalScore: 0,\n }));\n } catch (error) {\n logger.error('Failed to execute vector search:', JSON.stringify(error));\n return [];\n }\n }\n\n /**\n * Fetch all active memories for BM25 indexing\n */\n async fetchAllActive(): Promise<Array<{ id: UUID; content: string; embeddingContext: string }>> {\n const db = await this.getDb();\n\n const memories = await db\n .select()\n .from(longTermMemories)\n .where(\n and(eq(longTermMemories.agentId, this.runtime.agentId), eq(longTermMemories.isActive, true))\n );\n\n return memories.map((row) => ({\n id: row.id,\n content: row.content,\n embeddingContext: row.embeddingContext,\n }));\n }\n\n /**\n * Update access metadata (lastAccessedAt and accessCount)\n */\n async updateAccessMetadata(memoryIds: UUID[]): Promise<void> {\n if (memoryIds.length === 0) return;\n\n const db = await this.getDb();\n const now = new Date();\n\n try {\n for (const id of memoryIds) {\n await db\n .update(longTermMemories)\n .set({\n lastAccessedAt: now,\n accessCount: sql`${longTermMemories.accessCount} + 1`,\n })\n .where(eq(longTermMemories.id, id));\n }\n\n logger.debug({ count: memoryIds.length }, 'Updated access metadata');\n } catch (error) {\n logger.error({ error }, 'Failed to update access metadata');\n }\n }\n}\n",
|
|
8
|
+
"import { sql } from 'drizzle-orm';\nimport {\n pgTable,\n text,\n integer,\n jsonb,\n real,\n index,\n varchar,\n timestamp,\n boolean,\n vector,\n foreignKey,\n} from 'drizzle-orm/pg-core';\nimport { VECTOR_DIMS } from '@elizaos/core';\n\n/**\n * Long-term Memory Storage Table\n *\n * Research: Section 4.1 \"The SOTA Memory Schema\"\n *\n * This table stores ALL persistent memories (episodic, semantic, procedural) with:\n * - Memory type taxonomy (3-tier cognitive hierarchy)\n * - Decay parameters for exponential forgetting\n * - Confidence and provenance tracking\n * - Contextual embeddings for superior retrieval\n * - Soft delete for contradiction handling\n *\n * Design Decision: Single unified table vs separate tables per type\n * Rationale: Easier to query across types, unified retrieval logic, flexible type reassignment\n */\nexport const longTermMemories = pgTable(\n 'long_term_memories',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n agentId: varchar('agent_id', { length: 36 }).notNull(),\n entityId: varchar('entity_id', { length: 36 }).notNull(),\n roomId: varchar('room_id', { length: 36 }),\n\n /**\n * Memory Type: EPISODIC, SEMANTIC, or PROCEDURAL\n * Research: Section 1.1 \"Cognitive Hierarchy\"\n */\n type: text('type').notNull(),\n\n /**\n * The actual memory content\n * Example: \"User prefers Python over JavaScript\"\n */\n content: text('content').notNull(),\n\n /**\n * Contextualized content for embedding\n * Research: Section 3.2.1 \"Contextual Embeddings\"\n * Example: \"[User programming preference]: User prefers Python over JavaScript\"\n */\n embeddingContext: text('embedding_context').notNull(),\n\n /**\n * Confidence score (0.0 - 1.0)\n * Research: Section 4.1 - Track extraction certainty\n */\n confidence: real('confidence').notNull().default(1.0),\n\n /**\n * Decay rate (lambda λ) for exponential decay\n * Research: Section 4.2 \"Mathematics of Forgetting\"\n * - ~0: Core facts (never decay)\n * - 0.01: Mid-term facts (weeks)\n * - 0.5+: Transient facts (days)\n */\n decayRate: real('decay_rate').notNull().default(0.01),\n\n /**\n * Decay function type: EXPONENTIAL, LINEAR, NONE\n */\n decayFunction: text('decay_function').notNull().default('EXPONENTIAL'),\n\n /**\n * Timestamp when memory was created\n */\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n\n /**\n * Last time this memory was retrieved/accessed\n * Research: Section 4.2.1 - Critical for recency scoring\n */\n lastAccessedAt: timestamp('last_accessed_at'),\n\n /**\n * Number of times this memory has been retrieved\n * Research: Section 4.2.2 - High count = stronger memory\n */\n accessCount: integer('access_count').default(0).notNull(),\n\n /**\n * Soft delete flag for contradiction handling\n * Research: Section 4.3 \"Handling Contradictions\"\n * When false, memory is superseded by a newer, contradictory fact\n */\n isActive: boolean('is_active').default(true).notNull(),\n\n /**\n * Provenance: source tracking (JSON)\n * Research: Section 4.1 \"Provenance/Lineage\"\n * Structure: {sessionId, messageId, textSnippet, authorId, extractionModel}\n */\n source: jsonb('source').notNull().default({}),\n\n /**\n * Flexible metadata (JSON)\n * Can store: tags, categories, user notes, etc.\n */\n metadata: jsonb('metadata').notNull().default({}),\n\n /**\n * ID of memory this one supersedes (for contradiction resolution)\n * Research: Section 4.3.2 \"Resolution Strategies\"\n */\n supersedesId: varchar('supersedes_id', { length: 36 }),\n },\n (table) => ({\n // Primary lookup: agent + entity + type\n agentEntityIdx: index('ltm_agent_entity_idx').on(table.agentId, table.entityId),\n\n // Type-based filtering\n typeIdx: index('ltm_type_idx').on(table.type),\n\n // Room context filtering\n roomIdx: index('ltm_room_idx').on(table.roomId),\n\n // Active memories query (exclude superseded)\n activeIdx: index('ltm_active_idx').on(table.isActive),\n\n // Confidence-based retrieval\n confidenceIdx: index('ltm_confidence_idx').on(table.confidence),\n\n // Temporal queries (recent memories)\n createdAtIdx: index('ltm_created_at_idx').on(table.createdAt),\n\n // Recency scoring (for decay calculation)\n lastAccessedIdx: index('ltm_last_accessed_idx').on(table.lastAccessedAt),\n\n // Compound index for common query pattern: active memories by entity, sorted by confidence\n agentEntityActiveConfidenceIdx: index('ltm_agent_entity_active_conf_idx').on(\n table.agentId,\n table.entityId,\n table.isActive,\n table.confidence\n ),\n })\n);\n\n/**\n * Long-term Memory Embeddings Table\n * Stores vector embeddings for semantic search with dynamic dimension support\n * Research: Section 3 \"RAG Strategy\"\n */\nexport const longTermMemoryEmbeddings = pgTable(\n 'long_term_memory_embeddings',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n memoryId: varchar('memory_id', { length: 36 })\n .notNull()\n .references(() => longTermMemories.id, { onDelete: 'cascade' }),\n dim384: vector('dim_384', { dimensions: VECTOR_DIMS.SMALL }),\n dim512: vector('dim_512', { dimensions: VECTOR_DIMS.MEDIUM }),\n dim768: vector('dim_768', { dimensions: VECTOR_DIMS.LARGE }),\n dim1024: vector('dim_1024', { dimensions: VECTOR_DIMS.XL }),\n dim1536: vector('dim_1536', { dimensions: VECTOR_DIMS.XXL }),\n dim3072: vector('dim_3072', { dimensions: VECTOR_DIMS.XXXL }),\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n },\n (table) => [\n index('idx_ltm_embedding_memory_id').on(table.memoryId),\n foreignKey({\n name: 'fk_ltm_embedding_memory',\n columns: [table.memoryId],\n foreignColumns: [longTermMemories.id],\n }).onDelete('cascade'),\n ]\n);\n",
|
|
9
|
+
"import { sql } from 'drizzle-orm';\nimport {\n pgTable,\n text,\n integer,\n jsonb,\n index,\n varchar,\n timestamp,\n vector,\n foreignKey,\n} from 'drizzle-orm/pg-core';\nimport { VECTOR_DIMS } from '@elizaos/core';\n\n/**\n * Conversation Summaries Table - Hierarchical Summarization\n *\n * Research: Section 5.1.2 \"Hierarchical Episodic Summarization\"\n *\n * This table implements recursive, multi-level summarization for long conversations:\n * - Level 0: Raw messages (stored elsewhere)\n * - Level 1: Summary of 50-100 messages\n * - Level 2: Summary of 5-10 Level 1 summaries\n * - Level 3+: Recursive summarization for very long sessions\n *\n * Benefits:\n * - Dramatic token reduction (10x compression)\n * - Better context management for 100+ message sessions\n * - Preserves conversational narrative without exploding context window\n *\n * Design Philosophy:\n * - Summaries reference other summaries (parentSummaryId for tree structure)\n * - Each summary has a level (depth in the hierarchy)\n * - Token count tracked for precise budget management\n * - Time ranges tracked for temporal queries\n *\n * Note: \"Conversation Summaries\" provide narrative context, distinct from \"Facts\" which are discrete knowledge units.\n */\nexport const conversationSummaries = pgTable(\n 'conversation_summaries',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n agentId: varchar('agent_id', { length: 36 }).notNull(),\n entityId: varchar('entity_id', { length: 36 }).notNull(),\n roomId: varchar('room_id', { length: 36 }).notNull(),\n\n /**\n * Hierarchical level\n * - Level 1: Direct summarization of messages\n * - Level 2+: Summarization of lower-level summaries\n *\n * Research: Section 5.1.2 \"Recursive Summarization\"\n */\n level: integer('level').notNull().default(1),\n\n /**\n * Parent summary ID (for hierarchical structure)\n * - null for Level 1 summaries (direct from messages)\n * - UUID of lower-level summary for Level 2+\n */\n parentSummaryId: varchar('parent_summary_id', { length: 36 }),\n\n /**\n * The summary content\n * Example: \"User discussed their cat's dietary restrictions and asked for lasagna recipes.\n * Agent provided three options.\"\n */\n content: text('content').notNull(),\n\n /**\n * Estimated token count of the summary\n * Research: Section 5.1.3 \"Token Budget Enforcement\"\n */\n tokenCount: integer('token_count').notNull(),\n\n /**\n * Time range this summary covers\n * Research: Section 1.1.2 \"Episodic Memory - Temporal Anchoring\"\n */\n startTime: timestamp('start_time').notNull(),\n endTime: timestamp('end_time').notNull(),\n\n /**\n * Number of source items this summary covers\n * - For Level 1: number of messages\n * - For Level 2+: number of lower-level summaries\n */\n sourceCount: integer('source_count').notNull(),\n\n /**\n * IDs of source items (messages or summaries) this summarizes\n * Stored as JSON array for provenance tracking\n */\n sourceIds: jsonb('source_ids').notNull().default([]),\n\n /**\n * When this summary was created\n */\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n\n /**\n * Last time this summary was accessed/retrieved\n * Used for recency scoring and decay\n */\n lastAccessedAt: timestamp('last_accessed_at'),\n\n /**\n * How many times this summary has been retrieved\n */\n accessCount: integer('access_count').default(0).notNull(),\n\n /**\n * Metadata (e.g., key topics, sentiment, participant count)\n */\n metadata: jsonb('metadata').notNull().default({}),\n },\n (table) => ({\n // Primary lookup: agent + entity + room\n agentEntityRoomIdx: index('cs_agent_entity_room_idx').on(\n table.agentId,\n table.entityId,\n table.roomId\n ),\n\n // Level-based queries (fetch summaries at specific level)\n levelIdx: index('cs_level_idx').on(table.level),\n\n // Parent relationship queries (traverse hierarchy)\n parentIdx: index('cs_parent_idx').on(table.parentSummaryId),\n\n // Temporal queries (find summaries for time range)\n timeRangeIdx: index('cs_time_range_idx').on(table.startTime, table.endTime),\n\n // Recency queries (most recent summaries)\n createdAtIdx: index('cs_created_at_idx').on(table.createdAt),\n\n // Access pattern tracking\n lastAccessedIdx: index('cs_last_accessed_idx').on(table.lastAccessedAt),\n\n // Compound index for common query: recent summaries by entity/room at specific level\n entityRoomLevelTimeIdx: index('cs_entity_room_level_time_idx').on(\n table.entityId,\n table.roomId,\n table.level,\n table.createdAt\n ),\n })\n);\n\n/**\n * Conversation Summary Embeddings Table\n * Stores vector embeddings for semantic search of summaries with dynamic dimension support\n * Research: Section 5.1.2 \"Hierarchical Episodic Summarization\" + Section 3 \"RAG Strategy\"\n */\nexport const conversationSummaryEmbeddings = pgTable(\n 'conversation_summary_embeddings',\n {\n id: varchar('id', { length: 36 }).primaryKey(),\n summaryId: varchar('summary_id', { length: 36 })\n .notNull()\n .references(() => conversationSummaries.id, { onDelete: 'cascade' }),\n dim384: vector('dim_384', { dimensions: VECTOR_DIMS.SMALL }),\n dim512: vector('dim_512', { dimensions: VECTOR_DIMS.MEDIUM }),\n dim768: vector('dim_768', { dimensions: VECTOR_DIMS.LARGE }),\n dim1024: vector('dim_1024', { dimensions: VECTOR_DIMS.XL }),\n dim1536: vector('dim_1536', { dimensions: VECTOR_DIMS.XXL }),\n dim3072: vector('dim_3072', { dimensions: VECTOR_DIMS.XXXL }),\n createdAt: timestamp('created_at')\n .default(sql`now()`)\n .notNull(),\n },\n (table) => [\n index('idx_cs_embedding_summary_id').on(table.summaryId),\n foreignKey({\n name: 'fk_cs_embedding_summary',\n columns: [table.summaryId],\n foreignColumns: [conversationSummaries.id],\n }).onDelete('cascade'),\n ]\n);\n",
|
|
10
|
+
"import type { UUID } from '@elizaos/core';\nimport {\n type LongTermMemory,\n type ConversationSummary,\n MemoryType,\n DecayFunction,\n} from '../types/index';\n\n/**\n * Database Row Mapping Utilities\n *\n * Maps raw database rows to strongly-typed domain objects\n */\n\n/**\n * Map database row to LongTermMemory object\n *\n * @param row - Raw database row\n * @returns Typed LongTermMemory object\n */\nexport function mapDbRowToLongTermMemory(row: any): LongTermMemory {\n return {\n id: row.id as UUID,\n agentId: row.agentId as UUID,\n entityId: row.entityId as UUID,\n roomId: row.roomId as UUID | undefined,\n type: row.type as MemoryType,\n content: row.content,\n embeddingContext: row.embeddingContext,\n embedding: row.embedding as number[],\n confidence: row.confidence as number,\n decayRate: row.decayRate as number,\n decayFunction: row.decayFunction as DecayFunction,\n createdAt: row.createdAt,\n lastAccessedAt: row.lastAccessedAt,\n accessCount: row.accessCount as number,\n isActive: row.isActive as boolean,\n source: row.source as LongTermMemory['source'],\n metadata: row.metadata as Record<string, unknown>,\n supersedesId: row.supersedesId as UUID | undefined,\n };\n}\n\n/**\n * Map database row to ConversationSummary object\n *\n * @param row - Raw database row\n * @returns Typed ConversationSummary object\n */\nexport function mapDbRowToConversationSummary(row: any): ConversationSummary {\n return {\n id: row.id as UUID,\n agentId: row.agentId as UUID,\n entityId: row.entityId as UUID,\n roomId: row.roomId as UUID,\n level: row.level as number,\n parentSummaryId: row.parentSummaryId as UUID | undefined,\n content: row.content,\n embedding: row.embedding as number[] | undefined,\n tokenCount: row.tokenCount as number,\n startTime: row.startTime,\n endTime: row.endTime,\n sourceCount: row.sourceCount as number,\n sourceIds: row.sourceIds as UUID[],\n createdAt: row.createdAt,\n lastAccessedAt: row.lastAccessedAt,\n accessCount: row.accessCount as number,\n metadata: (row.metadata as Record<string, unknown>) || {},\n };\n}\n",
|
|
11
|
+
"import type { IAgentRuntime, UUID } from '@elizaos/core';\nimport { logger } from '@elizaos/core';\nimport { eq, and, desc, sql, cosineDistance } from 'drizzle-orm';\nimport { conversationSummaries, conversationSummaryEmbeddings } from '../schemas/index';\nimport { type ConversationSummary, type EmbeddingDimensionColumn } from '../types/index';\nimport { mapDbRowToConversationSummary } from '../utils/db-mapping';\n\n/**\n * Conversation Summary Repository\n *\n * Research: Section 5.1.2 \"Hierarchical Conversation Summarization\"\n * Handles database operations for conversation summaries\n */\nexport class ConversationSummaryRepository {\n constructor(\n private runtime: IAgentRuntime,\n private embeddingDimension?: EmbeddingDimensionColumn\n ) {}\n\n /**\n * Get database instance with health check\n */\n private async getDb(): Promise<any> {\n const adapter = (this.runtime as any).adapter || this.runtime;\n const db = adapter.db;\n\n if (!db) {\n throw new Error('Database not available');\n }\n\n try {\n const isReady = await adapter.isReady();\n if (!isReady) {\n logger.warn('[ConversationSummaryRepository] Database not ready, attempting reconnect...');\n await new Promise((resolve) => setTimeout(resolve, 1000));\n const stillNotReady = await adapter.isReady();\n if (stillNotReady === false) {\n throw new Error('Database connection lost and could not reconnect');\n }\n }\n } catch (error) {\n logger.error('[ConversationSummaryRepository] Database health check failed:', error);\n throw new Error('Database connection health check failed');\n }\n\n return db;\n }\n\n /**\n * Insert a new summary\n */\n async insert(\n summary: Omit<ConversationSummary, 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount'>,\n embedding?: number[]\n ): Promise<ConversationSummary> {\n const db = await this.getDb();\n const id = crypto.randomUUID() as UUID;\n const now = new Date();\n\n const newSummary: ConversationSummary = {\n id,\n createdAt: now,\n lastAccessedAt: null,\n accessCount: 0,\n embedding: embedding || [],\n ...summary,\n };\n\n await db.transaction(async (tx: any) => {\n // Insert summary\n await tx.insert(conversationSummaries).values({\n id: newSummary.id,\n agentId: newSummary.agentId,\n entityId: newSummary.entityId,\n roomId: newSummary.roomId,\n level: newSummary.level,\n parentSummaryId: newSummary.parentSummaryId || null,\n content: newSummary.content,\n tokenCount: newSummary.tokenCount,\n startTime: newSummary.startTime,\n endTime: newSummary.endTime,\n sourceCount: newSummary.sourceCount,\n sourceIds: newSummary.sourceIds,\n createdAt: now,\n lastAccessedAt: null,\n accessCount: 0,\n metadata: newSummary.metadata,\n });\n\n // Insert embedding if available\n if (embedding && this.embeddingDimension) {\n const embeddingValues: any = {\n id: crypto.randomUUID(),\n summaryId: id,\n createdAt: now,\n };\n embeddingValues[this.embeddingDimension] = embedding;\n await tx.insert(conversationSummaryEmbeddings).values(embeddingValues);\n }\n });\n\n logger.info(\n {\n id: newSummary.id,\n level: newSummary.level,\n tokenCount: newSummary.tokenCount,\n sourceCount: newSummary.sourceCount,\n },\n 'Stored conversation summary'\n );\n\n return newSummary;\n }\n\n /**\n * Find summaries by level\n */\n async findByLevel(roomId: UUID, level: number): Promise<ConversationSummary[]> {\n const db = await this.getDb();\n\n const results = await db\n .select()\n .from(conversationSummaries)\n .where(\n and(\n eq(conversationSummaries.agentId, this.runtime.agentId),\n eq(conversationSummaries.roomId, roomId),\n eq(conversationSummaries.level, level)\n )\n )\n .orderBy(desc(conversationSummaries.createdAt));\n\n return results.map((r: any) => mapDbRowToConversationSummary(r));\n }\n\n /**\n * Vector search for summaries\n */\n async vectorSearch(\n entityId: UUID,\n roomId: UUID,\n queryEmbedding: number[],\n limit: number = 5\n ): Promise<ConversationSummary[]> {\n if (!this.embeddingDimension) {\n logger.warn('Embedding dimension not set, skipping summary search');\n return [];\n }\n\n const db = await this.getDb();\n\n try {\n // Calculate similarity\n const similarity = sql<number>`1 - (${cosineDistance(\n conversationSummaryEmbeddings[this.embeddingDimension],\n queryEmbedding\n )})`;\n\n const results = await db\n .select({\n summary: conversationSummaries,\n embedding: conversationSummaryEmbeddings[this.embeddingDimension],\n similarity,\n })\n .from(conversationSummaries)\n .innerJoin(\n conversationSummaryEmbeddings,\n eq(conversationSummaryEmbeddings.summaryId, conversationSummaries.id)\n )\n .where(\n and(\n eq(conversationSummaries.agentId, this.runtime.agentId),\n eq(conversationSummaries.entityId, entityId),\n eq(conversationSummaries.roomId, roomId),\n sql`${conversationSummaryEmbeddings[this.embeddingDimension]} IS NOT NULL`\n )\n )\n .orderBy(desc(similarity))\n .limit(limit * 2); // Get extra for token budget trimming\n\n return results.map((r: any) => ({\n ...mapDbRowToConversationSummary(r.summary),\n embedding: r.embedding as number[],\n }));\n } catch (error) {\n logger.error('Failed to search summaries:', JSON.stringify(error));\n return [];\n }\n }\n\n /**\n * Update access metadata for summaries\n */\n async updateAccessMetadata(summaryIds: UUID[]): Promise<void> {\n if (summaryIds.length === 0) return;\n\n const db = await this.getDb();\n const now = new Date();\n\n try {\n for (const id of summaryIds) {\n await db\n .update(conversationSummaries)\n .set({\n lastAccessedAt: now,\n accessCount: sql`${conversationSummaries.accessCount} + 1`,\n })\n .where(eq(conversationSummaries.id, id));\n }\n\n logger.debug({ count: summaryIds.length }, 'Updated summary access metadata');\n } catch (error) {\n logger.error({ error }, 'Failed to update summary access metadata');\n }\n }\n}\n",
|
|
12
|
+
"import { type IAgentRuntime, ModelType, logger } from '@elizaos/core';\n\n/**\n * Embedding Generation Utility\n *\n * Research: Section 3.2.1 \"Contextual Embeddings\"\n */\n\n/**\n * Generate embedding for text using the runtime's embedding model\n *\n * @param runtime - Agent runtime instance\n * @param text - Text to generate embedding for\n * @returns Embedding vector\n */\nexport async function generateEmbedding(runtime: IAgentRuntime, text: string): Promise<number[]> {\n try {\n const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, text);\n return embedding;\n } catch (error) {\n logger.error({ error }, 'Failed to generate embedding');\n // Return zero vector as fallback\n return new Array(1536).fill(0);\n }\n}\n\n/**\n * Clean and normalize an embedding vector\n *\n * @param embedding - Raw embedding vector\n * @returns Cleaned vector with finite numbers and fixed precision\n */\nexport function cleanEmbedding(embedding: number[]): number[] {\n return embedding.map((n) => (Number.isFinite(n) ? Number(n.toFixed(6)) : 0));\n}\n",
|
|
13
|
+
"import { DecayFunction, type LongTermMemoryRetrievalResult } from '../types/index';\n\n/**\n * Decay Scoring Utilities\n *\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n *\n * Implements exponential and linear decay functions to model natural\n * forgetting curves inspired by cognitive science research (Ebbinghaus forgetting curve)\n */\n\n/**\n * Calculate decay factor based on decay function type\n *\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n * Formula: Score = Relevance * Confidence * exp(-λ * (t_now - t_last))\n *\n * @param decayFunction - Type of decay function (EXPONENTIAL, LINEAR, NONE)\n * @param decayRate - Decay rate (lambda λ)\n * @param timeDeltaDays - Time since last access in days\n * @returns Decay factor (0.0 to 1.0)\n */\nexport function calculateDecayFactor(\n decayFunction: DecayFunction,\n decayRate: number,\n timeDeltaDays: number\n): number {\n switch (decayFunction) {\n case DecayFunction.EXPONENTIAL:\n // Exponential decay: e^(-λ * t)\n return Math.exp(-decayRate * timeDeltaDays);\n\n case DecayFunction.LINEAR:\n // Linear decay: max(0, 1 - λ * t)\n return Math.max(0, 1 - decayRate * timeDeltaDays);\n\n case DecayFunction.NONE:\n // No decay\n return 1.0;\n\n default:\n return 1.0;\n }\n}\n\n/**\n * Calculate access boost factor from access count\n *\n * Research: Section 4.2.2 \"Reinforcement\"\n * More accesses = stronger memory\n *\n * @param accessCount - Number of times memory has been accessed\n * @returns Boost factor (>= 1.0)\n */\nexport function calculateAccessBoost(accessCount: number): number {\n // Logarithmic boost: 1 + log(1 + count) * 0.1\n return 1 + Math.log(1 + accessCount) * 0.1;\n}\n\n/**\n * Apply decay scoring to a set of memories\n *\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n * Calculates activation score and final score for each memory\n *\n * @param memories - Array of memory retrieval results\n * @returns Array with decay scores applied\n */\nexport function applyDecayScoring(\n memories: LongTermMemoryRetrievalResult[]\n): LongTermMemoryRetrievalResult[] {\n const now = Date.now();\n\n return memories.map((memory) => {\n // Calculate time delta in days\n const lastAccessed = memory.lastAccessedAt?.getTime() || memory.createdAt.getTime();\n const timeDeltaDays = (now - lastAccessed) / (1000 * 60 * 60 * 24);\n\n // Calculate decay factor\n const decayFactor = calculateDecayFactor(memory.decayFunction, memory.decayRate, timeDeltaDays);\n\n // Calculate access boost\n const accessBoost = calculateAccessBoost(memory.accessCount);\n\n // Calculate scores\n const activationScore = memory.confidence * decayFactor * accessBoost;\n const finalScore = memory.relevanceScore * activationScore;\n\n return {\n ...memory,\n activationScore,\n finalScore,\n };\n });\n}\n",
|
|
14
|
+
"import type { LongTermMemoryRetrievalResult } from '../types/index';\n\n/**\n * Search Result Merging Utilities\n *\n * Research: Section 3.2.1 \"Contextual Retrieval\"\n * Combines multiple ranking methods (Vector + BM25) for superior retrieval\n */\n\n/**\n * Merge vector and BM25 search results\n *\n * Research: Section 3.2.1 \"Contextual Retrieval\"\n * When a memory appears in both result sets, average their scores\n *\n * @param vectorResults - Results from vector search\n * @param bm25Results - Results from BM25 search\n * @returns Merged results with combined scores\n */\nexport function mergeSearchResults(\n vectorResults: LongTermMemoryRetrievalResult[],\n bm25Results: LongTermMemoryRetrievalResult[]\n): LongTermMemoryRetrievalResult[] {\n const merged = new Map<string, LongTermMemoryRetrievalResult>();\n\n // Add vector results\n for (const result of vectorResults) {\n merged.set(result.id, result);\n }\n\n // Merge BM25 results (average scores if duplicate)\n for (const result of bm25Results) {\n if (merged.has(result.id)) {\n const existing = merged.get(result.id)!;\n // Average the relevance scores\n existing.relevanceScore = (existing.relevanceScore + result.relevanceScore) / 2;\n } else {\n merged.set(result.id, result);\n }\n }\n\n return Array.from(merged.values());\n}\n",
|
|
15
|
+
"import type { UUID } from '@elizaos/core';\nimport { MemoryType, type LongTermMemoryRetrievalResult } from '../types/index';\n\n/**\n * Memory Formatting Utilities\n *\n * Research: Section 5.1.3 \"Tier 3: Just-In-Time Injection\"\n * Formats memories for LLM context in a human-readable format\n */\n\n/**\n * Format memories for context injection\n *\n * Research: Section 5.1.3 \"Tier 3: Just-In-Time Injection\"\n * Groups by type and formats in a human-readable markdown format\n *\n * @param memories - Array of memories to format\n * @returns Formatted string for LLM context\n */\nexport function formatMemoriesForContext(memories: LongTermMemoryRetrievalResult[]): string {\n if (memories.length === 0) {\n return '';\n }\n\n // Group by type\n const grouped = new Map<MemoryType, LongTermMemoryRetrievalResult[]>();\n\n for (const memory of memories) {\n if (!grouped.has(memory.type)) {\n grouped.set(memory.type, []);\n }\n grouped.get(memory.type)!.push(memory);\n }\n\n // Format each type\n const sections: string[] = [];\n\n if (grouped.has(MemoryType.SEMANTIC)) {\n const facts = grouped.get(MemoryType.SEMANTIC)!;\n const items = facts\n .map((m) => `- ${m.content} (confidence: ${m.confidence.toFixed(2)})`)\n .join('\\n');\n sections.push(`**Semantic Knowledge (Facts)**:\\n${items}`);\n }\n\n if (grouped.has(MemoryType.EPISODIC)) {\n const episodes = grouped.get(MemoryType.EPISODIC)!;\n const items = episodes\n .map((m) => `- ${m.content} (${m.createdAt.toLocaleDateString()})`)\n .join('\\n');\n sections.push(`**Episodic Memory (Events)**:\\n${items}`);\n }\n\n if (grouped.has(MemoryType.PROCEDURAL)) {\n const skills = grouped.get(MemoryType.PROCEDURAL)!;\n const items = skills.map((m) => `- ${m.content}`).join('\\n');\n sections.push(`**Procedural Knowledge (Skills)**:\\n${items}`);\n }\n\n return sections.join('\\n\\n');\n}\n",
|
|
16
|
+
"/**\n * Token Counter Utility\n *\n * Research: Section 5.1.3 \"Token Budget Enforcement\"\n *\n * This utility provides token counting for memory content to enforce\n * token budgets during retrieval. Uses a simplified estimation based on\n * GPT tokenization rules (1 token ≈ 4 characters for English text).\n *\n * For more precise counting, this can be replaced with a full tokenizer\n * library (e.g., tiktoken), but the estimation is sufficient for budget\n * enforcement in most cases.\n */\n\n/**\n * Estimate token count for a given text\n *\n * This is a simplified heuristic that works well for most content:\n * - 1 token ≈ 4 characters for English text\n * - Punctuation and whitespace are included\n * - Non-English text may have different ratios\n *\n * @param text - The text to count tokens for\n * @returns Estimated token count\n */\nexport function estimateTokenCount(text: string): number {\n if (!text || text.length === 0) {\n return 0;\n }\n\n // Simple heuristic: 1 token per ~4 characters\n // This is conservative and works well for most cases\n const charCount = text.length;\n const estimatedTokens = Math.ceil(charCount / 4);\n\n return estimatedTokens;\n}\n\n/**\n * Calculate token count for multiple text segments\n *\n * @param texts - Array of text strings\n * @returns Total estimated token count\n */\nexport function estimateTokenCountForArray(texts: string[]): number {\n return texts.reduce((total, text) => total + estimateTokenCount(text), 0);\n}\n\n/**\n * Trim an array of items to fit within a token budget\n *\n * This function takes an array of items with text content and trims it\n * to fit within the specified token budget. Items are assumed to be\n * already sorted by priority/score (highest first).\n *\n * @param items - Array of items (with getText function)\n * @param budget - Maximum token budget\n * @param getText - Function to extract text from an item\n * @param includeOverhead - Additional tokens per item (formatting overhead)\n * @returns Trimmed array of items that fit within budget\n */\nexport function trimToTokenBudget<T>(\n items: T[],\n budget: number,\n getText: (item: T) => string,\n includeOverhead: number = 10 // Default: 10 tokens for formatting per item\n): T[] {\n const result: T[] = [];\n let currentTokens = 0;\n\n for (const item of items) {\n const itemText = getText(item);\n const itemTokens = estimateTokenCount(itemText) + includeOverhead;\n\n // Check if adding this item would exceed budget\n if (currentTokens + itemTokens > budget) {\n // Budget exceeded, stop here\n break;\n }\n\n result.push(item);\n currentTokens += itemTokens;\n }\n\n return result;\n}\n\n/**\n * Format token count for human-readable display\n *\n * @param count - Token count\n * @returns Formatted string (e.g., \"1.2K tokens\")\n */\nexport function formatTokenCount(count: number): string {\n if (count < 1000) {\n return `${count} tokens`;\n } else if (count < 1000000) {\n return `${(count / 1000).toFixed(1)}K tokens`;\n } else {\n return `${(count / 1000000).toFixed(1)}M tokens`;\n }\n}\n",
|
|
17
|
+
"import {\n type Evaluator,\n type IAgentRuntime,\n type Memory,\n logger,\n ModelType,\n type UUID,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\nimport { CONSOLIDATION_SYSTEM_PROMPT, buildExtractionPrompt } from '../prompts/consolidation';\nimport type { ConsolidationResult, ExtractedLongTermMemory } from '../types/index';\nimport { MemoryType as MemoryTypeEnum, DecayFunction as DecayFunctionEnum } from '../types/index';\n\n/**\n * Consolidation buffer to track messages per room\n * This is evaluator-level state, separate from service state\n */\nconst consolidationBuffers = new Map<UUID, Memory[]>();\n\n/**\n * Memory Consolidation Evaluator\n *\n * Research: Section 2.3 \"Consolidation Pipeline\"\n *\n * This evaluator implements the full consolidation flow:\n * 1. Buffers conversation messages\n * 2. Validates when threshold is reached\n * 3. Extracts persistent facts using LLM\n * 4. Stores memories via service\n *\n * Architecture Design:\n * - Evaluator owns the consolidation logic and prompts\n * - Service handles storage/retrieval only\n * - System prompt is temporarily swapped during consolidation\n * - Non-blocking: Doesn't wait for consolidation to complete\n */\nexport const consolidationEvaluator: Evaluator = {\n name: 'CONSOLIDATION',\n similes: ['MEMORY_CONSOLIDATION', 'EXTRACT_FACTS', 'MEMORY_BUFFER'],\n\n description:\n 'Buffers conversation messages and performs periodic consolidation to extract persistent facts ' +\n 'using LLM analysis. Distinguishes transient intents from long-term knowledge.',\n\n /**\n * Validation: Check if we should trigger consolidation\n *\n * Research: Section 2.3 \"Threshold Trigger\"\n * Returns true when buffer reaches consolidation threshold\n */\n validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => {\n // First, buffer the message\n if (!consolidationBuffers.has(message.roomId)) {\n consolidationBuffers.set(message.roomId, []);\n }\n consolidationBuffers.get(message.roomId)!.push(message);\n\n // Get memory service for configuration\n const memoryService = runtime.getService<MemoryService>('memory');\n if (!memoryService) {\n return false;\n }\n\n const config = memoryService.getConfig();\n const bufferSize = consolidationBuffers.get(message.roomId)!.length;\n\n // Trigger consolidation if threshold reached\n const shouldConsolidate = bufferSize >= config.consolidationThreshold;\n\n if (shouldConsolidate) {\n logger.info(\n {\n roomId: message.roomId,\n bufferSize,\n threshold: config.consolidationThreshold,\n },\n 'Consolidation threshold reached'\n );\n }\n\n return shouldConsolidate;\n },\n\n /**\n * Handler: Execute consolidation pipeline\n *\n * Research: Section 2 \"Architecture for Extraction & Taxonomy\"\n *\n * Flow:\n * 1. Get buffered messages\n * 2. Format conversation log\n * 3. Swap system prompt temporarily\n * 4. Call LLM with extraction prompt\n * 5. Restore original system prompt\n * 6. Parse and filter results\n * 7. Store extracted memories via service\n * 8. Clear buffer\n */\n handler: async (runtime: IAgentRuntime, message: Memory): Promise<void> => {\n const roomId = message.roomId;\n\n try {\n // Get memory service\n const memoryService = runtime.getService<MemoryService>('memory');\n if (!memoryService) {\n logger.warn('Memory service not available for consolidation');\n return;\n }\n\n // Get buffer\n const buffer = consolidationBuffers.get(roomId) || [];\n if (buffer.length === 0) {\n return;\n }\n\n logger.info({ roomId, messageCount: buffer.length }, 'Starting memory consolidation');\n\n // Format conversation log\n const conversationLog = buffer\n .map((m, idx) => {\n const content =\n typeof m.content === 'string' ? m.content : m.content.text || JSON.stringify(m.content);\n return `[${idx + 1}] ${m.entityId}: ${content}`;\n })\n .join('\\n');\n\n // Build extraction prompt\n const extractionPrompt = buildExtractionPrompt(conversationLog);\n\n // Save original system prompt\n const originalSystemPrompt = runtime.character.system;\n\n try {\n // Temporarily replace system prompt\n runtime.character.system = CONSOLIDATION_SYSTEM_PROMPT;\n\n // Call LLM for extraction\n logger.debug('Calling LLM for memory extraction');\n const response = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt: extractionPrompt,\n temperature: 0.3, // Low temperature for consistent extraction\n });\n\n // Parse response\n const consolidationResult = parseConsolidationResult(response);\n\n logger.debug(\n {\n reasoning: consolidationResult.reasoningTrace,\n extracted: consolidationResult.extractedMemories.length,\n },\n 'Extraction complete'\n );\n\n // Filter by confidence\n const config = memoryService.getConfig();\n const validMemories = consolidationResult.extractedMemories.filter(\n (m) => m.confidence >= config.minConfidence\n );\n\n logger.info(\n {\n total: consolidationResult.extractedMemories.length,\n valid: validMemories.length,\n minConfidence: config.minConfidence,\n },\n 'Filtered extracted memories'\n );\n\n // Store each valid memory\n for (const extracted of validMemories) {\n await storeExtractedMemory(runtime, memoryService, roomId, buffer, extracted);\n }\n\n // Clear buffer after successful consolidation\n consolidationBuffers.set(roomId, []);\n\n logger.info({ roomId, stored: validMemories.length }, 'Memory consolidation complete');\n } finally {\n // ALWAYS restore original system prompt\n runtime.character.system = originalSystemPrompt;\n }\n } catch (error) {\n logger.error({ error, roomId }, 'Consolidation evaluator failed');\n // Don't throw - this should not break the conversation flow\n // Don't clear buffer on failure - will retry later\n }\n },\n\n /**\n * Examples: Not used for this evaluator\n */\n examples: [],\n};\n\n/**\n * Parse LLM response into ConsolidationResult\n *\n * Parses pipe-delimited format:\n * [ANALYSIS]\n * ... reasoning text ...\n * [MEMORIES]\n * MEM|TYPE|CATEGORY|CONFIDENCE|IS_CONTRADICTION|CONTENT\n */\nfunction parseConsolidationResult(response: any): ConsolidationResult {\n try {\n // useModel returns string directly for TEXT_LARGE\n const responseText = typeof response === 'string' ? response : JSON.stringify(response);\n\n // Extract [ANALYSIS] section\n const analysisMatch = responseText.match(/\\[ANALYSIS\\](.*?)(?:\\[MEMORIES\\]|$)/s);\n const reasoningTrace = analysisMatch ? analysisMatch[1].trim() : '';\n\n // Extract [MEMORIES] section\n const memoriesMatch = responseText.match(/\\[MEMORIES\\](.*?)$/s);\n const memoriesText = memoriesMatch ? memoriesMatch[1].trim() : '';\n\n // Parse individual memory lines\n const extractedMemories: ExtractedLongTermMemory[] = [];\n\n if (memoriesText) {\n const lines = memoriesText.split('\\n');\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n\n // Skip empty lines or lines that don't start with MEM|\n if (!trimmedLine || !trimmedLine.startsWith('MEM|')) {\n continue;\n }\n\n // Parse pipe-delimited format: MEM|TYPE|CATEGORY|CONFIDENCE|IS_CONTRADICTION|CONTENT\n const parts = trimmedLine.split('|');\n\n if (parts.length < 6) {\n logger.warn(\n { line: trimmedLine },\n 'Skipping malformed memory line (insufficient fields)'\n );\n continue;\n }\n\n // Extract fields (skip the \"MEM\" prefix)\n const type = parts[1].trim() as MemoryTypeEnum;\n const category = parts[2].trim();\n const confidenceStr = parts[3].trim();\n const isContradictionStr = parts[4].trim();\n // Content is everything after the 5th pipe (may contain pipes itself)\n const content = parts.slice(5).join('|').trim();\n\n // Validate type\n if (!['EPISODIC', 'SEMANTIC', 'PROCEDURAL'].includes(type)) {\n logger.warn({ type, line: trimmedLine }, 'Invalid memory type');\n continue;\n }\n\n // Validate category\n if (!category) {\n logger.warn({ line: trimmedLine }, 'Missing category');\n continue;\n }\n\n // Parse confidence\n const confidence = parseFloat(confidenceStr);\n if (isNaN(confidence) || confidence < 0 || confidence > 1) {\n logger.warn({ confidenceStr, line: trimmedLine }, 'Invalid confidence value');\n continue;\n }\n\n // Parse isContradiction\n const isContradiction = isContradictionStr.toLowerCase() === 'true';\n\n // Validate content\n if (!content) {\n logger.warn({ line: trimmedLine }, 'Missing content');\n continue;\n }\n\n // Build metadata from category\n const metadata: Record<string, unknown> = {\n category,\n };\n\n extractedMemories.push({\n type,\n content,\n confidence,\n isContradiction,\n metadata,\n });\n }\n }\n\n return {\n reasoningTrace,\n transientSummary: '', // Not used in pipe format\n extractedMemories,\n };\n } catch (error) {\n logger.error({ error }, 'Failed to parse consolidation response');\n return {\n reasoningTrace: 'Parse error',\n transientSummary: '',\n extractedMemories: [],\n };\n }\n}\n\n/**\n * Store an extracted memory via the service\n *\n * Research: Section 3.2.1 \"Contextual Embeddings\"\n * Enriches content with context before storage\n */\nasync function storeExtractedMemory(\n runtime: IAgentRuntime,\n memoryService: MemoryService,\n roomId: UUID,\n buffer: Memory[],\n extracted: ExtractedLongTermMemory\n): Promise<void> {\n // Get entity ID from the first message in buffer (assuming user is the entity)\n const entityId = (buffer[0]?.entityId || runtime.agentId) as UUID;\n\n // Generate contextual embedding string\n const embeddingContext = generateContextualString(extracted);\n\n // Get decay rate based on type\n const config = memoryService.getConfig();\n const decayRate = config.defaultDecayRates[extracted.type];\n\n // Prepare memory for storage\n const memoryData = {\n agentId: runtime.agentId,\n entityId,\n roomId,\n type: extracted.type,\n content: extracted.content,\n embeddingContext,\n confidence: extracted.confidence,\n decayRate,\n decayFunction: DecayFunctionEnum.EXPONENTIAL,\n source: {\n sessionId: roomId,\n messageId: extracted.sourceMessageId,\n textSnippet: extracted.content.substring(0, 200),\n },\n metadata: extracted.metadata || {},\n };\n\n // Handle contradiction if flagged\n if (config.enableContradictionDetection && extracted.isContradiction) {\n await memoryService.handleContradiction(entityId, memoryData);\n } else {\n await memoryService.storeLongTermMemory(memoryData);\n }\n}\n\n/**\n * Generate contextual string for embedding\n *\n * Research: Section 3.2.1 \"The Solution: Contextual Embeddings\"\n * Example: \"[User preference regarding programming]: I prefer Python over JavaScript\"\n */\nfunction generateContextualString(extracted: ExtractedLongTermMemory): string {\n const typeLabel = {\n [MemoryTypeEnum.EPISODIC]: 'Event',\n [MemoryTypeEnum.SEMANTIC]: 'Fact',\n [MemoryTypeEnum.PROCEDURAL]: 'Skill',\n }[extracted.type];\n\n // Try to infer category from metadata or content\n const category = extracted.metadata?.category || 'general';\n\n return `[${typeLabel} about ${category}]: ${extracted.content}`;\n}\n",
|
|
18
|
+
"/**\n * Memory Consolidation Prompts\n *\n * Research: Section 2.2.2 \"Proposed Extraction Prompt Structure\"\n *\n * This module contains all prompts used for memory consolidation.\n * Prompts are structured to use Chain-of-Thought (CoT) reasoning to\n * distinguish transient events from persistent facts.\n *\n * Key Principles:\n * - Clear mission statement\n * - Explicit definitions (transient vs persistent)\n * - Strict extraction rules\n * - Structured XML output (more reliable than JSON for LLMs)\n * - CoT examples for few-shot learning\n */\n\n/**\n * System prompt for the consolidation engine\n *\n * This replaces runtime.character.system temporarily during consolidation\n */\nexport const CONSOLIDATION_SYSTEM_PROMPT = `You are the \"Cortex\" — an advanced Memory Extraction Engine.\nYour function is to parse conversation logs and extract persistent facts into a structured database format.\n\n# CORE DIRECTIVE: \"Subject-First\" Extraction\nYou must rephrase memories to focus on the *topic*, not the user. This optimizes vector retrieval.\n- BAD: \"User likes to trade Bitcoin.\" (Too generic)\n- GOOD: \"Bitcoin (BTC) is a preferred trading asset.\" (Topic-focused)\n\n# COMPRESSION RULES (CRITICAL)\n1. **Aggressive Filtering**: Most user chatter is noise. If it won't be relevant in 30 days, DO NOT extract it.\n2. **Merge & Dedupe**: Do not create three separate memories for one topic. Combine them.\n - *Input:* \"I like Red. I also like Blue. And Green.\"\n - *Output:* \"Red, Blue, and Green are the preferred colors.\"\n3. **Conflict Resolution**: If a new fact contradicts an old one, mark 'isContradiction' as true.\n\n# OUTPUT FORMAT\nPhase 1: [ANALYSIS]\n- List extracted points.\n- MARK items as [TRANSIENT] (Ignore) or [MERGE] (Combine).\n- Refine the final wording.\n\nPhase 2: [MEMORIES]\nFormat: \\`MEM|TYPE|CATEGORY|CONFIDENCE|IS_CONTRADICTION|CONTENT\\`\n\nTypes: EPISODIC, SEMANTIC, PROCEDURAL\nCategories: bio, health, finance, preferences, relationships, skills, work\n`;\n\nexport function buildExtractionPrompt(conversationLog: string): string {\n const refDate = new Date().toISOString();\n return `# INPUT DATA\n**Reference Date:** ${refDate} (Use this to resolve relative dates like \"yesterday\" or \"next Friday\")\n\n<conversation_log>\n${conversationLog}\n</conversation_log>\n\n# FEW-SHOT EXAMPLES (DENSE INPUTS)\n\n<example_1_finance_consolidation>\nInput: \"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.\"\nOutput:\n[ANALYSIS]\n- \"Market looking bad\" -> Context, not memory.\n- \"Closing ETH long\" -> Actionable preference change.\n- \"Check weather\" -> [TRANSIENT] Ignore.\n- \"Fly to Tokyo\" -> [TRANSIENT] \"Might\" implies uncertainty. Ignore until confirmed.\n- \"Cancel SOL orders\" -> Actionable strategy.\n- \"Go all cash\" -> High-level strategy.\n- MERGE: Combine ETH close, SOL cancel, and Cash strategy into one record.\n[MEMORIES]\nMEM|PROCEDURAL|finance|0.95|true|Portfolio Strategy: All positions (ETH, SOL) liquidated; Cash-only stance adopted for weekend.\n</example_1_finance_consolidation>\n\n<example_2_companion_emotional>\nInput: \"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.\"\nOutput:\n[ANALYSIS]\n- \"Fight with sister Jenny\" -> Relationship dynamic.\n- \"She's controlling\" -> Character attribute.\n- \"Don't want to talk about her\" -> Boundary/Preference.\n- \"Play a game\" -> [TRANSIENT] Immediate desire.\n- \"Hate chess\" -> Negative Preference.\n- \"Do a quiz\" -> [TRANSIENT] Immediate desire.\n- MERGE: Combine Jenny details. Separate Chess preference.\n[MEMORIES]\nMEM|EPISODIC|relationships|0.9|false|Jenny (sister) is characterized as controlling; currently a sensitive topic to be avoided.\nMEM|SEMANTIC|preferences|0.95|false|Chess is a disliked activity (described as boring).\n</example_2_companion_emotional>\n\n<example_3_coding_stack>\nInput: \"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'.\"\nOutput:\n[ANALYSIS]\n- \"node_modules huge\" -> Rationale.\n- \"Done with NPM\" -> Deprecation.\n- \"Use Bun\" -> New Standard.\n- \"Debug this loop\" -> [TRANSIENT] Immediate task.\n- MERGE: Bun adoption and NPM rejection.\n[MEMORIES]\nMEM|PROCEDURAL|skills|0.95|true|Bun is the mandated package manager; NPM usage is deprecated/forbidden.\n</example_3_coding_stack>\n\n<example_4_health_routine>\nInput: \"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.\"\nOutput:\n[ANALYSIS]\n- \"Ate a burger\" -> [TRANSIENT] One-off meal.\n- \"Felt heavy\" -> [TRANSIENT] Temporary sensation.\n- \"Start intermittent fasting\" -> New Health Protocol.\n- \"16/8 window, 12-8\" -> Specific details of protocol.\n- \"Remind me to drink water\" -> [TRANSIENT] Command.\n- MERGE: All fasting details into one concise protocol.\n[MEMORIES]\nMEM|PROCEDURAL|health|0.9|false|Intermittent Fasting (16/8 protocol) adopted: Eating window restricted to 12pm-8pm.\n</example_4_health_routine>\n\n<example_5_work_milestones>\nInput: \"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.\"\nOutput:\n[ANALYSIS]\n- \"Meeting went well\" -> [TRANSIENT] Sentiment.\n- \"Apex Corp\" -> Client Entity.\n- \"$50k budget\" -> Financial Fact.\n- \"Deadline March 1st\" -> Project Constraint.\n- \"Write note\" -> [TRANSIENT] Task.\n- \"Update resume\" -> [TRANSIENT] Generic task unless specific details given.\n- MERGE: Client details, budget, and deadline.\n[MEMORIES]\nMEM|SEMANTIC|work|1.0|false|Apex Corp project secured: $50k budget with March 1st deadline.\n</example_5_work_milestones>\n\n# EXTRACTION CHECKLIST\n1. **Search for STATE CHANGES**: Did the user move, change jobs, break up, or alter a portfolio? These are high-value.\n2. **Search for HARD CONSTRAINTS**: Look for phrases like \"Never do X\", \"Always use Y\", \"I hate Z\".\n3. **COMPRESSION**:\n - You have received a long conversation.\n - **MERGE** related details into single, dense records.\n - **IGNORE** all small talk, greetings, and transient requests.\n4. **QUALITY CONTROL**: If a fact feels temporary or weak, **DO NOT** extract it. Silence is better than noise.\n\nBegin the [ANALYSIS] phase now.`;\n}\n\n/**\n * Contradiction detection prompt\n *\n * Research: Section 4.3.1 \"Detection Logic\"\n *\n * Used to determine if a new memory contradicts existing memories\n */\nexport function buildContradictionPrompt(\n newMemoryContent: string,\n existingMemories: Array<{ content: string; confidence: number; createdAt: string }>\n): string {\n return `Does this new memory contradict any existing memories?\n\nNew: \"${newMemoryContent}\"\n\nExisting:\n${existingMemories.map((m, idx) => `${idx + 1}. \"${m.content}\" (confidence: ${m.confidence})`).join('\\n')}\n\nA contradiction means both statements cannot be true simultaneously.\n\nTRUE contradictions:\n- \"User likes blue\" vs \"User hates blue\"\n- \"User lives in Paris\" vs \"User lives in London\"\n- \"User is vegetarian\" vs \"User eats meat\"\n\nNOT contradictions:\n- \"User likes blue\" vs \"User likes blue for clothes\" (nuance)\n- \"User was in Paris\" vs \"User moved to London\" (time change)\n- \"User likes Python\" vs \"User likes JavaScript\" (not exclusive)\n\n<response>\n<hasContradiction>true or false</hasContradiction>\n<contradictingIndex>number or null</contradictingIndex>\n<reasoning>Brief explanation</reasoning>\n</response>`;\n}\n",
|
|
19
|
+
"import {\n type Evaluator,\n type IAgentRuntime,\n type Memory,\n logger,\n ModelType,\n type UUID,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\nimport {\n SUMMARIZATION_SYSTEM_PROMPT,\n HIGHER_LEVEL_SUMMARIZATION_SYSTEM_PROMPT,\n buildLevel1SummaryPrompt,\n buildHigherLevelSummaryPrompt,\n estimateTokensInSummary,\n} from '../prompts/summarization';\nimport type { ConversationSummary } from '../types/index';\n\n/**\n * Summarization message counters per room (Level 1)\n * Tracks BOTH user and agent messages (all dialogue messages)\n * Counter-only approach - messages are pulled from DB when summarization triggers\n */\nconst summarizationCounters = new Map<UUID, number>();\n\n/**\n * Hierarchical Summarization Evaluator\n *\n * Research: Section 5.1.2 \"Hierarchical Episodic Summarization\"\n *\n * Implements recursive, multi-level summarization for token-efficient conversation history:\n * - Level 1: Summarizes 50-100 messages into narrative paragraphs\n * - Level 2+: Summarizes lower-level summaries into higher-level abstractions\n */\nexport const summarizationEvaluator: Evaluator = {\n name: 'SUMMARIZATION',\n similes: ['HIERARCHICAL_SUMMARIZATION', 'EPISODIC_COMPRESSION', 'CONVERSATION_SUMMARY'],\n\n description:\n 'Hierarchical conversation summarization that compresses message history into multi-level narrative summaries ' +\n 'for token-efficient long-term episodic memory.',\n\n /**\n * Validation: Check if we should trigger summarization\n */\n validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => {\n // Get memory service for configuration\n const memoryService = runtime.getService<MemoryService>('memory');\n if (!memoryService) {\n return false;\n }\n\n const config = memoryService.getConfig();\n\n // Check if summarization is enabled\n if (!config.summarization?.enabled) {\n logger.debug('Summarization is not enabled');\n return false;\n }\n\n // Initialize counter for this room if needed\n if (!summarizationCounters.has(message.roomId)) {\n summarizationCounters.set(message.roomId, 0);\n }\n\n // Increment counter for ALL dialogue messages (both user and agent)\n const currentCount = summarizationCounters.get(message.roomId)! + 1;\n summarizationCounters.set(message.roomId, currentCount);\n\n const threshold = config.summarization.messagesPerSummary;\n\n logger.debug(\n {\n currentCount,\n threshold,\n messageId: message.id,\n entityId: message.entityId,\n roomId: message.roomId,\n },\n 'Message counted for summarization (user + agent messages)'\n );\n\n // Trigger Level 1 summarization if threshold reached\n const shouldSummarize = currentCount >= threshold;\n\n if (shouldSummarize) {\n logger.info(\n {\n roomId: message.roomId,\n messageCount: currentCount,\n threshold,\n },\n 'Summarization threshold reached (Level 1) - triggering summarization'\n );\n }\n\n return shouldSummarize;\n },\n\n /**\n * Handler: Execute hierarchical summarization pipeline\n */\n handler: async (runtime: IAgentRuntime, message: Memory): Promise<void> => {\n const memoryService = runtime.getService<MemoryService>('memory');\n if (!memoryService) {\n logger.warn('MemoryService not available for summarization');\n return;\n }\n\n const config = memoryService.getConfig();\n if (!config.summarization?.enabled) {\n return;\n }\n\n // Get the current count\n const messageCount = summarizationCounters.get(message.roomId) || 0;\n if (messageCount === 0) {\n return;\n }\n\n logger.info(\n {\n roomId: message.roomId,\n messageCount,\n },\n 'Starting Level 1 summarization - pulling messages from database'\n );\n\n try {\n // Step 1: Get the most recent Level 1 summary to determine where to start\n const previousSummary = await memoryService.getMostRecentLevel1Summary(\n message.roomId,\n message.entityId\n );\n\n // Step 2: Pull messages from database since last summary (or from beginning)\n const messages = await fetchMessagesSinceLastSummary(\n runtime,\n message.roomId,\n previousSummary?.endTime\n );\n\n if (messages.length === 0) {\n logger.warn({ roomId: message.roomId }, 'No messages found for summarization');\n return;\n }\n\n // Step 3: Create Level 1 summary with previous summary context\n const summary = await createLevel1Summary(\n runtime,\n memoryService,\n messages,\n message.roomId,\n previousSummary\n );\n\n if (summary) {\n logger.info(\n {\n summaryId: summary.id,\n tokenCount: summary.tokenCount,\n messageCount: messages.length,\n startTime: summary.startTime,\n endTime: summary.endTime,\n },\n 'Created Level 1 summary from database messages'\n );\n\n // Step 4: Reset the counter\n summarizationCounters.set(message.roomId, 0);\n\n // Step 5: Check if we should trigger higher-level summarization\n await checkAndTriggerHigherLevelSummarization(\n runtime,\n memoryService,\n summary.roomId,\n summary.level\n );\n }\n } catch (error) {\n logger.error(\n {\n error,\n roomId: message.roomId,\n },\n 'Failed to create summary'\n );\n }\n },\n\n examples: [],\n};\n\n/**\n * Fetch messages from database since the last summary\n * @param runtime Agent runtime\n * @param roomId Room ID\n * @param lastSummaryEndTime End time of the last summary (null for first summarization)\n * @returns Array of messages sorted chronologically (oldest first)\n */\nasync function fetchMessagesSinceLastSummary(\n runtime: IAgentRuntime,\n roomId: UUID,\n lastSummaryEndTime?: Date\n): Promise<Memory[]> {\n // Fetch all messages for this room\n const allMessages = await runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: 1000, // Large count to get all messages\n unique: false,\n });\n\n // Filter to only dialogue messages (exclude action results)\n const dialogueMessages = allMessages.filter(\n (msg) => !(msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result')\n );\n\n // Filter by time if we have a previous summary\n let messages = dialogueMessages;\n if (lastSummaryEndTime) {\n messages = dialogueMessages.filter((msg) => {\n if (!msg.createdAt) return false;\n const msgTime = new Date(msg.createdAt);\n return msgTime > lastSummaryEndTime;\n });\n }\n\n // Sort chronologically (oldest first) for natural conversation flow\n messages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));\n\n logger.debug(\n {\n roomId,\n totalMessages: allMessages.length,\n dialogueMessages: dialogueMessages.length,\n filteredMessages: messages.length,\n lastSummaryEndTime: lastSummaryEndTime?.toISOString(),\n },\n 'Fetched messages for summarization'\n );\n\n return messages;\n}\n\n/**\n * Parse LLM response into SummarizationResult\n */\nfunction parseSummarizationResult(response: any): {\n summary: string;\n keyTopics: string;\n reasoningTrace: string;\n} {\n try {\n const responseText = typeof response === 'string' ? response : JSON.stringify(response);\n\n // Extract [ANALYSIS] section\n const analysisMatch = responseText.match(/\\[ANALYSIS\\](.*?)(?:\\[RESULT\\]|$)/s);\n const reasoningTrace = analysisMatch ? analysisMatch[1].trim() : '';\n\n // Extract [RESULT] section\n const resultMatch = responseText.match(/\\[RESULT\\](.*?)$/s);\n const resultText = resultMatch ? resultMatch[1].trim() : '';\n\n let summary = '';\n let keyTopics = '';\n\n if (resultText) {\n // Check for pipe format: SUMM|TAGS|CONTENT\n const lines = resultText.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('SUMM|')) {\n const parts = trimmed.split('|');\n if (parts.length >= 3) {\n keyTopics = parts[1].trim();\n // Content is everything after the 2nd pipe\n summary = parts.slice(2).join('|').trim();\n break;\n }\n }\n }\n }\n\n return { summary, keyTopics, reasoningTrace };\n } catch (error) {\n logger.error({ error }, 'Failed to parse summarization response');\n return { summary: '', keyTopics: '', reasoningTrace: '' };\n }\n}\n\n/**\n * Create Level 1 summary from raw messages pulled from database\n * Includes previous summary for context and continuity\n * @param runtime Agent runtime\n * @param memoryService Memory service\n * @param messages Messages to summarize (sorted chronologically)\n * @param roomId Room ID\n * @param previousSummary Previous Level 1 summary (for context)\n */\nasync function createLevel1Summary(\n runtime: IAgentRuntime,\n memoryService: MemoryService,\n messages: Memory[],\n roomId: UUID,\n previousSummary?: ConversationSummary\n): Promise<ConversationSummary | null> {\n // Format messages with timestamps and agent/user labels (like recentMessages.ts)\n const formattedMessages = messages\n .map((m, i) => {\n const text = typeof m.content === 'string' ? m.content : m.content.text || '';\n const author = m.entityId === runtime.agentId ? 'Agent' : 'User';\n const timestamp = m.createdAt ? new Date(m.createdAt).toISOString() : 'Unknown time';\n return `[${timestamp}] ${author}: ${text}`;\n })\n .join('\\n');\n\n // Build prompt with previous summary context if available\n let prompt: string;\n if (previousSummary) {\n prompt = buildLevel1SummaryPrompt(formattedMessages, previousSummary.content);\n } else {\n prompt = buildLevel1SummaryPrompt(formattedMessages);\n }\n\n // Save original system prompt\n const originalSystemPrompt = runtime.character.system;\n\n try {\n // Swap system prompt\n runtime.character.system = SUMMARIZATION_SYSTEM_PROMPT;\n\n // Call LLM\n logger.debug('Calling LLM for Level 1 summarization with timestamped conversation log');\n const response = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt,\n temperature: 0.3,\n });\n\n // Restore system prompt\n runtime.character.system = originalSystemPrompt;\n\n // Parse response\n const { summary, keyTopics, reasoningTrace } = parseSummarizationResult(response);\n\n if (!summary) {\n logger.warn({ reasoningTrace }, 'No summary extracted from LLM response');\n return null;\n }\n\n const tokenCount = estimateTokensInSummary(summary);\n\n // Get time range from actual messages\n const startTime = messages[0].createdAt ? new Date(messages[0].createdAt) : new Date();\n const endTime = messages[messages.length - 1].createdAt\n ? new Date(messages[messages.length - 1].createdAt)\n : new Date();\n\n // Store summary with full metadata\n const summaryData: Omit<\n ConversationSummary,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount'\n > = {\n agentId: runtime.agentId,\n entityId: messages[0].entityId,\n roomId,\n level: 1,\n parentSummaryId: undefined,\n content: summary,\n tokenCount,\n startTime, // First message timestamp\n endTime, // Last message timestamp\n sourceCount: messages.length, // Total number of messages\n sourceIds: messages.map((m) => m.id), // All message IDs\n metadata: {\n keyTopics,\n hasPreviousSummary: !!previousSummary,\n },\n };\n\n return await memoryService.storeSummary(summaryData);\n } catch (error) {\n logger.error({ error }, 'Failed to call LLM for Level 1 summarization');\n runtime.character.system = originalSystemPrompt;\n return null;\n }\n}\n\n/**\n * Check if we should create a higher-level summary\n * and trigger recursive summarization if needed\n */\nasync function checkAndTriggerHigherLevelSummarization(\n runtime: IAgentRuntime,\n memoryService: MemoryService,\n roomId: UUID,\n currentLevel: number\n): Promise<void> {\n const config = memoryService.getConfig();\n if (!config.summarization) {\n return;\n }\n\n // Check if we've reached max depth\n if (currentLevel >= config.summarization.maxDepth) {\n logger.debug({ currentLevel, maxDepth: config.summarization.maxDepth }, 'Max depth reached');\n return;\n }\n\n // Get all summaries at this level for this room\n const summaries = await memoryService.getSummariesByLevel(roomId, currentLevel);\n\n // Check if we have enough summaries to create a higher-level summary\n const threshold = config.summarization.summariesPerLevel;\n if (summaries.length < threshold) {\n return;\n }\n\n logger.info(\n {\n level: currentLevel,\n count: summaries.length,\n nextLevel: currentLevel + 1,\n },\n `Triggering Level ${currentLevel + 1} summarization`\n );\n\n // Create higher-level summary\n const higherSummary = await createHigherLevelSummary(\n runtime,\n memoryService,\n summaries,\n roomId,\n currentLevel + 1\n );\n\n if (higherSummary) {\n // Recursively check if we should go even higher\n await checkAndTriggerHigherLevelSummarization(runtime, memoryService, roomId, currentLevel + 1);\n }\n}\n\n/**\n * Create Level N+1 summary from Level N summaries\n */\nasync function createHigherLevelSummary(\n runtime: IAgentRuntime,\n memoryService: MemoryService,\n lowerSummaries: ConversationSummary[],\n roomId: UUID,\n level: number\n): Promise<ConversationSummary | null> {\n // Format summaries for prompt\n const formattedSummaries = lowerSummaries\n .map((s, i) => `<summary${i + 1}>${s.content}</summary${i + 1}>`)\n .join('\\n');\n\n // Build prompt\n const prompt = buildHigherLevelSummaryPrompt(formattedSummaries);\n\n // Save original system prompt\n const originalSystemPrompt = runtime.character.system;\n\n try {\n // Swap system prompt\n runtime.character.system = HIGHER_LEVEL_SUMMARIZATION_SYSTEM_PROMPT;\n\n // Call LLM\n const response = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt,\n temperature: 0.3,\n });\n\n // Restore system prompt\n runtime.character.system = originalSystemPrompt;\n\n // Parse response\n const { summary, keyTopics, reasoningTrace } = parseSummarizationResult(response);\n\n if (!summary) {\n logger.warn({ reasoningTrace }, 'No higher-level summary extracted from LLM response');\n return null;\n }\n\n const tokenCount = estimateTokensInSummary(summary);\n\n // Get time range\n const startTime = new Date(Math.min(...lowerSummaries.map((s) => s.startTime.getTime())));\n const endTime = new Date(Math.max(...lowerSummaries.map((s) => s.endTime.getTime())));\n\n // Store summary\n const summaryData: Omit<\n ConversationSummary,\n 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount'\n > = {\n agentId: runtime.agentId,\n entityId: lowerSummaries[0].entityId,\n roomId,\n level,\n parentSummaryId: undefined,\n content: summary,\n tokenCount,\n startTime,\n endTime,\n sourceCount: lowerSummaries.length,\n sourceIds: lowerSummaries.map((s) => s.id),\n metadata: {\n keyTopics,\n compressedSummaries: lowerSummaries.length,\n },\n };\n\n return await memoryService.storeSummary(summaryData);\n } catch (error) {\n logger.error({ error, level }, 'Failed to create higher-level summary');\n runtime.character.system = originalSystemPrompt;\n return null;\n }\n}\n",
|
|
20
|
+
"/**\n * Hierarchical Summarization Prompts\n *\n * Research: Section 5.1.2 \"Hierarchical Episodic Summarization\"\n *\n * These prompts implement recursive, multi-level summarization:\n * - Level 1: Summarize raw messages into narrative paragraphs\n * - Level 2+: Summarize lower-level summaries into higher-level abstractions\n *\n * Goal: Achieve 10x token compression while preserving conversational narrative\n */\n\n/**\n * System prompt for Level 1 summarization (messages → summary)\n */\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are \"Chronos\", a master summarizer.\nYour function is to condense conversation logs into concise, subject-first narrative summaries.\n\n# CORE DIRECTIVE: \"Subject-First\" Summarization\nYou must rephrase the narrative to focus on the *topic*, not the user. This optimizes vector retrieval.\n- BAD: \"User asked about Python.\" (Too generic)\n- GOOD: \"Python programming inquiries were addressed.\" (Topic-focused)\n\n# COMPRESSION RULES\n1. **Be Concise**: Target 2-4 sentences. Maximum 100 words.\n2. **Be Factual**: No interpretation, no speculation. Only what actually happened.\n3. **Be Narrative**: Write as a story, not a bullet list.\n4. **Preserve Key Facts**: If the user revealed important information (preferences, identity, needs), include it.\n5. **Exclude Trivia**: Skip greetings, acknowledgments, and filler conversation.\n\n# OUTPUT FORMAT\nPhase 1: [ANALYSIS]\n- Identify key topics.\n- Draft the summary.\n- Refine wording to be subject-first.\n\nPhase 2: [RESULT]\nFormat: \\`SUMM|TAGS|CONTENT\\`\n- TAGS: Comma-separated list of key topics (lowercase)\n- CONTENT: The narrative summary text (must be a single line, no newlines)\n`;\n\nexport function buildLevel1SummaryPrompt(\n formattedMessages: string,\n previousSummary?: string\n): string {\n // Include previous summary context if available\n const previousContext = previousSummary\n ? `\n# PREVIOUS SUMMARY\n<previous_summary>\n${previousSummary}\n</previous_summary>\n\n**Note**: The above is what was discussed before. Ensure your new summary:\n- Does not duplicate information already captured in the previous summary\n- Focuses only on the NEW conversation below\n- Maintains continuity (e.g., \"Conversation continued with...\")\n`\n : '';\n\n return `${previousContext}\n# INPUT DATA\n<messages>\n${formattedMessages}\n</messages>\n\n# FEW-SHOT EXAMPLES\n\n<example_1_task_oriented>\nInput:\n[Message 1] User: I need help deploying my React app to Vercel\n[Message 2] Agent: Sure! First, make sure you have the Vercel CLI installed...\n[Message 3] User: Done. What's next?\n[Message 4] Agent: Run 'vercel' in your project directory...\n[Message 5] User: It worked! Thanks!\n\nOutput:\n[ANALYSIS]\n- Topic: React app deployment to Vercel.\n- Action: CLI installation and deployment.\n- Outcome: Success.\n- Draft: User requested help... -> React app deployment...\n[RESULT]\nSUMM|deployment,react,vercel,cli|React app deployment to Vercel was successfully completed following CLI installation and configuration guidance.\n</example_1_task_oriented>\n\n<example_2_identity_revelation>\nInput:\n[Message 1] User: I'm working on a side project in my spare time\n[Message 2] Agent: That's great! What kind of project?\n[Message 3] User: A machine learning app for analyzing stock data. I'm a data scientist by profession.\n[Message 4] Agent: Interesting! Are you using Python?\n[Message 5] User: Yeah, mostly PyTorch and pandas.\n\nOutput:\n[ANALYSIS]\n- Identity: Data scientist.\n- Project: Stock data analysis (ML).\n- Tech Stack: Python, PyTorch, pandas.\n- Draft: User discussed... -> Stock data analysis project...\n[RESULT]\nSUMM|machine learning,data science,python,stocks|Stock data analysis project (Machine Learning) utilizing Python (PyTorch, pandas) is in development by a data scientist.\n</example_2_identity_revelation>\n\n<example_3_chitchat>\nInput:\n[Message 1] User: Hey, how's it going?\n[Message 2] Agent: I'm doing well, thanks for asking! How can I help you today?\n[Message 3] User: Just saying hi\n[Message 4] Agent: Nice to hear from you!\n\nOutput:\n[ANALYSIS]\n- Content: Greetings only.\n- Substance: None.\n[RESULT]\nSUMM|greeting,casual|Casual greeting exchanged; no substantive topics discussed.\n</example_3_chitchat>\n\nBegin the [ANALYSIS] phase now.`;\n}\n\n/**\n * System prompt for Level 2+ summarization (summaries → meta-summary)\n */\nexport const HIGHER_LEVEL_SUMMARIZATION_SYSTEM_PROMPT = `You are \"Chronos\", a Meta-Summarization Agent.\nYour task is to compress multiple conversation summaries into a single, higher-level summary.\n\n# MISSION\nTransform a list of conversation summaries into one concise meta-summary that captures:\n1. **Overarching themes** across the summaries\n2. **Key events or milestones** (e.g., \"User onboarded\", \"Project completed\")\n3. **Evolving context** (e.g., \"User's preferences shifted from X to Y\")\n\n# RULES\n- **Subject-First**: Focus on the topic, not the user.\n- **Abstract Higher**: Don't repeat specifics from each summary. Find the pattern.\n- **Chronological Flow**: Maintain temporal order if it matters.\n- **Preserve Critical Facts**: If summaries mention important identity or preferences, keep them.\n\n# OUTPUT FORMAT\nPhase 1: [ANALYSIS]\n- Identify themes and milestones.\n- Combine related points.\n- Refine to subject-first.\n\nPhase 2: [RESULT]\nFormat: \\`SUMM|TAGS|CONTENT\\`\n- TAGS: Comma-separated list of key topics (lowercase)\n- CONTENT: The meta-summary text (must be a single line, no newlines)\n`;\n\nexport function buildHigherLevelSummaryPrompt(formattedSummaries: string): string {\n return `# INPUT DATA\n<summaries>\n${formattedSummaries}\n</summaries>\n\n# FEW-SHOT EXAMPLES\n\n<example_1_meta_summary>\nInput:\n<summary1>Stock data analysis project (Machine Learning) utilizing Python (PyTorch, pandas) is in development by a data scientist.</summary1>\n<summary2>Flask and Vercel were suggested for ML model deployment to a web app.</summary2>\n<summary3>CORS configuration issues were resolved, leading to successful deployment.</summary3>\n\nOutput:\n[ANALYSIS]\n- Theme: ML App Development & Deployment.\n- Flow: Development -> Stack Choice -> Deployment -> Troubleshooting -> Success.\n- Draft: User, a data scientist... -> Machine learning stock analysis app...\n[RESULT]\nSUMM|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.\n</example_1_meta_summary>\n\nBegin the [ANALYSIS] phase now.`;\n}\n\n/**\n * Estimate token count from text (used as fallback)\n */\nexport function estimateTokensInSummary(text: string): number {\n // Simple heuristic: 1 token ≈ 4 characters\n return Math.ceil(text.length / 4);\n}\n",
|
|
21
|
+
"import {\n type Provider,\n type IAgentRuntime,\n type Memory,\n type State,\n logger,\n type ProviderResult,\n addHeader,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\nimport { MemoryType } from '../types/index';\n\n/**\n * Long-Term Memory Provider (Facts Only)\n *\n * Research: Section 3 \"RAG Strategy\" - Semantic & Procedural Knowledge\n *\n * This provider focuses ONLY on persistent knowledge about the user:\n * - **Semantic Facts**: Timeless information (preferences, identity, skills)\n * - **Procedural Patterns**: How the user does things, tool preferences\n *\n * DOES NOT INCLUDE:\n * - Recent messages (handled by RECENT_CONTEXT)\n * - Conversation summaries (handled by RECENT_CONTEXT)\n * - Current message (handled by RECENT_CONTEXT)\n *\n * Design Philosophy:\n * - Pure knowledge retrieval (no conversational context)\n * - Used in FINAL response phase (after planning)\n * - Provides \"who is this user\" context\n *\n * Template Variables Provided:\n * - `longTermMemories`: Formatted semantic/procedural facts\n */\nexport const longTermMemoryProvider: Provider = {\n name: 'LONG_TERM_MEMORY',\n description: 'User knowledge and facts (semantic + procedural memory)',\n position: 80, // Lower priority - used in final response, not planning\n\n get: async (runtime: IAgentRuntime, message: Memory, state?: State): Promise<ProviderResult> => {\n try {\n // Get memory service\n const memoryService = runtime.getService<MemoryService>('memory');\n\n if (!memoryService) {\n logger.warn('Memory service not available');\n return {\n data: {},\n values: {},\n text: '',\n };\n }\n\n // Extract user ID (entity we're retrieving memories for)\n const entityId = message.entityId;\n const roomId = message.roomId;\n\n // Construct query from message content\n const query =\n typeof message.content === 'string'\n ? message.content\n : message.content.text || JSON.stringify(message.content);\n\n logger.debug(\n {\n entityId,\n roomId,\n queryLength: query.length,\n },\n 'Retrieving unified memories'\n );\n\n // =========================================================================\n // SEMANTIC & PROCEDURAL FACTS (Pure Knowledge - No Conversation Context)\n // Research: Section 3 \"RAG Strategy\" + Section 4.2 \"Decay Scoring\"\n // =========================================================================\n\n const config = memoryService.getConfig();\n\n // Retrieve semantic, procedural, and episodic memories in parallel\n const [semanticMemories, proceduralMemories, episodicMemories] = await Promise.all([\n memoryService.searchLongTermMemories({\n entityId,\n query,\n roomId,\n type: MemoryType.SEMANTIC,\n limit: config.retrievalLimit,\n minConfidence: config.minConfidence,\n similarityThreshold: 0.15,\n }),\n memoryService.searchLongTermMemories({\n entityId,\n query,\n roomId,\n type: MemoryType.PROCEDURAL,\n limit: Math.floor(config.retrievalLimit / 2),\n minConfidence: config.minConfidence,\n similarityThreshold: 0.15,\n }),\n memoryService.searchLongTermMemories({\n entityId,\n query,\n roomId,\n type: MemoryType.EPISODIC,\n limit: config.retrievalLimit,\n minConfidence: config.minConfidence,\n similarityThreshold: 0.15,\n }),\n ]);\n\n // Format long-term memories\n const longTermSections: string[] = [];\n\n if (semanticMemories.length > 0) {\n const items = semanticMemories\n .map(\n (m) =>\n `- ${m.content} (confidence: ${m.confidence.toFixed(2)}, strength: ${m.activationScore.toFixed(2)})`\n )\n .join('\\n');\n longTermSections.push(addHeader('## Semantic Knowledge (Facts)', items));\n }\n\n if (proceduralMemories.length > 0) {\n const items = proceduralMemories.map((m) => `- ${m.content}`).join('\\n');\n longTermSections.push(addHeader('## Procedural Knowledge (Skills & Patterns)', items));\n }\n\n if (episodicMemories.length > 0) {\n const items = episodicMemories\n .map(\n (m) =>\n `- ${m.content} (occurred: ${m.createdAt ? new Date(m.createdAt).toLocaleDateString() : 'Unknown'})`\n )\n .join('\\n');\n longTermSections.push(addHeader('## Significant Past Events', items));\n }\n\n const longTermMemoriesText = longTermSections.join('\\n\\n');\n\n // =========================================================================\n // Assemble Result\n // =========================================================================\n\n const data = {\n semanticMemories,\n proceduralMemories,\n episodicMemories,\n config: {\n retrievalLimit: config.retrievalLimit,\n tokenBudget: config.tokenBudget,\n },\n };\n\n const values = {\n longTermMemories: longTermMemoriesText,\n };\n\n const text = longTermMemoriesText;\n\n logger.info(\n {\n semanticCount: semanticMemories.length,\n proceduralCount: proceduralMemories.length,\n episodicCount: episodicMemories.length,\n },\n 'Retrieved long-term memory facts'\n );\n\n return {\n data,\n values,\n text,\n };\n } catch (error) {\n logger.error({ error }, 'Failed to retrieve long-term memories');\n // Return empty on error to avoid breaking conversation\n return {\n data: {},\n values: {\n longTermMemories: '',\n },\n text: '',\n };\n }\n },\n};\n",
|
|
22
|
+
"import {\n addHeader,\n ChannelType,\n CustomMetadata,\n formatMessages,\n formatPosts,\n getEntityDetails,\n type Entity,\n type IAgentRuntime,\n type Memory,\n type Provider,\n type UUID,\n logger,\n} from '@elizaos/core';\nimport { MemoryService } from '../services/memory-service';\nimport type { ConversationSummary } from '../types/index';\n\n/**\n * Smart Context Manager Provider\n *\n * Research: CONTEXT-SUMMARY.MD Section 2.3 \"The Hybrid Architecture: Summary + Buffer\"\n *\n * This provider implements a dynamic buffer architecture:\n * - **The Buffer**: Recent messages with overlap for continuity\n * - **The Compressed History**: Hierarchical summaries for older messages\n * - **The Received Message**: Current user input clearly marked\n *\n * Dynamic Buffer Strategy:\n * - No summaries: Show ALL messages (best for early conversations)\n * - After summary: Show [overlap + new unsummarized messages]\n * - Overlap (fixed): Last N user messages from summarized portion (configurable)\n * - New messages (dynamic): ALL messages since last summary\n * - Buffer GROWS naturally until next summarization threshold\n *\n * Key Features:\n * - Preserves conversational continuity through smart overlap\n * - Dynamically grows buffer as conversation continues\n * - Reduces token usage through intelligent compression\n * - Maintains character fidelity with in-context summaries\n * - Clearly indicates current message for focused responses\n */\n\n// Configuration constants - loaded from runtime.getSetting for tunability\nconst getProviderConfig = (runtime: IAgentRuntime) => ({\n // How many user messages to show as overlap from summarized portion (for continuity)\n overlapUserMessageCount: parseInt(runtime.getSetting('CONTEXT_OVERLAP_USER_MESSAGES') || '2', 10),\n});\n\ninterface ConversationData {\n entities: Entity[];\n room: any;\n allMessages: Memory[];\n}\n\ninterface BufferCalculationResult {\n bufferMessages: Memory[];\n lastSummarizedIndex: number;\n}\n\n/**\n * Fetch all conversation data in parallel\n */\nasync function fetchConversationData(\n runtime: IAgentRuntime,\n roomId: UUID\n): Promise<ConversationData> {\n const [entities, room, allMessages] = await Promise.all([\n getEntityDetails({ runtime, roomId }),\n runtime.getRoom(roomId),\n runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: 100,\n unique: false,\n }),\n ]);\n\n return { entities, room, allMessages };\n}\n\n/**\n * Filter and sort dialogue messages\n */\nfunction filterAndSortDialogueMessages(allMessages: Memory[]): Memory[] {\n // Separate action results from dialogue messages\n const dialogueMessages = allMessages.filter(\n (msg) => !(msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result')\n );\n\n // Sort dialogue messages by timestamp (oldest to newest) to ensure chronological order\n dialogueMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));\n\n return dialogueMessages;\n}\n\n/**\n * Build compressed history from hierarchical summaries\n * Research: CONTEXT-SUMMARY.MD Section 2.3.2 \"The Archive\"\n */\nasync function buildCompressedHistory(\n runtime: IAgentRuntime,\n message: Memory,\n dialogueMessages: Memory[],\n sessionStartTime: number\n): Promise<{ compressedHistoryText: string; lastSummarizedIndex: number }> {\n let compressedHistoryText = '';\n let lastSummarizedIndex = -1;\n\n const memoryService = runtime.getService<MemoryService>('memory');\n if (!memoryService?.searchSummaries) {\n return { compressedHistoryText, lastSummarizedIndex };\n }\n\n try {\n // Use hierarchical summaries\n const summaries = await memoryService.searchSummaries({\n entityId: message.entityId,\n roomId: message.roomId,\n query: typeof message.content === 'string' ? message.content : message.content.text || '',\n limit: 3, // Show top 3 relevant summaries\n tokenBudget: 500, // Limit summary tokens\n });\n\n if (summaries.length === 0) {\n return { compressedHistoryText, lastSummarizedIndex };\n }\n\n // Find the most recent Level 1 summary to determine coverage point\n lastSummarizedIndex = findLastSummarizedMessageIndex(summaries, dialogueMessages);\n\n // Format summaries for display\n const summaryItems = summaries\n .map((s) => {\n const levelLabel = s.level === 1 ? 'Recent Session' : `Overview (L${s.level})`;\n return `**[${levelLabel}]** ${s.content}`;\n })\n .join('\\n\\n');\n\n // Build header with session start time\n const headerText = `# Conversation History (Compressed)\\n**Session Started:** ${formatDateTime(sessionStartTime)}`;\n compressedHistoryText = addHeader(headerText, summaryItems);\n\n logger.debug(\n {\n summaryCount: summaries.length,\n totalTokens: summaries.reduce((sum, s) => sum + s.tokenCount, 0),\n lastSummarizedIndex,\n },\n 'Using hierarchical summaries for compressed history'\n );\n } catch (error) {\n logger.warn({ error }, 'Failed to retrieve summaries');\n }\n\n return { compressedHistoryText, lastSummarizedIndex };\n}\n\n/**\n * Find the index of the last message that was summarized\n */\nfunction findLastSummarizedMessageIndex(\n summaries: ConversationSummary[],\n dialogueMessages: Memory[]\n): number {\n const level1Summaries = summaries.filter((s) => s.level === 1);\n if (level1Summaries.length === 0) {\n return -1;\n }\n\n // Find which dialogue messages are covered by summaries\n const allSummarizedMessageIds = new Set<UUID>();\n level1Summaries.forEach((summary) => {\n summary.sourceIds.forEach((id) => allSummarizedMessageIds.add(id));\n });\n\n // Find the index of the last summarized message\n for (let i = dialogueMessages.length - 1; i >= 0; i--) {\n if (allSummarizedMessageIds.has(dialogueMessages[i].id)) {\n logger.debug(\n {\n lastSummarizedIndex: i,\n totalMessages: dialogueMessages.length,\n summarizedCount: allSummarizedMessageIds.size,\n },\n 'Determined last summarized message index'\n );\n return i;\n }\n }\n\n return -1;\n}\n\n/**\n * Calculate which messages to show in the buffer\n * Research: CONTEXT-SUMMARY.MD Section 2.3.1 \"The Buffer\"\n *\n * Dynamic Buffer Strategy:\n * - If NO summaries: Show ALL messages (early conversation, best context)\n * - If summaries exist: Show [OVERLAP + NEW UNSUMMARIZED MESSAGES]\n * - OVERLAP (fixed): Last N user messages from summarized portion (configurable, default 4)\n * - NEW MESSAGES (dynamic): ALL messages after lastSummarizedIndex\n * - This allows buffer to GROW naturally as conversation continues until next summary\n *\n * Example flow (with overlapUserMessageCount=4):\n * - Messages 0-9: No summary, show all 10 messages\n * - Summary created (covers 0-9)\n * - Messages 10-11: Show [overlap: msgs 3-9] + [new: msgs 10-11] = ~10 messages\n * - Messages 12-13: Show [overlap: msgs 3-9] + [new: msgs 10-13] = ~12 messages\n * - Continue until next summary threshold...\n */\nfunction calculateBufferMessages(\n runtime: IAgentRuntime,\n dialogueMessages: Memory[],\n lastSummarizedIndex: number,\n hasSummaries: boolean,\n overlapUserMessageCount: number\n): BufferCalculationResult {\n let bufferMessages: Memory[];\n\n if (lastSummarizedIndex >= 0 && hasSummaries) {\n // We have summaries - use DYNAMIC BUFFER strategy\n // Buffer = [overlap from summarized] + [all new unsummarized messages]\n\n // Part 1: Get overlap - last N user messages from SUMMARIZED portion\n const summarizedMessages = dialogueMessages.slice(0, lastSummarizedIndex + 1);\n const summarizedUserMessages = summarizedMessages.filter((m) => m.entityId !== runtime.agentId);\n const overlapUserMessages = summarizedUserMessages.slice(-overlapUserMessageCount);\n\n // Part 2: Get all NEW messages after the last summarized index\n const newUnsummarizedMessages = dialogueMessages.slice(lastSummarizedIndex + 1);\n\n // Find where the overlap starts in the full dialogue\n let overlapStartIndex = lastSummarizedIndex + 1; // Default: no overlap, start at first new message\n\n if (overlapUserMessages.length > 0) {\n // Find the first of the overlap user messages in the full dialogue\n const firstOverlapUserMessageId = overlapUserMessages[0].id;\n const foundIndex = dialogueMessages.findIndex((m) => m.id === firstOverlapUserMessageId);\n if (foundIndex >= 0) {\n overlapStartIndex = foundIndex;\n }\n }\n\n // Combine overlap + new messages\n // This gives us: [last N user messages from summarized] + [all messages since summary]\n bufferMessages = dialogueMessages.slice(overlapStartIndex);\n\n logger.debug(\n {\n lastSummarizedIndex,\n summarizedMessageCount: summarizedMessages.length,\n overlapStartIndex,\n overlapSize: lastSummarizedIndex + 1 - overlapStartIndex,\n newUnsummarizedCount: newUnsummarizedMessages.length,\n bufferSize: bufferMessages.length,\n totalDialogueMessages: dialogueMessages.length,\n overlapUserMessageCount,\n },\n `Dynamic buffer: [overlap: last ${overlapUserMessageCount} user msgs from summary] + [all new unsummarized messages]`\n );\n } else {\n // No summaries - show ALL messages (early conversation)\n bufferMessages = dialogueMessages;\n\n logger.debug(\n {\n bufferSize: bufferMessages.length,\n totalMessages: dialogueMessages.length,\n },\n 'Using full conversation: no summaries yet'\n );\n }\n\n return { bufferMessages, lastSummarizedIndex };\n}\n\n/**\n * Format a timestamp to a readable datetime string\n */\nfunction formatDateTime(timestamp: number): string {\n const date = new Date(timestamp);\n return date.toLocaleString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n}\n\n/**\n * Remove entity IDs and thoughts from formatted message text\n * Removes patterns like [uuid] and (Name's internal thought: ...) from the formatted output\n */\nfunction removeEntityIds(text: string): string {\n // Remove [uuid] patterns - matches UUIDs in square brackets\n // Remove thoughts - matches patterns like (Name's internal thought: ...)\n return text\n .replace(/\\s*\\[[\\w\\-]+\\]/g, '')\n .replace(/\\s*\\([^)]*'s internal thought:[^)]*\\)/gi, '')\n .split('\\n')\n .map((line) => line.trim())\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n'); // Collapse multiple newlines to max 2\n}\n\n/**\n * Format buffer messages for display\n */\nasync function formatBufferMessages(\n bufferMessages: Memory[],\n entities: Entity[],\n room: any,\n sessionStartTime: number\n): Promise<string> {\n const isPostFormat = room?.type\n ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD\n : false;\n\n const [formattedRecentMessages, formattedRecentPosts] = await Promise.all([\n formatMessages({\n messages: bufferMessages,\n entities: entities,\n }),\n formatPosts({\n messages: bufferMessages,\n entities: entities,\n conversationHeader: false,\n }),\n ]);\n\n let recentBufferText = (isPostFormat ? formattedRecentPosts : formattedRecentMessages) || '';\n\n // Remove entity IDs from the formatted text\n recentBufferText = removeEntityIds(recentBufferText);\n\n // Build header with time range information\n const firstBufferTime = bufferMessages.length > 0 ? bufferMessages[0].createdAt : null;\n const lastBufferTime =\n bufferMessages.length > 0 ? bufferMessages[bufferMessages.length - 1].createdAt : null;\n\n let headerText = `# Recent Messages (Last ${bufferMessages.length})`;\n if (firstBufferTime && lastBufferTime) {\n headerText += `\\n**Time Range:** ${formatDateTime(firstBufferTime)} - ${formatDateTime(lastBufferTime)}`;\n }\n\n return recentBufferText ? addHeader(headerText, recentBufferText) : '';\n}\n\n/**\n * Build received message and focus sections\n */\nfunction buildReceivedMessageSection(\n message: Memory,\n entities: Entity[]\n): { receivedMessageHeader: string; focusHeader: string } {\n const metaData = message.metadata as CustomMetadata;\n const senderName =\n entities.find((entity: Entity) => entity.id === message.entityId)?.names[0] ||\n metaData?.entityName ||\n 'Unknown User';\n const receivedMessageContent = message.content.text;\n const hasReceivedMessage = !!receivedMessageContent?.trim();\n\n const receivedMessageHeader = hasReceivedMessage\n ? addHeader('# Current Message', `**From ${senderName}:** ${receivedMessageContent}`)\n : '';\n\n const focusHeader = hasReceivedMessage\n ? addHeader(\n '# Response Focus',\n `Reply to **${senderName}**'s current message above. Stay relevant to their question. Don't repeat previous responses unless asked again.`\n )\n : '';\n\n return { receivedMessageHeader, focusHeader };\n}\n\n/**\n * Assemble final context sections\n */\nfunction assembleContextSections(\n compressedHistoryText: string,\n recentBufferHeader: string,\n receivedMessageHeader: string,\n focusHeader: string\n): string {\n const textSections = [\n compressedHistoryText, // 1. Summaries at top (attention peak)\n recentBufferHeader, // 2. Recent buffer (immediate context)\n receivedMessageHeader, // 3. Current message\n focusHeader, // 4. Focus instruction\n ].filter(Boolean);\n\n return textSections.join('\\n\\n');\n}\n\nexport const recentContextProvider: Provider = {\n name: 'RECENT_CONVERSATION_SUMMARY',\n description:\n 'Intelligent context management combining recent messages with hierarchical summaries for optimal token efficiency',\n position: 100,\n\n get: async (runtime: IAgentRuntime, message: Memory) => {\n try {\n const { roomId } = message;\n\n // Load configuration\n const config = getProviderConfig(runtime);\n\n // Step 1: Fetch all conversation data in parallel\n const { entities, room, allMessages } = await fetchConversationData(runtime, roomId);\n\n // Step 2: Filter and sort dialogue messages\n const dialogueMessages = filterAndSortDialogueMessages(allMessages);\n\n // Determine session start time (earliest message timestamp)\n const sessionStartTime =\n dialogueMessages.length > 0 ? dialogueMessages[0].createdAt || Date.now() : Date.now();\n\n // Step 3: Build compressed history (summaries)\n const { compressedHistoryText, lastSummarizedIndex } = await buildCompressedHistory(\n runtime,\n message,\n dialogueMessages,\n sessionStartTime\n );\n\n const hasSummaries = !!compressedHistoryText;\n\n // Step 4: Calculate buffer messages (dynamic: grows until next summary)\n const { bufferMessages } = calculateBufferMessages(\n runtime,\n dialogueMessages,\n lastSummarizedIndex,\n hasSummaries,\n config.overlapUserMessageCount\n );\n\n // Step 5: Format buffer messages\n const recentBufferHeader = await formatBufferMessages(\n bufferMessages,\n entities,\n room,\n sessionStartTime\n );\n\n // Step 6: Build received message section\n const { receivedMessageHeader, focusHeader } = buildReceivedMessageSection(message, entities);\n\n // Step 7: Assemble final context\n const text = assembleContextSections(\n compressedHistoryText,\n recentBufferHeader,\n receivedMessageHeader,\n focusHeader\n );\n\n // Prepare return data\n const data = {\n dialogueMessages: bufferMessages,\n messageCount: dialogueMessages.length,\n lastSummarizedIndex,\n config,\n };\n\n const isPostFormat = room?.type\n ? room.type === ChannelType.FEED || room.type === ChannelType.THREAD\n : false;\n\n const values = {\n compressedHistory: compressedHistoryText,\n recentMessages: recentBufferHeader,\n receivedMessage: receivedMessageHeader,\n focusInstruction: focusHeader,\n // Legacy compatibility\n recentPosts: isPostFormat ? recentBufferHeader : '',\n };\n\n logger.info(\n {\n messageCount: dialogueMessages.length,\n bufferSize: bufferMessages.length,\n hasSummaries,\n lastSummarizedIndex,\n estimatedTokens: Math.ceil(text.length / 4),\n overlapUserMessageCount: config.overlapUserMessageCount,\n },\n 'Recent context assembled'\n );\n\n return {\n data,\n values,\n text,\n };\n } catch (error) {\n logger.error({ error }, 'Error in recentContextProvider');\n return {\n data: {\n dialogueMessages: [],\n messageCount: 0,\n lastSummarizedIndex: -1,\n config: getProviderConfig(runtime),\n },\n values: {\n compressedHistory: '',\n recentMessages: '',\n receivedMessage: '',\n focusInstruction: '',\n // Legacy compatibility\n recentPosts: '',\n },\n text: 'Error retrieving context.',\n };\n }\n },\n};\n",
|
|
23
|
+
"import { addHeader, type IAgentRuntime, type Memory, type Provider, logger } from '@elizaos/core';\n\n/**\n * Action Results Provider\n *\n * Research: CONTEXT-SUMMARY.MD Section 4.1.1 \"The Dual-Track Memory System\"\n *\n * This provider surfaces recent action executions to the agent, providing\n * visibility into what tools have been used and their outcomes. This is kept\n * separate from conversation messages to maintain clarity.\n */\n\nconst getActionResultsConfig = (runtime: IAgentRuntime) => ({\n limit: parseInt(runtime.getSetting('CONTEXT_ACTION_RESULTS_LIMIT') || '3', 10),\n});\n\n/**\n * Format action results grouped by run\n */\nfunction formatActionResults(actionResultMessages: Memory[], limit: number): string {\n if (actionResultMessages.length === 0) {\n return '';\n }\n\n // Group by runId\n const groupedByRun = new Map<string, Memory[]>();\n for (const mem of actionResultMessages) {\n const runId: string = String(mem.content?.runId || 'unknown');\n if (!groupedByRun.has(runId)) {\n groupedByRun.set(runId, []);\n }\n groupedByRun.get(runId)!.push(mem);\n }\n\n const formattedActionResults = Array.from(groupedByRun.entries())\n .slice(-limit)\n .map(([runId, memories]) => {\n const sortedMemories = memories.sort(\n (a: Memory, b: Memory) => (a.createdAt || 0) - (b.createdAt || 0)\n );\n\n const thought = sortedMemories[0]?.content?.planThought || '';\n const runText = sortedMemories\n .map((mem: Memory) => {\n const actionName = mem.content?.actionName || 'Unknown';\n const status = mem.content?.actionStatus || 'unknown';\n const planStep = mem.content?.planStep || '';\n const text = mem.content?.text || '';\n const error = mem.content?.error || '';\n\n let memText = ` - ${actionName} (${status})`;\n if (planStep) memText += ` [${planStep}]`;\n if (error) {\n memText += `: Error - ${error}`;\n } else if (text && text !== `Executed action: ${actionName}`) {\n memText += `: ${text}`;\n }\n\n return memText;\n })\n .join('\\n');\n\n return `**Action Run ${runId.slice(0, 8)}**${thought ? ` - \"${thought}\"` : ''}\\n${runText}`;\n })\n .join('\\n\\n');\n\n return formattedActionResults\n ? addHeader('# Recent Action Executions', formattedActionResults)\n : '';\n}\n\nexport const actionResultsProvider: Provider = {\n name: 'ACTION_RESULTS',\n description: 'Recent action executions with their outcomes (tool memory)',\n position: 101, // Right after RECENT_CONVERSATION_SUMMARY\n\n get: async (runtime: IAgentRuntime, message: Memory) => {\n try {\n const { roomId } = message;\n const config = getActionResultsConfig(runtime);\n\n // Fetch recent messages to find action results\n const allMessages = await runtime.getMemories({\n tableName: 'messages',\n roomId,\n count: 50, // Look back for action results\n unique: false,\n });\n\n // Filter only action results\n const actionResultMessages = allMessages.filter(\n (msg) => msg.content?.type === 'action_result' && msg.metadata?.type === 'action_result'\n );\n\n // Sort by timestamp (oldest to newest)\n actionResultMessages.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));\n\n const text = formatActionResults(actionResultMessages, config.limit);\n\n logger.debug(\n {\n actionResultCount: actionResultMessages.length,\n limit: config.limit,\n },\n 'Action results provider assembled'\n );\n\n return {\n data: {\n actionResults: actionResultMessages,\n config,\n },\n values: {\n recentActionResults: text,\n },\n text,\n };\n } catch (error) {\n logger.error({ error }, 'Error in actionResultsProvider');\n return {\n data: {\n actionResults: [],\n config: getActionResultsConfig(runtime),\n },\n values: {\n recentActionResults: '',\n },\n text: '',\n };\n }\n },\n};\n",
|
|
24
|
+
"import type { Plugin } from '@elizaos/core';\nimport { MemoryService } from './services/memory-service';\nimport { consolidationEvaluator } from './evaluators/consolidation';\nimport { summarizationEvaluator } from './evaluators/summarization';\nimport { longTermMemoryProvider } from './providers/long-term-memory';\nimport { recentContextProvider } from './providers/recent-conversation-summary';\nimport { actionResultsProvider } from './providers/action-results';\nimport * as schema from './schemas/index';\n\nexport * from './types/index';\nexport * from './schemas/index';\nexport * from './prompts/consolidation';\nexport * from './prompts/summarization';\nexport * from './utils/index';\nexport * from './repositories/index';\nexport { MemoryService } from './services/memory-service';\nexport { longTermMemoryProvider, recentContextProvider, actionResultsProvider };\n\n/**\n * Memory Plugin - State-of-the-Art Cognitive Memory System\n *\n * Based on comprehensive research analysis (refactor.md), this plugin implements\n * a sophisticated memory architecture that mirrors human cognitive processes.\n *\n * ## Core Concepts (Research-Based)\n *\n * ### 1. Three-Tier Memory Taxonomy\n * Research: Section 1.1 \"The Cognitive Hierarchy\"\n * - **EPISODIC**: Specific events anchored in time and place (conversation logs)\n * - **SEMANTIC**: Facts and knowledge detached from episodes (user preferences, identity)\n * - **PROCEDURAL**: Skills and successful tool execution patterns (\"know-how\")\n *\n * ### 2. Memory Consolidation Pipeline\n * Research: Section 2 \"Architecture for Extraction & Taxonomy\"\n * - Buffers conversation messages asynchronously\n * - Triggers consolidation every N messages (configurable)\n * - Extracts persistent facts using LLM with specialized prompts\n * - Filters transient intents (e.g., \"draw a cat\") from persistent facts (e.g., \"user likes cats\")\n *\n * ### 3. Hybrid Retrieval (Vector + BM25)\n * Research: Section 3 \"Retrieval Augmented Generation Strategy\"\n * - **Vector Search**: Semantic similarity using embeddings\n * - **BM25**: Keyword-based search for exact matches\n * - Combined with exponential decay for time-weighted scoring\n *\n * ### 4. Exponential Decay & Forgetting\n * Research: Section 4.2 \"Mathematical Model for Memory Decay\"\n * - Memories fade over time using Ebbinghaus forgetting curve\n * - Reinforcement: Frequently accessed memories decay slower\n * - Configurable decay rates per memory type\n *\n * ### 5. Contextual Embeddings\n * Research: Section 3.2.1 \"Solving the Pronoun Problem\"\n * - Enriches content with context before embedding\n * - Example: \"It was terrible\" → \"[User movie preference]: The movie Inception was terrible\"\n * - Enables superior retrieval accuracy\n *\n * ### 6. Contradiction Detection & Resolution\n * Research: Section 4.3 \"Handling Contradictions\"\n * - Detects when new facts contradict existing ones\n * - Uses soft-delete (isActive flag) to supersede old memories\n * - Maintains provenance chain (supersedesId)\n *\n * ## Components\n *\n * - **MemoryService**: Core service managing all memory operations\n * - **consolidationEvaluator**: Buffers messages and triggers fact extraction\n * - **summarizationEvaluator**: Creates hierarchical conversation summaries\n * - **longTermMemoryProvider** (LONG_TERM_MEMORY): User knowledge and facts\n * - **recentContextProvider** (RECENT_CONVERSATION_SUMMARY): Conversational history with summaries\n * - **actionResultsProvider** (ACTION_RESULTS): Recent action executions and tool memory\n *\n * ## Configuration (Environment Variables)\n *\n * All settings use `runtime.getSetting()` pattern:\n *\n * - `MEMORY_CONSOLIDATION_THRESHOLD`: Messages before consolidation (default: 12)\n * - `MEMORY_MIN_CONFIDENCE`: Minimum confidence to store (default: 0.7)\n * - `MEMORY_ENABLE_VECTOR_SEARCH`: Enable semantic search (default: true)\n * - `MEMORY_ENABLE_BM25`: Enable keyword search (default: true)\n * - `MEMORY_RETRIEVAL_LIMIT`: Max memories to retrieve (default: 5)\n * - `MEMORY_TOKEN_BUDGET`: Token budget for memory context (default: 1000)\n *\n * ### Hierarchical Summarization\n *\n * - `MEMORY_SUMMARY_ENABLED`: Enable hierarchical summarization (default: true)\n * - `MEMORY_MESSAGES_PER_SUMMARY`: Messages per Level 1 summary (default: 7)\n * - `MEMORY_SUMMARIES_PER_LEVEL`: Summaries before next level (default: 5)\n * - `MEMORY_SUMMARY_MAX_DEPTH`: Maximum hierarchy depth (default: 3)\n * - `MEMORY_SUMMARY_TOKEN_BUDGET`: Token budget for summaries (default: 500)\n * - `CONTEXT_OVERLAP_USER_MESSAGES`: User messages overlap after summary (default: 2)\n *\n * ## Database Tables\n *\n * - `long_term_memories`: Unified storage for all memory types\n * - `conversation_summaries`: Hierarchical conversation summaries\n *\n * ## Design Decisions\n *\n * ### Why Single Unified Table?\n * Research: Section 4.1 \"Data Structure & Schema\"\n * - Easier cross-type queries\n * - Unified retrieval logic\n * - Flexible type reassignment (episodic can become semantic over time)\n * - Simpler codebase\n *\n * ### Why Async Consolidation?\n * Research: Section 2.3 \"Consolidation Pipeline\"\n * - Doesn't block conversation flow\n * - Allows for deeper analysis without latency\n * - Mirrors biological \"sleep\" consolidation\n *\n * ### Why Contextual Embeddings?\n * Research: Section 3.2.1 \"Contextual Retrieval\"\n * - Solves pronoun ambiguity (\"it\", \"that\")\n * - Improves retrieval accuracy by 49% (Anthropic research)\n * - Self-contained memory chunks\n *\n * ## Usage Examples\n *\n * ### Accessing the Service\n * ```typescript\n * const memoryService = runtime.getService<MemoryService>('memory');\n * ```\n *\n * ### Searching Memories\n * ```typescript\n * const memories = await memoryService.searchLongTermMemories({\n * entityId: userId,\n * query: \"What does the user like?\",\n * type: MemoryType.SEMANTIC,\n * limit: 5\n * });\n * ```\n *\n * ### Storing a Memory Manually\n * ```typescript\n * await memoryService.storeLongTermMemory({\n * agentId: runtime.agentId,\n * entityId: userId,\n * type: MemoryType.SEMANTIC,\n * content: \"User is allergic to peanuts\",\n * embeddingContext: \"[User health information]: User is allergic to peanuts\",\n * confidence: 1.0,\n * decayRate: 0.0, // Core fact, never decays\n * decayFunction: DecayFunction.NONE,\n * source: { authorId: userId },\n * metadata: { category: \"health\" }\n * });\n * ```\n *\n * ## Research References\n *\n * This implementation is based on the comprehensive research document (refactor.md)\n * which analyzed 40+ academic papers and industry implementations to identify\n * state-of-the-art techniques for agentic memory systems.\n *\n * Key research areas:\n * - Cognitive science (memory hierarchies, consolidation)\n * - RAG optimization (vector search, BM25, contextual retrieval)\n * - Forgetting curves (Ebbinghaus, exponential decay)\n * - LLM prompting (Chain-of-Thought, extraction patterns)\n *\n */\nexport const memoryPlugin: Plugin = {\n name: 'memory',\n description:\n 'State-of-the-art cognitive memory system with episodic, semantic, and procedural memory, ' +\n 'featuring hybrid retrieval (Vector + BM25 + Graph), exponential decay, contextual embeddings, ' +\n 'and contradiction detection',\n\n services: [MemoryService],\n\n evaluators: [consolidationEvaluator, summarizationEvaluator],\n\n providers: [longTermMemoryProvider, recentContextProvider, actionResultsProvider],\n\n // Export schema for dynamic migrations\n schema,\n};\n\nexport default memoryPlugin;\n"
|
|
15
25
|
],
|
|
16
|
-
"mappings": "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",
|
|
17
|
-
"debugId": "
|
|
26
|
+
"mappings": "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",
|
|
27
|
+
"debugId": "CCBB98EF3F397EB764756E2164756E21",
|
|
18
28
|
"names": []
|
|
19
29
|
}
|