open-mem 0.10.0 → 0.11.0
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/CHANGELOG.md +13 -0
- package/README.md +56 -2
- package/dist/adapters/http/server.d.ts.map +1 -1
- package/dist/ai/prompts.d.ts +3 -2
- package/dist/ai/prompts.d.ts.map +1 -1
- package/dist/claude-code.js +40 -45
- package/dist/config.d.ts.map +1 -1
- package/dist/cursor.js +40 -45
- package/dist/daemon.js +37 -42
- package/dist/hooks/compaction.d.ts +5 -1
- package/dist/hooks/compaction.d.ts.map +1 -1
- package/dist/index.js +89 -90
- package/dist/maintenance.js +34 -34
- package/dist/mcp.js +44 -44
- package/dist/modes/loader.d.ts +7 -0
- package/dist/modes/loader.d.ts.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -1
package/dist/mcp.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var q0=Object.defineProperty;var h0=(E,M)=>{for(var N in M)q0(E,N,{get:M[N],enumerable:!0,configurable:!0,set:(_)=>M[N]=()=>_})};var kE=(E,M)=>()=>(E&&(M=E(E=0)),M);var D=import.meta.require;import{existsSync as n0,readFileSync as d0}from"fs";function i0(){let E={};if(process.env.OPEN_MEM_DB_PATH)E.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)E.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)E.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)E.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")E.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")E.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)E.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_BATCH_SIZE)E.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)E.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)E.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")E.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)E.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)E.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)E.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")E.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")E.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")E.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)E.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")E.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")E.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)E.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")E.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")E.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)E.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")E.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")E.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")E.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)E.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)E.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)E.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)E.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")E.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(M))E.conflictSimilarityBandLow=M}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(M))E.conflictSimilarityBandHigh=M}if(process.env.OPEN_MEM_USER_MEMORY==="true")E.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)E.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)E.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")E.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)E.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")E.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)E.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((M)=>M.trim()).filter(Boolean);return E}function a0(E){let M=`${E}/.open-mem/config.json`;if(!n0(M))return{};try{let N=d0(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}function r0(E){switch(E){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function h(E,M){let N=a0(E),_=i0(),J={...fE,...N,..._,...M};if(!J.dbPath.startsWith("/"))J.dbPath=`${E}/${J.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!M?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)J.provider="google";else if(process.env.ANTHROPIC_API_KEY)J.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)J.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)J.provider="openrouter"}if(!J.apiKey)switch(J.provider){case"google":J.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":J.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":J.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":J.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(J.provider==="openrouter"&&J.model==="gemini-2.5-flash-lite")J.model="google/gemini-2.5-flash-lite";if(J.embeddingDimension===void 0)J.embeddingDimension=r0(J.provider);return J}function EE(){return{...fE}}var fE;var ME=kE(()=>{fE={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"dispersed",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0}});var J0={};h0(J0,{writeProjectConfig:()=>_0,validatePatch:()=>ZE,readProjectConfig:()=>b,previewConfig:()=>jM,patchConfig:()=>TM,getEffectiveConfig:()=>v,getConfigSchema:()=>kM});import{existsSync as RM}from"fs";import{mkdir as WM,readFile as YM,writeFile as LM}from"fs/promises";import{dirname as BM,join as GM}from"path";function M0(E){return GM(E,".open-mem","config.json")}function N0(E){return E0.find((M)=>M.key===E)}function FM(E,M){let N=N0(E);if(!N)return null;if(N.type==="string"&&typeof M!=="string")return`${String(E)} must be a string`;if(N.type==="number"&&typeof M!=="number")return`${String(E)} must be a number`;if(N.type==="boolean"&&typeof M!=="boolean")return`${String(E)} must be a boolean`;if(N.type==="array"&&!Array.isArray(M))return`${String(E)} must be an array`;if(N.enum&&typeof M==="string"&&!N.enum.includes(M))return`${String(E)} must be one of: ${N.enum.join(", ")}`;if(typeof M==="number"){if(N.min!==void 0&&M<N.min)return`${String(E)} must be >= ${N.min}`;if(N.max!==void 0&&M>N.max)return`${String(E)} must be <= ${N.max}`}return null}function kM(){return E0}async function b(E){let M=M0(E);if(!RM(M))return{};try{let N=await YM(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}async function _0(E,M){let N=M0(E),J={...await b(E),...M};await WM(BM(N),{recursive:!0}),await LM(N,JSON.stringify(J,null,2),"utf-8")}function ZE(E){let M=[];for(let[N,_]of Object.entries(E)){let S=FM(N,_);if(S)M.push(S)}return M}async function v(E){let M=EE(),N=await b(E),_=h(E),J=[],S={};for(let[V,A]of Object.entries(M)){let $=V,O=N0($),Z=(DM[$]??[]).some((z)=>typeof process.env[z]==="string"),Y=Object.hasOwn(N,$),H="default";if(Y)H="file";if(Z)H="env";if(S[$]={source:H,locked:Z,restartRequired:O?.restartRequired??!1,liveApply:O?.liveApply??!1},H==="env"&&Y)J.push(`${String($)} is overridden by environment variable.`);if(_[$]===void 0&&A!==void 0)J.push(`${String($)} resolved to undefined unexpectedly.`)}return{config:_,meta:S,warnings:J}}async function jM(E,M){let N=ZE(M);if(N.length>0)return{...await v(E),warnings:N};let _=EE(),J=await b(E),S={..._,...J,...M},A={...h(E,M),...S},$=(await v(E)).meta;return{config:A,meta:$,warnings:[]}}async function TM(E,M){let N=ZE(M);if(N.length>0)return{...await v(E),warnings:N};return await _0(E,M),v(E)}var E0,DM;var S0=kE(()=>{ME();E0=[{key:"dbPath",label:"Database Path",type:"string",group:"Storage",liveApply:!1,restartRequired:!0},{key:"provider",label:"Provider",type:"string",group:"AI",liveApply:!1,restartRequired:!0,enum:["google","anthropic","openai","bedrock"]},{key:"model",label:"Model",type:"string",group:"AI",liveApply:!1,restartRequired:!0},{key:"maxTokensPerCompression",label:"Max Tokens Per Compression",type:"number",group:"AI",liveApply:!0,restartRequired:!1,min:128,max:8192},{key:"compressionEnabled",label:"Compression Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"contextInjectionEnabled",label:"Context Injection Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"maxContextTokens",label:"Max Context Tokens",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:500,max:64000},{key:"batchSize",label:"Batch Size",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1,max:100},{key:"batchIntervalMs",label:"Batch Interval (ms)",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1000,max:300000},{key:"ignoredTools",label:"Ignored Tools",type:"array",group:"Filtering",liveApply:!0,restartRequired:!1},{key:"minOutputLength",label:"Min Output Length",type:"number",group:"Filtering",liveApply:!0,restartRequired:!1,min:0,max:1e4},{key:"maxObservations",label:"Max Observations",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:1,max:200},{key:"contextFullObservationCount",label:"Full Observation Count",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:0,max:20},{key:"contextShowTokenCosts",label:"Show Token Costs",type:"boolean",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1},{key:"sensitivePatterns",label:"Sensitive Patterns",type:"array",group:"Privacy",liveApply:!0,restartRequired:!1},{key:"retentionDays",label:"Retention Days",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:3650},{key:"maxDatabaseSizeMb",label:"Max Database Size (MB)",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:1e5},{key:"dashboardEnabled",label:"Dashboard Enabled",type:"boolean",group:"Dashboard",liveApply:!1,restartRequired:!0},{key:"dashboardPort",label:"Dashboard Port",type:"number",group:"Dashboard",liveApply:!1,restartRequired:!0,min:1,max:65535},{key:"platformOpenCodeEnabled",label:"OpenCode Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformClaudeCodeEnabled",label:"Claude Code Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformCursorEnabled",label:"Cursor Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpCompatibilityMode",label:"MCP Compatibility Mode",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0,enum:["strict","legacy"]},{key:"mcpProtocolVersion",label:"MCP Protocol Version",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpSupportedProtocolVersions",label:"MCP Supported Protocols",type:"array",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"rerankingEnabled",label:"Reranking Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"entityExtractionEnabled",label:"Entity Extraction Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"userMemoryEnabled",label:"User Memory Enabled",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"userMemoryMaxContextTokens",label:"User Memory Max Context Tokens",type:"number",group:"Advanced",liveApply:!0,restartRequired:!1,min:0,max:8000}],DM={dbPath:["OPEN_MEM_DB_PATH"],provider:["OPEN_MEM_PROVIDER"],model:["OPEN_MEM_MODEL"],compressionEnabled:["OPEN_MEM_COMPRESSION"],contextInjectionEnabled:["OPEN_MEM_CONTEXT_INJECTION"],maxContextTokens:["OPEN_MEM_MAX_CONTEXT_TOKENS"],ignoredTools:["OPEN_MEM_IGNORED_TOOLS"],batchSize:["OPEN_MEM_BATCH_SIZE"],retentionDays:["OPEN_MEM_RETENTION_DAYS"],contextShowTokenCosts:["OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS"],contextFullObservationCount:["OPEN_MEM_CONTEXT_FULL_COUNT"],maxObservations:["OPEN_MEM_MAX_OBSERVATIONS"],dashboardEnabled:["OPEN_MEM_DASHBOARD"],dashboardPort:["OPEN_MEM_DASHBOARD_PORT"],platformOpenCodeEnabled:["OPEN_MEM_PLATFORM_OPENCODE"],platformClaudeCodeEnabled:["OPEN_MEM_PLATFORM_CLAUDE_CODE"],platformCursorEnabled:["OPEN_MEM_PLATFORM_CURSOR"],mcpCompatibilityMode:["OPEN_MEM_MCP_COMPAT_MODE"],mcpProtocolVersion:["OPEN_MEM_MCP_PROTOCOL_VERSION"],mcpSupportedProtocolVersions:["OPEN_MEM_MCP_SUPPORTED_PROTOCOLS"],rerankingEnabled:["OPEN_MEM_RERANKING"],userMemoryEnabled:["OPEN_MEM_USER_MEMORY"]}});import{readFileSync as sM}from"fs";import{join as EN}from"path";import{parseArgs as MN}from"util";import{createInterface as u0}from"readline";import{z as T}from"zod";import{z as X}from"zod";var g=X.enum(["decision","bugfix","feature","refactor","discovery","change"]);function R(E,M={}){return{data:E,error:null,meta:M}}function F(E,M,N){return{data:null,error:{code:E,message:M,details:N},meta:{}}}var K={find:X.object({query:X.string().min(1),scope:X.enum(["project","user","all"]).optional().default("project"),types:X.array(g).optional(),limit:X.number().int().min(1).max(50).optional().default(10),cursor:X.string().optional(),include:X.object({snippets:X.boolean().optional(),scores:X.boolean().optional(),relations:X.boolean().optional()}).optional()}),history:X.object({limit:X.number().int().min(1).max(20).optional().default(5),cursor:X.string().optional(),sessionId:X.string().optional(),anchor:X.string().optional().describe("Observation ID to center the timeline around"),depthBefore:X.number().int().min(0).max(20).optional().default(5).describe("Number of observations to show before the anchor"),depthAfter:X.number().int().min(0).max(20).optional().default(5).describe("Number of observations to show after the anchor")}),get:X.object({ids:X.array(X.string()).min(1),includeHistory:X.boolean().optional().default(!1),limit:X.number().int().min(1).max(50).optional().default(10)}),create:X.object({title:X.string(),type:g,narrative:X.string(),concepts:X.array(X.string()).optional(),files:X.array(X.string()).optional(),importance:X.number().int().min(1).max(5).optional(),scope:X.enum(["project","user"]).optional().default("project")}),revise:X.object({id:X.string(),title:X.string().optional(),narrative:X.string().optional(),type:g.optional(),concepts:X.array(X.string()).optional(),importance:X.number().int().min(1).max(5).optional(),reason:X.string().optional()}),remove:X.object({id:X.string(),reason:X.string().optional()}),transferExport:X.object({scope:X.enum(["project"]).optional().default("project"),type:g.optional(),limit:X.number().int().min(1).optional(),format:X.enum(["json"]).optional().default("json")}),transferImport:X.object({payload:X.string(),mode:X.enum(["skip","merge","replace"]).optional().default("skip")}),maintenance:X.object({action:X.enum(["folderContextDryRun","folderContextClean","folderContextRebuild","folderContextPurge"])}),help:X.object({})};var p0="2024-11-05",v0=T.object({name:T.string().min(1),arguments:T.record(T.string(),T.unknown()).optional()});function g0(E){if(typeof E!=="object"||E===null)return!1;let M=E;return M.jsonrpc==="2.0"&&typeof M.method==="string"}function B(E){let N=T.toJSONSchema(E);return{type:"object",properties:N.properties??{},required:N.required??void 0,additionalProperties:!1}}function jE(E){return E.issues.map((M)=>{return`${M.path.length>0?M.path.join("."):"input"}: ${M.message}`}).join("; ")}class o{memoryEngine;version;compatibilityMode;protocolVersion;supportedProtocolVersions;initialized=!1;pendingOps=[];constructor(E){this.memoryEngine=E.memoryEngine,this.version=E.version,this.compatibilityMode=E.compatibilityMode??"strict",this.protocolVersion=E.protocolVersion??p0,this.supportedProtocolVersions=E.supportedProtocolVersions&&E.supportedProtocolVersions.length>0?E.supportedProtocolVersions:[this.protocolVersion]}start(){let E=u0({input:process.stdin,terminal:!1});E.on("line",(M)=>{let N=M.trim();if(!N)return;try{let _=JSON.parse(N);if(!g0(_)){this.send({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Request"}});return}this.handle(_)}catch{this.send({jsonrpc:"2.0",id:null,error:{code:-32700,message:"Parse error"}})}}),E.on("close",()=>{Promise.allSettled(this.pendingOps).then(()=>process.exit(0))})}handle(E){if(E.method==="notifications/initialized"){this.initialized=!0;return}if(E.id===void 0||E.id===null)return;if(E.method==="initialize"){this.handleInitialize(E);return}if(!this.initialized&&this.compatibilityMode==="strict"){this.send({jsonrpc:"2.0",id:E.id,error:{code:-32002,message:"Server not initialized"}});return}switch(E.method){case"tools/list":this.send({jsonrpc:"2.0",id:E.id,result:{tools:this.getToolDefinitions()}});return;case"tools/call":{let M=this.handleToolCall(E.id,E.params);this.pendingOps.push(M),M.finally(()=>{this.pendingOps=this.pendingOps.filter((N)=>N!==M)});return}case"ping":this.send({jsonrpc:"2.0",id:E.id,result:{}});return;default:this.send({jsonrpc:"2.0",id:E.id,error:{code:-32601,message:`Method not found: ${E.method}`}})}}handleInitialize(E){let M=typeof E.params?.protocolVersion==="string"?E.params.protocolVersion:this.protocolVersion;if(!this.supportedProtocolVersions.includes(M)){this.send({jsonrpc:"2.0",id:E.id??null,error:{code:-32602,message:`Unsupported protocol version: ${M}`,data:{supported:this.supportedProtocolVersions}}});return}this.initialized=!0,this.send({jsonrpc:"2.0",id:E.id??null,result:{protocolVersion:M,capabilities:{tools:{listChanged:!1}},serverInfo:{name:"open-mem",version:this.version}}})}getToolDefinitions(){return[{name:"mem-find",description:"Search past memories \u2014 decisions, discoveries, gotchas, and session history. Use to recall context from previous sessions before starting work.",inputSchema:B(K.find)},{name:"mem-history",description:"Browse session timeline and summaries. Use to understand what happened in recent sessions or drill into a specific session.",inputSchema:B(K.history)},{name:"mem-get",description:"Fetch full memory details by ID. Use after mem-find or mem-history to get complete narratives, facts, and file lists.",inputSchema:B(K.get)},{name:"mem-create",description:"Save an important observation to memory. Use for decisions + rationale, non-obvious gotchas, user preferences, or cross-session plans that auto-capture wouldn't understand the significance of.",inputSchema:B(K.create)},{name:"mem-revise",description:"Update an existing memory with a new revision. Use when a previous decision changed, a gotcha was resolved, or information became outdated.",inputSchema:B(K.revise)},{name:"mem-remove",description:"Tombstone an obsolete or incorrect memory. Use to clean up memories that are no longer accurate or relevant.",inputSchema:B(K.remove)},{name:"mem-export",description:"Export project memories as portable JSON for backup or transfer between machines.",inputSchema:B(K.transferExport)},{name:"mem-import",description:"Import memories from a JSON export. Skips duplicates by default.",inputSchema:B(K.transferImport)},{name:"mem-maintenance",description:"Run folder context maintenance \u2014 clean, rebuild, purge, or dry-run AGENTS.md files.",inputSchema:B(K.maintenance)},{name:"mem-help",description:"Show detailed memory workflow guidance including when to save, what to save, and memory type reference.",inputSchema:B(K.help)}]}async handleToolCall(E,M){let N=v0.safeParse(M??{});if(!N.success){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(F("VALIDATION_ERROR",jE(N.error)),null,2)}],isError:!0}});return}let _=N.data.name,J=N.data.arguments??{};try{let S=await this.executeTool(_,J);this.send({jsonrpc:"2.0",id:E,result:S})}catch(S){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(F("INTERNAL_ERROR",String(S)),null,2)}],isError:!0}})}}async executeTool(E,M){let N=async()=>{switch(E){case"mem-find":{let _=K.find.parse(M),J=await this.memoryEngine.search(_.query,{limit:_.limit,type:_.types?.[0]});return JSON.stringify(R({results:J}),null,2)}case"mem-history":{let _=K.history.parse(M);return JSON.stringify(R({items:await this.memoryEngine.timeline({limit:_.limit,sessionId:_.sessionId,anchor:_.anchor,depthBefore:_.depthBefore,depthAfter:_.depthAfter})}),null,2)}case"mem-get":{let _=K.get.parse(M);return JSON.stringify(R({observations:await this.memoryEngine.recall(_.ids,_.limit)}),null,2)}case"mem-create":{let _=K.create.parse(M),J=await this.memoryEngine.save({..._,sessionId:"mcp"});return JSON.stringify(J?R({observation:J}):F("CONFLICT","Unable to create memory"),null,2)}case"mem-revise":{let _=K.revise.parse(M),J=await this.memoryEngine.update(_);return JSON.stringify(J?R({previousId:_.id,newId:J.id,observation:J}):F("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-remove":{let _=K.remove.parse(M),J=await this.memoryEngine.delete([_.id]);return JSON.stringify(J>0?R({id:_.id,tombstoned:!0}):F("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-export":{let _=K.transferExport.parse(M),J=await this.memoryEngine.export("project",{type:_.type,limit:_.limit});return JSON.stringify(R({payload:J,format:_.format}),null,2)}case"mem-import":{let _=K.transferImport.parse(M),J=_.mode==="replace"?"overwrite":"skip-duplicates",S=await this.memoryEngine.import(_.payload,{mode:J});return JSON.stringify(R({imported:S.imported,skipped:S.skipped,mode:_.mode}),null,2)}case"mem-maintenance":{let _=K.maintenance.parse(M);if(_.action==="folderContextDryRun")return JSON.stringify(R(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(_.action==="folderContextClean")return JSON.stringify(R(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);if(_.action==="folderContextPurge")return JSON.stringify(R(await this.memoryEngine.maintainFolderContext("purge",!1)),null,2);return JSON.stringify(R(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"mem-help":return JSON.stringify(R({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(F("NOT_FOUND",`Unknown tool: ${E}`),null,2)}};try{let _=await N(),J=_.includes('"error": {')&&!_.includes('"error": null');return{content:[{type:"text",text:_}],isError:J}}catch(_){if(_ instanceof T.ZodError)return{content:[{type:"text",text:JSON.stringify(F("VALIDATION_ERROR",jE(_)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(F("INTERNAL_ERROR",String(_)),null,2)}],isError:!0}}}send(E){process.stdout.write(`${JSON.stringify(E)}
|
|
4
|
-
`)}}function
|
|
5
|
-
`)}function
|
|
6
|
-
**Read cost:** ~${M}t | **Discovery cost:** ~${N}t | **Savings:** ${
|
|
3
|
+
var w0=Object.defineProperty;var g0=(E,M)=>{for(var N in M)w0(E,N,{get:M[N],enumerable:!0,configurable:!0,set:(_)=>M[N]=()=>_})};var t=(E,M)=>()=>(E&&(M=E(E=0)),M);var D=import.meta.require;import{existsSync as o0,readdirSync as t0,readFileSync as e0}from"fs";import{join as xE}from"path";function s0(){if(P)return P;if(P=new Map,!o0(NE))return P;for(let E of t0(NE)){if(!E.endsWith(".json"))continue;try{let M=e0(xE(NE,E),"utf-8"),N=JSON.parse(M);if(N.id&&N.observationTypes&&N.conceptVocabulary)P.set(N.id,N)}catch{}}return P}function hE(){return[...s0().keys()].sort()}var NE,P=null;var uE=t(()=>{NE=xE(import.meta.dir,".")});import{existsSync as EM,readFileSync as MM}from"fs";function NM(){let E={};if(process.env.OPEN_MEM_DB_PATH)E.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)E.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)E.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)E.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")E.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")E.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)E.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_BATCH_SIZE)E.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)E.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)E.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")E.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)E.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)E.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)E.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")E.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")E.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")E.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)E.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")E.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")E.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)E.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")E.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")E.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)E.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")E.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")E.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")E.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)E.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)E.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)E.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)E.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")E.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(M))E.conflictSimilarityBandLow=M}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(M))E.conflictSimilarityBandHigh=M}if(process.env.OPEN_MEM_USER_MEMORY==="true")E.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)E.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)E.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")E.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)E.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")E.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)E.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)E.mode=process.env.OPEN_MEM_MODE;return E}function _M(E){let M=`${E}/.open-mem/config.json`;if(!EM(M))return{};try{let N=MM(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}function JM(E){switch(E){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function f(E,M){let N=_M(E),_=NM(),J={...fE,...N,..._,...M};if(!J.dbPath.startsWith("/"))J.dbPath=`${E}/${J.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!M?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)J.provider="google";else if(process.env.ANTHROPIC_API_KEY)J.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)J.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)J.provider="openrouter"}if(!J.apiKey)switch(J.provider){case"google":J.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":J.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":J.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":J.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(J.provider==="openrouter"&&J.model==="gemini-2.5-flash-lite")J.model="google/gemini-2.5-flash-lite";if(J.embeddingDimension===void 0)J.embeddingDimension=JM(J.provider);if(J.mode&&!hE().includes(J.mode))J.mode="code";return J}function _E(){return{...fE}}var fE;var JE=t(()=>{uE();fE={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"dispersed",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0,mode:"code"}});var O0={};g0(O0,{writeProjectConfig:()=>$0,validatePatch:()=>zE,readProjectConfig:()=>n,previewConfig:()=>uM,patchConfig:()=>fM,getEffectiveConfig:()=>w,getConfigSchema:()=>hM});import{existsSync as jM}from"fs";import{mkdir as TM,readFile as yM,writeFile as PM}from"fs/promises";import{dirname as mM,join as IM}from"path";function S0(E){return IM(E,".open-mem","config.json")}function A0(E){return V0.find((M)=>M.key===E)}function xM(E,M){let N=A0(E);if(!N)return null;if(N.type==="string"&&typeof M!=="string")return`${String(E)} must be a string`;if(N.type==="number"&&typeof M!=="number")return`${String(E)} must be a number`;if(N.type==="boolean"&&typeof M!=="boolean")return`${String(E)} must be a boolean`;if(N.type==="array"&&!Array.isArray(M))return`${String(E)} must be an array`;if(N.enum&&typeof M==="string"&&!N.enum.includes(M))return`${String(E)} must be one of: ${N.enum.join(", ")}`;if(typeof M==="number"){if(N.min!==void 0&&M<N.min)return`${String(E)} must be >= ${N.min}`;if(N.max!==void 0&&M>N.max)return`${String(E)} must be <= ${N.max}`}return null}function hM(){return V0}async function n(E){let M=S0(E);if(!jM(M))return{};try{let N=await yM(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}async function $0(E,M){let N=S0(E),J={...await n(E),...M};await TM(mM(N),{recursive:!0}),await PM(N,JSON.stringify(J,null,2),"utf-8")}function zE(E){let M=[];for(let[N,_]of Object.entries(E)){let V=xM(N,_);if(V)M.push(V)}return M}async function w(E){let M=_E(),N=await n(E),_=f(E),J=[],V={};for(let[S,A]of Object.entries(M)){let $=S,O=A0($),U=(qM[$]??[]).some((Q)=>typeof process.env[Q]==="string"),L=Object.hasOwn(N,$),z="default";if(L)z="file";if(U)z="env";if(V[$]={source:z,locked:U,restartRequired:O?.restartRequired??!1,liveApply:O?.liveApply??!1},z==="env"&&L)J.push(`${String($)} is overridden by environment variable.`);if(_[$]===void 0&&A!==void 0)J.push(`${String($)} resolved to undefined unexpectedly.`)}return{config:_,meta:V,warnings:J}}async function uM(E,M){let N=zE(M);if(N.length>0)return{...await w(E),warnings:N};let _=_E(),J=await n(E),V={..._,...J,...M},A={...f(E,M),...V},$=(await w(E)).meta;return{config:A,meta:$,warnings:[]}}async function fM(E,M){let N=zE(M);if(N.length>0)return{...await w(E),warnings:N};return await $0(E,M),w(E)}var V0,qM;var X0=t(()=>{JE();V0=[{key:"dbPath",label:"Database Path",type:"string",group:"Storage",liveApply:!1,restartRequired:!0},{key:"provider",label:"Provider",type:"string",group:"AI",liveApply:!1,restartRequired:!0,enum:["google","anthropic","openai","bedrock"]},{key:"model",label:"Model",type:"string",group:"AI",liveApply:!1,restartRequired:!0},{key:"maxTokensPerCompression",label:"Max Tokens Per Compression",type:"number",group:"AI",liveApply:!0,restartRequired:!1,min:128,max:8192},{key:"compressionEnabled",label:"Compression Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"contextInjectionEnabled",label:"Context Injection Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"maxContextTokens",label:"Max Context Tokens",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:500,max:64000},{key:"batchSize",label:"Batch Size",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1,max:100},{key:"batchIntervalMs",label:"Batch Interval (ms)",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1000,max:300000},{key:"ignoredTools",label:"Ignored Tools",type:"array",group:"Filtering",liveApply:!0,restartRequired:!1},{key:"minOutputLength",label:"Min Output Length",type:"number",group:"Filtering",liveApply:!0,restartRequired:!1,min:0,max:1e4},{key:"maxObservations",label:"Max Observations",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:1,max:200},{key:"contextFullObservationCount",label:"Full Observation Count",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:0,max:20},{key:"contextShowTokenCosts",label:"Show Token Costs",type:"boolean",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1},{key:"sensitivePatterns",label:"Sensitive Patterns",type:"array",group:"Privacy",liveApply:!0,restartRequired:!1},{key:"retentionDays",label:"Retention Days",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:3650},{key:"maxDatabaseSizeMb",label:"Max Database Size (MB)",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:1e5},{key:"dashboardEnabled",label:"Dashboard Enabled",type:"boolean",group:"Dashboard",liveApply:!1,restartRequired:!0},{key:"dashboardPort",label:"Dashboard Port",type:"number",group:"Dashboard",liveApply:!1,restartRequired:!0,min:1,max:65535},{key:"platformOpenCodeEnabled",label:"OpenCode Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformClaudeCodeEnabled",label:"Claude Code Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformCursorEnabled",label:"Cursor Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpCompatibilityMode",label:"MCP Compatibility Mode",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0,enum:["strict","legacy"]},{key:"mcpProtocolVersion",label:"MCP Protocol Version",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpSupportedProtocolVersions",label:"MCP Supported Protocols",type:"array",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"rerankingEnabled",label:"Reranking Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"entityExtractionEnabled",label:"Entity Extraction Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"userMemoryEnabled",label:"User Memory Enabled",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"userMemoryMaxContextTokens",label:"User Memory Max Context Tokens",type:"number",group:"Advanced",liveApply:!0,restartRequired:!1,min:0,max:8000}],qM={dbPath:["OPEN_MEM_DB_PATH"],provider:["OPEN_MEM_PROVIDER"],model:["OPEN_MEM_MODEL"],compressionEnabled:["OPEN_MEM_COMPRESSION"],contextInjectionEnabled:["OPEN_MEM_CONTEXT_INJECTION"],maxContextTokens:["OPEN_MEM_MAX_CONTEXT_TOKENS"],ignoredTools:["OPEN_MEM_IGNORED_TOOLS"],batchSize:["OPEN_MEM_BATCH_SIZE"],retentionDays:["OPEN_MEM_RETENTION_DAYS"],contextShowTokenCosts:["OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS"],contextFullObservationCount:["OPEN_MEM_CONTEXT_FULL_COUNT"],maxObservations:["OPEN_MEM_MAX_OBSERVATIONS"],dashboardEnabled:["OPEN_MEM_DASHBOARD"],dashboardPort:["OPEN_MEM_DASHBOARD_PORT"],platformOpenCodeEnabled:["OPEN_MEM_PLATFORM_OPENCODE"],platformClaudeCodeEnabled:["OPEN_MEM_PLATFORM_CLAUDE_CODE"],platformCursorEnabled:["OPEN_MEM_PLATFORM_CURSOR"],mcpCompatibilityMode:["OPEN_MEM_MCP_COMPAT_MODE"],mcpProtocolVersion:["OPEN_MEM_MCP_PROTOCOL_VERSION"],mcpSupportedProtocolVersions:["OPEN_MEM_MCP_SUPPORTED_PROTOCOLS"],rerankingEnabled:["OPEN_MEM_RERANKING"],userMemoryEnabled:["OPEN_MEM_USER_MEMORY"]}});import{readFileSync as $N}from"fs";import{join as ON}from"path";import{parseArgs as XN}from"util";import{createInterface as l0}from"readline";import{z as T}from"zod";import{z as Z}from"zod";var g=Z.enum(["decision","bugfix","feature","refactor","discovery","change"]);function Y(E,M={}){return{data:E,error:null,meta:M}}function F(E,M,N){return{data:null,error:{code:E,message:M,details:N},meta:{}}}var H={find:Z.object({query:Z.string().min(1),scope:Z.enum(["project","user","all"]).optional().default("project"),types:Z.array(g).optional(),limit:Z.number().int().min(1).max(50).optional().default(10),cursor:Z.string().optional(),include:Z.object({snippets:Z.boolean().optional(),scores:Z.boolean().optional(),relations:Z.boolean().optional()}).optional()}),history:Z.object({limit:Z.number().int().min(1).max(20).optional().default(5),cursor:Z.string().optional(),sessionId:Z.string().optional(),anchor:Z.string().optional().describe("Observation ID to center the timeline around"),depthBefore:Z.number().int().min(0).max(20).optional().default(5).describe("Number of observations to show before the anchor"),depthAfter:Z.number().int().min(0).max(20).optional().default(5).describe("Number of observations to show after the anchor")}),get:Z.object({ids:Z.array(Z.string()).min(1),includeHistory:Z.boolean().optional().default(!1),limit:Z.number().int().min(1).max(50).optional().default(10)}),create:Z.object({title:Z.string(),type:g,narrative:Z.string(),concepts:Z.array(Z.string()).optional(),files:Z.array(Z.string()).optional(),importance:Z.number().int().min(1).max(5).optional(),scope:Z.enum(["project","user"]).optional().default("project")}),revise:Z.object({id:Z.string(),title:Z.string().optional(),narrative:Z.string().optional(),type:g.optional(),concepts:Z.array(Z.string()).optional(),importance:Z.number().int().min(1).max(5).optional(),reason:Z.string().optional()}),remove:Z.object({id:Z.string(),reason:Z.string().optional()}),transferExport:Z.object({scope:Z.enum(["project"]).optional().default("project"),type:g.optional(),limit:Z.number().int().min(1).optional(),format:Z.enum(["json"]).optional().default("json")}),transferImport:Z.object({payload:Z.string(),mode:Z.enum(["skip","merge","replace"]).optional().default("skip")}),maintenance:Z.object({action:Z.enum(["folderContextDryRun","folderContextClean","folderContextRebuild","folderContextPurge"])}),help:Z.object({})};var c0="2024-11-05",b0=T.object({name:T.string().min(1),arguments:T.record(T.string(),T.unknown()).optional()});function n0(E){if(typeof E!=="object"||E===null)return!1;let M=E;return M.jsonrpc==="2.0"&&typeof M.method==="string"}function C(E){let N=T.toJSONSchema(E);return{type:"object",properties:N.properties??{},required:N.required??void 0,additionalProperties:!1}}function yE(E){return E.issues.map((M)=>{return`${M.path.length>0?M.path.join("."):"input"}: ${M.message}`}).join("; ")}class e{memoryEngine;version;compatibilityMode;protocolVersion;supportedProtocolVersions;initialized=!1;pendingOps=[];constructor(E){this.memoryEngine=E.memoryEngine,this.version=E.version,this.compatibilityMode=E.compatibilityMode??"strict",this.protocolVersion=E.protocolVersion??c0,this.supportedProtocolVersions=E.supportedProtocolVersions&&E.supportedProtocolVersions.length>0?E.supportedProtocolVersions:[this.protocolVersion]}start(){let E=l0({input:process.stdin,terminal:!1});E.on("line",(M)=>{let N=M.trim();if(!N)return;try{let _=JSON.parse(N);if(!n0(_)){this.send({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Request"}});return}this.handle(_)}catch{this.send({jsonrpc:"2.0",id:null,error:{code:-32700,message:"Parse error"}})}}),E.on("close",()=>{Promise.allSettled(this.pendingOps).then(()=>process.exit(0))})}handle(E){if(E.method==="notifications/initialized"){this.initialized=!0;return}if(E.id===void 0||E.id===null)return;if(E.method==="initialize"){this.handleInitialize(E);return}if(!this.initialized&&this.compatibilityMode==="strict"){this.send({jsonrpc:"2.0",id:E.id,error:{code:-32002,message:"Server not initialized"}});return}switch(E.method){case"tools/list":this.send({jsonrpc:"2.0",id:E.id,result:{tools:this.getToolDefinitions()}});return;case"tools/call":{let M=this.handleToolCall(E.id,E.params);this.pendingOps.push(M),M.finally(()=>{this.pendingOps=this.pendingOps.filter((N)=>N!==M)});return}case"ping":this.send({jsonrpc:"2.0",id:E.id,result:{}});return;default:this.send({jsonrpc:"2.0",id:E.id,error:{code:-32601,message:`Method not found: ${E.method}`}})}}handleInitialize(E){let M=typeof E.params?.protocolVersion==="string"?E.params.protocolVersion:this.protocolVersion;if(!this.supportedProtocolVersions.includes(M)){this.send({jsonrpc:"2.0",id:E.id??null,error:{code:-32602,message:`Unsupported protocol version: ${M}`,data:{supported:this.supportedProtocolVersions}}});return}this.initialized=!0,this.send({jsonrpc:"2.0",id:E.id??null,result:{protocolVersion:M,capabilities:{tools:{listChanged:!1}},serverInfo:{name:"open-mem",version:this.version}}})}getToolDefinitions(){return[{name:"mem-find",description:"Search past memories \u2014 decisions, discoveries, gotchas, and session history. Use to recall context from previous sessions before starting work.",inputSchema:C(H.find)},{name:"mem-history",description:"Browse session timeline and summaries. Use to understand what happened in recent sessions or drill into a specific session.",inputSchema:C(H.history)},{name:"mem-get",description:"Fetch full memory details by ID. Use after mem-find or mem-history to get complete narratives, facts, and file lists.",inputSchema:C(H.get)},{name:"mem-create",description:"Save an important observation to memory. Use for decisions + rationale, non-obvious gotchas, user preferences, or cross-session plans that auto-capture wouldn't understand the significance of.",inputSchema:C(H.create)},{name:"mem-revise",description:"Update an existing memory with a new revision. Use when a previous decision changed, a gotcha was resolved, or information became outdated.",inputSchema:C(H.revise)},{name:"mem-remove",description:"Tombstone an obsolete or incorrect memory. Use to clean up memories that are no longer accurate or relevant.",inputSchema:C(H.remove)},{name:"mem-export",description:"Export project memories as portable JSON for backup or transfer between machines.",inputSchema:C(H.transferExport)},{name:"mem-import",description:"Import memories from a JSON export. Skips duplicates by default.",inputSchema:C(H.transferImport)},{name:"mem-maintenance",description:"Run folder context maintenance \u2014 clean, rebuild, purge, or dry-run AGENTS.md files.",inputSchema:C(H.maintenance)},{name:"mem-help",description:"Show detailed memory workflow guidance including when to save, what to save, and memory type reference.",inputSchema:C(H.help)}]}async handleToolCall(E,M){let N=b0.safeParse(M??{});if(!N.success){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(F("VALIDATION_ERROR",yE(N.error)),null,2)}],isError:!0}});return}let _=N.data.name,J=N.data.arguments??{};try{let V=await this.executeTool(_,J);this.send({jsonrpc:"2.0",id:E,result:V})}catch(V){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(F("INTERNAL_ERROR",String(V)),null,2)}],isError:!0}})}}async executeTool(E,M){let N=async()=>{switch(E){case"mem-find":{let _=H.find.parse(M),J=await this.memoryEngine.search(_.query,{limit:_.limit,type:_.types?.[0]});return JSON.stringify(Y({results:J}),null,2)}case"mem-history":{let _=H.history.parse(M);return JSON.stringify(Y({items:await this.memoryEngine.timeline({limit:_.limit,sessionId:_.sessionId,anchor:_.anchor,depthBefore:_.depthBefore,depthAfter:_.depthAfter})}),null,2)}case"mem-get":{let _=H.get.parse(M);return JSON.stringify(Y({observations:await this.memoryEngine.recall(_.ids,_.limit)}),null,2)}case"mem-create":{let _=H.create.parse(M),J=await this.memoryEngine.save({..._,sessionId:"mcp"});return JSON.stringify(J?Y({observation:J}):F("CONFLICT","Unable to create memory"),null,2)}case"mem-revise":{let _=H.revise.parse(M),J=await this.memoryEngine.update(_);return JSON.stringify(J?Y({previousId:_.id,newId:J.id,observation:J}):F("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-remove":{let _=H.remove.parse(M),J=await this.memoryEngine.delete([_.id]);return JSON.stringify(J>0?Y({id:_.id,tombstoned:!0}):F("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-export":{let _=H.transferExport.parse(M),J=await this.memoryEngine.export("project",{type:_.type,limit:_.limit});return JSON.stringify(Y({payload:J,format:_.format}),null,2)}case"mem-import":{let _=H.transferImport.parse(M),J=_.mode==="replace"?"overwrite":"skip-duplicates",V=await this.memoryEngine.import(_.payload,{mode:J});return JSON.stringify(Y({imported:V.imported,skipped:V.skipped,mode:_.mode}),null,2)}case"mem-maintenance":{let _=H.maintenance.parse(M);if(_.action==="folderContextDryRun")return JSON.stringify(Y(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(_.action==="folderContextClean")return JSON.stringify(Y(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);if(_.action==="folderContextPurge")return JSON.stringify(Y(await this.memoryEngine.maintainFolderContext("purge",!1)),null,2);return JSON.stringify(Y(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"mem-help":return JSON.stringify(Y({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(F("NOT_FOUND",`Unknown tool: ${E}`),null,2)}};try{let _=await N(),J=_.includes('"error": {')&&!_.includes('"error": null');return{content:[{type:"text",text:_}],isError:J}}catch(_){if(_ instanceof T.ZodError)return{content:[{type:"text",text:JSON.stringify(F("VALIDATION_ERROR",yE(_)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(F("INTERNAL_ERROR",String(_)),null,2)}],isError:!0}}}send(E){process.stdout.write(`${JSON.stringify(E)}
|
|
4
|
+
`)}}function s(E){if(typeof E!=="object"||E===null)return!1;let M=E,N=M.status;if(N===429||N===500||N===503)return!0;let _=M.error;if(typeof _==="object"&&_!==null&&_.type==="overloaded_error")return!0;return!1}function EE(E){if(E&&typeof E==="object"){let M=E.status;if(typeof M==="number")return M===400||M===401||M===403}return!1}class ME{specificationVersion;provider;modelId;supportedUrls;providers;constructor(E){if(E.length===0)throw Error("At least one provider required");let M=E[0].model;this.specificationVersion=M.specificationVersion,this.provider=M.provider,this.modelId=M.modelId,this.supportedUrls=M.supportedUrls,this.providers=E}async doGenerate(E){let M;for(let N=0;N<this.providers.length;N++){let _=this.providers[N];try{return await _.model.doGenerate(E)}catch(J){if(M=J,EE(J))throw J;if(s(J)&&N<this.providers.length-1){let V=this.providers[N+1],S=J.status??"unknown";console.error(`[open-mem] Provider ${_.name} failed (${S}), falling over to ${V.name}`);continue}throw J}}throw M}async doStream(E){let M;for(let N=0;N<this.providers.length;N++){let _=this.providers[N];try{return await _.model.doStream(E)}catch(J){if(M=J,EE(J))throw J;if(s(J)&&N<this.providers.length-1){let V=this.providers[N+1],S=J.status??"unknown";console.error(`[open-mem] Provider ${_.name} failed (${S}), falling over to ${V.name}`);continue}throw J}}throw M}}var d0={"claude-sonnet-4-20250514":"us.anthropic.claude-sonnet-4-20250514-v1:0","claude-opus-4-20250514":"us.anthropic.claude-opus-4-20250514-v1:0","claude-3-5-sonnet-20241022":"us.anthropic.claude-3-5-sonnet-20241022-v2:0","claude-3-5-haiku-20241022":"us.anthropic.claude-3-5-haiku-20241022-v1:0","claude-3-haiku-20240307":"anthropic.claude-3-haiku-20240307-v1:0"};function i0(E){if(E.includes("."))return E;return d0[E]||`us.anthropic.${E}-v1:0`}function PE(E){switch(E.provider){case"anthropic":{let{createAnthropic:M}=D("@ai-sdk/anthropic");return M({apiKey:E.apiKey})(E.model)}case"bedrock":{let{createAmazonBedrock:M}=D("@ai-sdk/amazon-bedrock");return M()(i0(E.model))}case"openai":{let{createOpenAI:M}=D("@ai-sdk/openai");return M({apiKey:E.apiKey})(E.model)}case"google":{let{createGoogleGenerativeAI:M}=D("@ai-sdk/google");return M({apiKey:E.apiKey})(E.model)}case"openrouter":{let{createOpenRouter:M}=D("@openrouter/ai-sdk-provider");return M({apiKey:E.apiKey})(E.model)}default:throw Error(`Unknown provider: ${E.provider}. Supported: anthropic, bedrock, openai, google, openrouter`)}}function mE(E){try{switch(E.provider){case"google":{let{createGoogleGenerativeAI:M}=D("@ai-sdk/google");return M({apiKey:E.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:M}=D("@ai-sdk/openai");return M({apiKey:E.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:M}=D("@ai-sdk/amazon-bedrock");return M().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;case"openrouter":return null;default:return null}}catch{return null}}var r0={google:"gemini-2.5-flash-lite",anthropic:"claude-sonnet-4-20250514",openai:"gpt-4o-mini",bedrock:"us.anthropic.claude-3-5-haiku-20241022-v1:0",openrouter:"google/gemini-2.5-flash-lite"};function a0(E){switch(E){case"google":return process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;case"anthropic":return process.env.ANTHROPIC_API_KEY;case"openai":return process.env.OPENAI_API_KEY;case"openrouter":return process.env.OPENROUTER_API_KEY;case"bedrock":return;default:return}}function IE(E){if(!E.fallbackProviders||E.fallbackProviders.length===0)return[];return E.fallbackProviders.map((M)=>({provider:M,model:r0[M]??"gemini-2.5-flash-lite",apiKey:a0(M)}))}function qE(E,M=[]){let N=PE(E);if(M.length===0)return N;let _=[{name:E.provider,model:N},...M.map((J)=>({name:J.provider,model:PE(J)}))];return new ME(_)}JE();import{randomUUID as Z0}from"crypto";function VM(E,M){let N=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"i"),_=E.match(N);return _?_[1].trim():""}function SM(E,M){let N=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"gi"),_=[];for(let J of E.matchAll(N)){let V=J[1].trim();if(V)_.push(V)}return _}function vE(E){let M=VM(E,"reranked");if(!M)return null;let N=SM(M,"index");if(N.length===0)return null;let _=[];for(let J of N){let V=Number.parseInt(J,10);if(Number.isNaN(V)||V<0)return null;_.push(V)}return _}function k(E){return Math.ceil(E.length/4)}var AM={showTokenCosts:!0,observationTypes:"all",fullObservationCount:3,showLastSummary:!0},v={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"};function pE(E,M=AM){let N=[];if(N.push("## open-mem: Past Session Memory"),N.push(""),N.push("**\uD83D\uDCA1 Progressive Disclosure:** This is a compact index showing WHAT was observed and retrieval COST."),N.push("Use `mem-find` to find observations by query, then `mem-get` with IDs to fetch full details."),N.push(""),N.push("**3-Layer Memory Access:**"),N.push("- **Layer 1** `mem-find` \u2014 Find observations by query (returns IDs + summaries)"),N.push("- **Layer 2** `mem-history` \u2014 Browse session history and drill into sessions"),N.push("- **Layer 3** `mem-get` \u2014 Get full details by ID (use IDs from search results or the index below)"),N.push(""),N.push("**\uD83D\uDCDD When to Save (`mem-create`):** Proactively save decisions + rationale, non-obvious gotchas/workarounds, user preferences, and cross-session plans. Auto-capture handles tool executions \u2014 use `mem-create` for insights auto-capture can't understand the significance of. Wrap sensitive content in `<private>` tags to exclude from memory. Call `mem-help` for detailed guidance."),M.showLastSummary&&E.recentSummaries.length>0){N.push(""),N.push("### Recent Sessions"),N.push("| Session | Summary | Decisions |"),N.push("|---------|---------|-----------|");for(let S of E.recentSummaries){let A=S.keyDecisions.length>0?S.keyDecisions.join("; "):"\u2014";N.push(`| ${S.sessionId} | ${S.summary} | ${A} |`)}}let _=M.observationTypes==="all"?E.observationIndex:E.observationIndex.filter((S)=>M.observationTypes.includes(S.type));if(_.length>0){N.push(""),N.push(`### Recent Observations (${_.length} entries)`);let S=OM(_,E.fullObservations);for(let[A,$]of S){if(N.push(""),N.push(`**${A}**`),M.showTokenCosts)N.push("| ID | Type | Title | ~Tokens |"),N.push("|----|------|-------|---------|");else N.push("| ID | Type | Title |"),N.push("|----|------|-------|");for(let O of $){let X=v[O.type]||"\uD83D\uDCDD";if(M.showTokenCosts)N.push(`| ${O.id} | ${X} | ${O.title} | ~${O.tokenCount} |`);else N.push(`| ${O.id} | ${X} | ${O.title} |`)}}}let J=E.fullObservations.slice(0,M.fullObservationCount);if(J.length>0){N.push(""),N.push("### Full Details (most recent)");for(let S of J){let A=v[S.type]||"\uD83D\uDCDD";if(N.push(""),N.push(`#### ${A} ${S.title} (${S.id})`),N.push(S.narrative),S.facts.length>0)N.push(`**Facts:** ${S.facts.map((O)=>`- ${O}`).join(" ")}`);if(S.concepts.length>0)N.push(`**Concepts:** ${S.concepts.join(", ")}`);let $=[...S.filesRead,...S.filesModified];if($.length>0)N.push(`**Files:** ${$.join(", ")}`)}}let V=$M(E);if(V)N.push(""),N.push(V);return N.join(`
|
|
5
|
+
`)}function $M(E){let M=0,N=0,_=new Set(E.observationIndex.map((S)=>S.id));for(let S of E.observationIndex)M+=S.tokenCount,N+=S.discoveryTokens;for(let S of E.fullObservations)if(!_.has(S.id))M+=S.tokenCount,N+=S.discoveryTokens;if(N===0)return null;let J=N-M,V=Math.max(0,Math.round(J/N*100));return`### \uD83D\uDCB0 Memory Economics
|
|
6
|
+
**Read cost:** ~${M}t | **Discovery cost:** ~${N}t | **Savings:** ${V}% (${J}t saved)`}function OM(E,M){let N=new Map;for(let J of M){let V=J.filesModified[0]||J.filesRead[0];if(V)N.set(J.id,V)}let _=new Map;for(let J of E){let V=N.get(J.id)??"General",S=_.get(V)??[];S.push(J),_.set(V,S)}return _}function wE(E){let M=[];if(M.push("[open-mem] Memory context:"),E.recentSummaries.length>0){M.push(`
|
|
7
7
|
Recent sessions:`);for(let N of E.recentSummaries)M.push(`- ${N.summary}`)}if(E.observationIndex.length>0){M.push(`
|
|
8
|
-
Recent observations (${E.observationIndex.length} entries):`);for(let N of E.observationIndex)M.push(`- ${
|
|
9
|
-
`)}function
|
|
10
|
-
`)}function
|
|
11
|
-
Cross-project observations (${_.length} entries):`);for(let
|
|
12
|
-
`)}var
|
|
13
|
-
`);await
|
|
14
|
-
`)}async function
|
|
8
|
+
Recent observations (${E.observationIndex.length} entries):`);for(let N of E.observationIndex)M.push(`- ${v[N.type]||"\uD83D\uDCDD"} ${N.title}`)}return M.join(`
|
|
9
|
+
`)}function gE(E,M){if(E.length===0)return"";let N=M,_=[];for(let V of E){let S=V.tokenCount||k(V.title);if(N-S<0)break;_.push(V),N-=S}if(_.length===0)return"";let J=[];J.push("### Cross-Project Memory"),J.push(""),J.push("| ID | Type | Title | ~Tokens |"),J.push("|----|------|-------|---------|");for(let V of _){let S=v[V.type]||"\uD83D\uDCDD";J.push(`| ${V.id} | ${S} | ${V.title} | ~${V.tokenCount} |`)}return J.join(`
|
|
10
|
+
`)}function lE(E,M){if(E.length===0)return"";let N=M,_=[];for(let V of E){let S=V.tokenCount||k(V.title);if(N-S<0)break;_.push(V),N-=S}if(_.length===0)return"";let J=[];J.push(`
|
|
11
|
+
Cross-project observations (${_.length} entries):`);for(let V of _)J.push(`- ${v[V.type]||"\uD83D\uDCDD"} ${V.title}`);return J.join(`
|
|
12
|
+
`)}var l={recency:0.4,typeImportance:0.3,sessionAffinity:0.2,tokenEfficiency:0.1},XM={decision:1,bugfix:0.9,feature:0.8,refactor:0.6,discovery:0.5,change:0.4};function ZM(E,M){let N=new Date(E),J=(M.getTime()-N.getTime())/3600000;if(J<0)return 1;if(J<24)return 1;if(J<48)return 0.8;if(J<168)return 0.5;return 0.2}function UM(E){return XM[E]??0.3}function KM(E,M){if(!M)return 0.5;return E===M?1:0.3}function HM(E){if(E<=10)return 1;if(E>=200)return 0.2;return 1-(E-10)/190*0.8}function zM(E,M){let N=ZM(E.createdAt,M.now),_=UM(E.type),J=KM(E.sessionId,M.currentSessionId),V=HM(E.tokenCount);return N*l.recency+_*l.typeImportance+J*l.sessionAffinity+V*l.tokenEfficiency}function cE(E,M){let N=new Map;for(let _ of E)N.set(_.id,zM(_,M));return[...E].sort((_,J)=>{let V=N.get(_.id)??0,S=N.get(J.id)??0;if(S!==V)return S-V;return new Date(J.createdAt).getTime()-new Date(_.createdAt).getTime()})}function bE(E,M,N,_,J=[],V){let S=_,A=[],$=[];for(let X of M){let U=X.tokenCount||k(X.summary);if(S-U<0)break;A.push(X),S-=U}let O=V?cE(N,V):N;for(let X of O){let U=X.tokenCount||k(X.title);if(S-U<0)break;$.push(X),S-=U}return{recentSummaries:A,observationIndex:$,fullObservations:[...J],totalTokens:_-S}}import{existsSync as ZE}from"fs";import{readdir as kM,readFile as eE,unlink as XE,writeFile as sE}from"fs/promises";import{join as UE,resolve as KE}from"path";import{existsSync as dE}from"fs";import{mkdir as QM,readFile as WM,rename as YM,unlink as BM,writeFile as LM}from"fs/promises";import{dirname as c,isAbsolute as AE,join as p,normalize as RM,relative as $E,resolve as I,sep as VE}from"path";var m="<!-- open-mem-context -->",y="<!-- /open-mem-context -->",iE={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},nE=new Map,CM=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function rE(E,M,N){if(M.length===0)return;if(N.mode==="single")return GM(E,M,N);let{maxDepth:_,filename:J}=N,V=[];for(let $ of M){for(let O of $.filesModified)V.push(O);for(let O of $.filesRead)V.push(O)}let S=oE(V,E,_);if(S.size===0)return;let A=tE(M,S,E);for(let[$,O]of A)try{let X=DM($,O,E);await aE($,X,J)}catch(X){console.error(`[open-mem] Failed to update AGENTS.md in ${$}:`,X)}}async function GM(E,M,N){let{maxDepth:_,filename:J}=N,V=M.filter(SE);if(V.length===0)return;let S=[];for(let z of V){for(let Q of z.filesModified)S.push(Q);for(let Q of z.filesRead)S.push(Q)}let A=oE(S,E,_),$=tE(V,A,E),O=V.filter((z)=>{return[...z.filesModified,...z.filesRead].some((B)=>{if(!B)return!1;let j=AE(B)?B:p(E,B);return I(c(j))===I(E)})});if(O.length>0)$.set(I(E),O);if($.size===0)return;let X=[];X.push("## Project Activity (auto-generated by open-mem)"),X.push("");let U=[...$.entries()].map(([z,Q])=>({relPath:$E(E,z)||".",observations:Q})).sort((z,Q)=>z.relPath.localeCompare(Q.relPath));for(let{relPath:z,observations:Q}of U){let B=Q.filter(SE).sort((W,u)=>u.createdAt.localeCompare(W.createdAt)).slice(0,10);if(B.length===0)continue;X.push(`### ${z}/`),X.push("| ID | Type | Title | Date |"),X.push("|----|------|-------|------|");for(let W of B){let u=iE[W.type]||"\uD83D\uDCDD",v0=W.createdAt.split("T")[0],p0=W.title.replace(/\|/g,"\\|");X.push(`| ${W.id} | ${u} ${W.type} | ${p0} | ${v0} |`)}let j=new Set;for(let W of B)for(let u of W.concepts)j.add(u);if(j.size>0){let W=[...j].slice(0,10).join(", ");X.push(""),X.push(`**Key concepts:** ${W}`)}let G=B.filter((W)=>W.type==="decision").map((W)=>W.title);if(G.length>0)X.push(""),X.push(`**Recent decisions:** ${G.slice(0,5).join("; ")}`);X.push("")}X.push("\uD83D\uDCA1 *Use `mem-find` to search full details. Use `mem-create` to save important decisions.*");let L=X.join(`
|
|
13
|
+
`);await aE(E,L,J)}function SE(E){return!/^\w[\w-]*\s+execution$/i.test(E.title)}function DM(E,M,N){let _=[...M].filter(SE).sort((O,X)=>X.createdAt.localeCompare(O.createdAt)).slice(0,10),J=$E(N,E)||".",V=[];V.push(`## Recent Activity in \`${J}/\` (auto-generated by open-mem)`),V.push(""),V.push("| ID | Type | Title | Date |"),V.push("|----|------|-------|------|");for(let O of _){let X=iE[O.type]||"\uD83D\uDCDD",U=O.createdAt.split("T")[0],L=O.title.replace(/\|/g,"\\|");V.push(`| ${O.id} | ${X} ${O.type} | ${L} | ${U} |`)}let S=new Set;for(let O of _)for(let X of O.concepts)S.add(X);if(S.size>0){let O=[...S].slice(0,10).join(", ");V.push(""),V.push(`**Key concepts:** ${O}`)}let A=_.filter((O)=>O.type==="decision").map((O)=>O.title);if(A.length>0)V.push(""),V.push(`**Recent decisions:** ${A.slice(0,5).join("; ")}`);let $=_.filter((O)=>O.type==="decision"&&O.narrative).slice(0,3);if($.length>0){V.push(""),V.push("**Decision details:**");for(let O of $){let X=O.narrative.split(/[.!?]\s/)[0],U=X.length>120?`${X.slice(0,117)}...`:X;V.push(`- \u2696\uFE0F ${O.title}: ${U}`)}}return V.push(""),V.push("\uD83D\uDCA1 *Use `mem-find` to search full details across all sessions. Use `mem-create` to save important decisions.*"),V.join(`
|
|
14
|
+
`)}async function aE(E,M,N){if(!dE(E))return;let J=(nE.get(E)??Promise.resolve()).then(async()=>{let V=p(E,N),S=p(E,`.${N}.tmp`),A="";try{A=await WM(V,"utf-8")}catch{}let $=FM(A,M);try{await QM(c(S),{recursive:!0}),await LM(S,$,"utf-8"),await YM(S,V)}catch(O){try{await BM(S)}catch{}throw O}});return nE.set(E,J.catch(()=>{})),J}function FM(E,M){if(!E)return`${m}
|
|
15
15
|
${M}
|
|
16
16
|
${y}
|
|
17
|
-
`;let N=E.indexOf(m),_=E.indexOf(y);if(N!==-1&&_!==-1&&_>N){let
|
|
17
|
+
`;let N=E.indexOf(m),_=E.indexOf(y);if(N!==-1&&_!==-1&&_>N){let V=E.substring(0,N),S=E.substring(_+y.length);return`${V}${m}
|
|
18
18
|
${M}
|
|
19
|
-
${y}${
|
|
19
|
+
${y}${S}`}let J=E;if(N!==-1&&_===-1)J=J.replace(m,"").trim();else if(N===-1&&_!==-1)J=J.replace(y,"").trim();else if(N!==-1&&_!==-1&&_<=N)J=J.replace(y,"").replace(m,"").trim();return`${J}
|
|
20
20
|
|
|
21
21
|
${m}
|
|
22
22
|
${M}
|
|
23
23
|
${y}
|
|
24
|
-
`}function
|
|
25
|
-
`:""}if(M===-1&&N!==-1){let
|
|
26
|
-
`:""}if(N<=M){let
|
|
27
|
-
`:""}let _=E.slice(0,M).trimEnd(),J=E.slice(N+
|
|
24
|
+
`}function oE(E,M,N){let _=new Set,J=I(M);for(let V of E){if(!V||!V.trim())continue;if(V.startsWith("~")||V.startsWith("http"))continue;let S=AE(V)?V:p(M,V),A=c(S),$=I(A);if(!$.startsWith(J+VE)&&$!==J)continue;if($===J)continue;let O=$E(J,$);if(O.split(VE).length>N)continue;if(RM(O).split(VE).some((L)=>CM.has(L)))continue;if(!dE($))continue;_.add($)}return _}function tE(E,M,N){let _=new Map;for(let J of E){let V=[...J.filesModified,...J.filesRead],S=new Set;for(let A of V){if(!A)continue;let $=AE(A)?A:p(N,A),O=I(c($));if(M.has(O))S.add(O)}for(let A of S){let $=_.get(A)??[];$.push(J),_.set(A,$)}}return _}var OE="<!-- open-mem-context -->",b="<!-- /open-mem-context -->";async function M0(E,M,N){let _;try{_=await kM(E,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(let J of _){let V=String(J.name);if(V===".git"||V==="node_modules"||V===".open-mem"||V==="dist")continue;let S=UE(E,V);if(J.isDirectory())await M0(S,M,N);else if(J.isFile()&&V===M)N.push(S)}}async function HE(E,M){let N=KE(E),_=[];return await M0(N,M,_),_}function E0(E){let M=E.indexOf(OE),N=E.indexOf(b);if(M===-1&&N===-1)return E;if(M!==-1&&N===-1){let V=E.replace(OE,"").trim();return V?`${V}
|
|
25
|
+
`:""}if(M===-1&&N!==-1){let V=E.replace(b,"").trim();return V?`${V}
|
|
26
|
+
`:""}if(N<=M){let V=E.replace(OE,"").replace(b,"").trim();return V?`${V}
|
|
27
|
+
`:""}let _=E.slice(0,M).trimEnd(),J=E.slice(N+b.length).trimStart();if(!_&&!J)return"";if(!_)return`${J}
|
|
28
28
|
`;if(!J)return`${_}
|
|
29
29
|
`;return`${_}
|
|
30
30
|
|
|
31
31
|
${J}
|
|
32
|
-
`}async function
|
|
32
|
+
`}async function N0(E,M,N=!1){let _=await HE(E,M),J=0;for(let V of _){let S=await eE(V,"utf-8"),A=E0(S);if(A!==S){if(J+=1,!N)if(A==="")await XE(V);else await sE(V,A,"utf-8")}}if(M){let V=UE(KE(E),M);if(ZE(V))try{let S=await eE(V,"utf-8"),A=E0(S);if(A!==S){if(J+=1,!N)if(A==="")await XE(V);else await sE(V,A,"utf-8")}if(!_.includes(V))_.push(V)}catch{}}return{files:_,changed:J}}async function _0(E,M){let N=await HE(E,M);if(M){let J=UE(KE(E),M);if(ZE(J)&&!N.includes(J))N.push(J)}let _=0;for(let J of N)try{await XE(J),_++}catch{}return{deleted:_,files:N}}async function J0(E,M,N,_,J=!1){let S=M.getAll(E).flatMap(($)=>N.getBySession($.id));if(J){let $=new Set;for(let O of S)for(let X of[...O.filesRead,...O.filesModified])$.add(X);return{observations:S.length,filesTouched:$.size}}if(!ZE(E))return{observations:0,filesTouched:0};await rE(E,S,{maxDepth:_.maxDepth,mode:_.mode,filename:_.filename});let A=await HE(E,_.filename);return{observations:S.length,filesTouched:A.length}}class QE{observations;sessions;summaries;searchOrchestrator;projectPath;config;userObservationRepo;runtimeSnapshotProvider;configAuditStore;maintenanceHistoryStore;configAuditLogFallback=[];maintenanceLogFallback=[];constructor(E){this.observations=E.observations,this.sessions=E.sessions,this.summaries=E.summaries,this.searchOrchestrator=E.searchOrchestrator,this.projectPath=E.projectPath,this.config=E.config,this.userObservationRepo=E.userObservationRepo??null,this.runtimeSnapshotProvider=E.runtimeSnapshotProvider??null,this.configAuditStore=E.configAuditStore??null,this.maintenanceHistoryStore=E.maintenanceHistoryStore??null}getByIdIncludingArchived(E){let M=this.observations;return M.getByIdIncludingArchived?M.getByIdIncludingArchived(E):this.observations.getById(E)}listByProjectWithState(E){let M=this.observations;if(M.listByProject)return M.listByProject(this.projectPath,E);if(E.state!=="current")return[];return this.listObservations({limit:E.limit,offset:E.offset,type:E.type,sessionId:E.sessionId})}async ingest(E){}async processPending(E){return 0}async search(E,M={}){return this.searchOrchestrator.search(E,{type:M.type,limit:M.limit??10,projectPath:this.projectPath,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.after,createdBefore:M.before,concepts:M.concepts,files:M.files})}async timeline(E={}){if(E.anchor){let N=this.observations.getById(E.anchor);if(!N)return[];let _=E.depthBefore??5,J=E.depthAfter??5,V=this.observations.getAroundTimestamp(N.createdAt,_,J,this.projectPath),S=[...V.filter(($)=>$.createdAt<N.createdAt),N,...V.filter(($)=>$.createdAt>N.createdAt)];return[{session:this.sessions.getById(N.sessionId)??{id:N.sessionId,projectPath:this.projectPath,startedAt:N.createdAt,endedAt:null,status:"completed",observationCount:0,summaryId:null},summary:null,observations:S}]}if(E.sessionId){let N=this.sessions.getById(E.sessionId);if(!N)return[];return[{session:N,summary:this.summaries.getBySessionId(N.id),observations:this.observations.getBySession(N.id)}]}return this.sessions.getRecent(this.projectPath,E.limit??5).map((N)=>({session:N,summary:this.summaries.getBySessionId(N.id),observations:[]}))}async recall(E,M=10){let N=[];for(let _ of E.slice(0,M)){let J=this.observations.getById(_);if(J){N.push(J);continue}if(!this.userObservationRepo)continue;let V=this.userObservationRepo.getById(_);if(!V)continue;N.push({...V,sessionId:"",rawToolOutput:"",discoveryTokens:0})}return N}async save(E){if(E.scope==="user"){if(!this.userObservationRepo)return null;return{...this.userObservationRepo.create({type:E.type,title:E.title,subtitle:"",facts:[],narrative:E.narrative,concepts:E.concepts??[],filesRead:[],filesModified:E.files??[],toolName:"mem-create",tokenCount:k(`${E.title} ${E.narrative}`),importance:E.importance??3,sourceProject:this.projectPath}),sessionId:"",rawToolOutput:"",discoveryTokens:0}}this.sessions.getOrCreate(E.sessionId,this.projectPath);let M=this.observations.create({sessionId:E.sessionId,type:E.type,title:E.title,subtitle:"",facts:[],narrative:E.narrative,concepts:E.concepts??[],filesRead:[],filesModified:E.files??[],rawToolOutput:`[Manual save] ${E.narrative}`,toolName:"mem-create",tokenCount:k(`${E.title} ${E.narrative}`),discoveryTokens:0,importance:E.importance??3});return this.sessions.incrementObservationCount(E.sessionId),M}async update(E){let M=this.observations.getById(E.id);if(!M)return null;let N=this.sessions.getById(M.sessionId);if(!N||N.projectPath!==this.projectPath)return null;let{id:_,...J}=E;return this.observations.update(E.id,J)??null}async delete(E){let M=0;for(let N of E){let _=this.observations.getById(N);if(!_)continue;let J=this.sessions.getById(_.sessionId);if(!J||J.projectPath!==this.projectPath)continue;if(this.observations.delete(N))M+=1}return M}async export(E,M={}){if(E!=="project")throw Error("Only project scope export is supported.");let N=this.sessions.getAll(this.projectPath),_=[];for(let A of N)_.push(...this.observations.getBySession(A.id));if(M.type)_=_.filter((A)=>A.type===M.type);if(_.sort((A,$)=>new Date(A.createdAt).getTime()-new Date($.createdAt).getTime()),M.limit&&M.limit<_.length)_=_.slice(0,M.limit);let J=_.map(({rawToolOutput:A,...$})=>$),V=N.map((A)=>this.summaries.getBySessionId(A.id)).filter((A)=>A!==null);return{version:1,exportedAt:new Date().toISOString(),project:this.projectPath,observations:J,summaries:V}}async import(E,M={}){let N;try{N=JSON.parse(E)}catch{throw Error("Invalid JSON payload.")}if(typeof N!=="object"||N===null)throw Error("Invalid import payload.");let _=N;if(_.version!==1||!Array.isArray(_.observations))throw Error("Unsupported export format.");let J=M.mode??"skip-duplicates",V=0,S=0;for(let A of _.observations){let $=this.observations.getById(A.id);if($&&J==="skip-duplicates"){S+=1;continue}if($&&J==="overwrite")this.observations.delete(A.id);this.sessions.getOrCreate(A.sessionId,this.projectPath),this.observations.importObservation({id:A.id,sessionId:A.sessionId,type:A.type,title:A.title,subtitle:A.subtitle??"",facts:A.facts??[],narrative:A.narrative??"",concepts:A.concepts??[],filesRead:A.filesRead??[],filesModified:A.filesModified??[],rawToolOutput:A.rawToolOutput??"",toolName:A.toolName??"unknown",createdAt:A.createdAt,tokenCount:A.tokenCount??0,discoveryTokens:A.discoveryTokens??0,importance:A.importance??3,supersededBy:A.supersededBy??null,supersededAt:A.supersededAt??null}),this.sessions.incrementObservationCount(A.sessionId),V+=1}for(let A of _.summaries??[]){let $=this.summaries.getBySessionId(A.sessionId);if($&&J==="skip-duplicates")continue;if($&&J==="overwrite")continue;this.sessions.getOrCreate(A.sessionId,this.projectPath),this.summaries.importSummary(A),this.sessions.setSummary(A.sessionId,A.id)}return{imported:V,skipped:S}}async buildContext(E,M="normal"){let N=this.sessions.getRecent(this.projectPath,5),_=N.map((X)=>X.summaryId?this.summaries.getBySessionId(X.id):null).filter((X)=>X!==null),J=this.observations.getIndex(this.projectPath,this.config.maxObservations),S=J.slice(0,this.config.contextFullObservationCount).map((X)=>X.id).map((X)=>this.observations.getById(X)).filter((X)=>X!==null),A=bE(N,_,J,this.config.maxContextTokens,S);if(M==="compaction"){let X=wE(A);if(this.config.userMemoryEnabled&&this.userObservationRepo)X+=lE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);return X}let $={showTokenCosts:this.config.contextShowTokenCosts,observationTypes:this.config.contextObservationTypes,fullObservationCount:this.config.contextFullObservationCount,showLastSummary:this.config.contextShowLastSummary},O=pE(A,$);if(this.config.userMemoryEnabled&&this.userObservationRepo){let X=gE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);if(X)O+=`
|
|
33
33
|
|
|
34
|
-
${
|
|
35
|
-
`)}listObservations(E){let{limit:M=50,offset:N=0,type:_,sessionId:J,state:
|
|
34
|
+
${X}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memories","1. `mem-find` \u2014 Search by query (returns IDs + summaries)","2. `mem-history` \u2014 Browse session timeline and summaries","3. `mem-get` \u2014 Fetch full details by ID (from find/history results)","","## When to Save (`mem-create`)","Save when the information is **stable, reusable, and non-obvious**:",'- Architectural decisions + rationale ("chose X over Y because...")',"- Non-obvious gotchas or workarounds discovered","- User preferences and conventions","- Cross-session plans or migration progress",'- Environment constraints ("Bedrock requires tool names matching [a-zA-Z0-9_-]+")',"","## When NOT to Save","Auto-capture already handles tool executions. Don't manually save:","- Ephemeral logs or one-off command outputs","- Information already visible in code or config files","- Routine file reads or edits (auto-captured)","","## Memory Types","- `decision` \u2014 Architectural choices with rationale","- `discovery` \u2014 Non-obvious findings, gotchas, constraints","- `bugfix` \u2014 Bug root causes and fixes","- `feature` \u2014 Feature implementations and design notes","- `refactor` \u2014 Refactoring rationale and approach","- `change` \u2014 General changes worth remembering","","## Editing & Cleanup","- `mem-revise` \u2014 Update outdated memories with new revisions","- `mem-remove` \u2014 Tombstone obsolete or incorrect memories","","## Privacy","Wrap sensitive content in `<private>` tags to exclude from memory.","","## Transfer","- `mem-export` \u2014 Backup/portability as JSON","- `mem-import` \u2014 Restore from JSON export"].join(`
|
|
35
|
+
`)}listObservations(E){let{limit:M=50,offset:N=0,type:_,sessionId:J,state:V}=E;if(V)return this.listByProjectWithState({limit:M,offset:N,type:_,state:V,sessionId:J});if(J){let $=this.observations.getBySession(J);if(_)$=$.filter((O)=>O.type===_);return $.slice(N,N+M)}let A=this.observations.getIndex(this.projectPath,N+M).slice(N);if(_)A=A.filter(($)=>$.type===_);return A.map(($)=>this.observations.getById($.id)).filter(($)=>$!==null)}getObservation(E){return this.observations.getById(E)}getLineage(E){let N=this.getByIdIncludingArchived(E);if(!N)return null;let _=N,J=0,V=new Set([N.id]);while(_.revisionOf&&J<256){let X=this.getByIdIncludingArchived(_.revisionOf);if(!X||V.has(X.id))break;_=X,V.add(X.id),J+=1}let S=[],A=_,$=new Set,O=0;while(A&&!$.has(A.id)&&O<256){$.add(A.id);let X=A.deletedAt?"tombstoned":A.supersededBy?"superseded":"current";S.push({id:A.id,revisionOf:A.revisionOf??null,supersededBy:A.supersededBy??null,supersededAt:A.supersededAt??null,deletedAt:A.deletedAt??null,state:X,observation:A}),A=A.supersededBy?this.getByIdIncludingArchived(A.supersededBy):null,O+=1}return S}listSessions(E){return this.sessions.getRecent(E.projectPath??this.projectPath,E.limit??20)}getSession(E){let M=this.sessions.getById(E);if(!M)return null;return{session:M,summary:this.summaries.getBySessionId(E),observations:this.observations.getBySession(E)}}stats(){let E=this.observations.getCount(),N=this.sessions.getAll(this.projectPath).length,_=this.observations.getIndex(this.projectPath,1e4),J=0,V=0,S={};for(let O of _)J+=O.tokenCount,V+=O.discoveryTokens,S[O.type]=(S[O.type]||0)+1;let A=V-J,$=_.length>0?Math.round(J/_.length):0;return{totalObservations:E,totalSessions:N,totalTokensSaved:A,averageObservationSize:$,typeBreakdown:S}}async maintainFolderContext(E,M){if(E==="purge")return{action:"purge",dryRun:!1,...await _0(this.projectPath,this.config.folderContextFilename)};if(E==="rebuild"){let _=await J0(this.projectPath,this.sessions,this.observations,{maxDepth:this.config.folderContextMaxDepth,mode:this.config.folderContextMode,filename:this.config.folderContextFilename},M);return{action:E,dryRun:M,..._}}let N=await N0(this.projectPath,this.config.folderContextFilename,M);return{action:"clean",dryRun:M,...N}}getRevisionDiff(E,M){let N=this.getByIdIncludingArchived(E),_=this.getByIdIncludingArchived(M);if(!N||!_)return null;let J=[],V=(A,$,O)=>{if(JSON.stringify($)!==JSON.stringify(O))J.push({field:A,before:$,after:O})};V("title",_.title,N.title),V("subtitle",_.subtitle,N.subtitle),V("narrative",_.narrative,N.narrative),V("type",_.type,N.type),V("facts",_.facts,N.facts),V("concepts",_.concepts,N.concepts),V("filesRead",_.filesRead,N.filesRead),V("filesModified",_.filesModified,N.filesModified),V("importance",_.importance,N.importance);let S=J.length===0?"No material changes between revisions.":`Changed ${J.length} field${J.length===1?"":"s"}: ${J.map((A)=>A.field).join(", ")}.`;return{fromId:M,toId:E,summary:S,changedFields:J}}getHealth(){let E=this.runtimeSnapshotProvider?.(),M=E&&E.queue.lastError?"degraded":"ok";return{status:E?.status??"ok",timestamp:E?.timestamp??new Date().toISOString(),components:{database:{status:"ok"},search:{status:"ok"},config:{status:"ok"},queue:{status:M,detail:E?.queue.lastError??void 0}}}}getMetrics(){let E=this.stats();return{timestamp:this.runtimeSnapshotProvider?.()?.timestamp??new Date().toISOString(),memory:{totalObservations:E.totalObservations,totalSessions:E.totalSessions,totalTokensSaved:E.totalTokensSaved,averageObservationSize:E.averageObservationSize}}}getPlatforms(){return{name:"open-mem",provider:this.config.provider,dashboardEnabled:this.config.dashboardEnabled,vectorEnabled:Boolean(this.config.embeddingDimension&&this.config.embeddingDimension>0)}}getAdapterStatuses(){let E={opencode:this.config.platformOpenCodeEnabled??!0,"claude-code":this.config.platformClaudeCodeEnabled??!1,cursor:this.config.platformCursorEnabled??!1};return[{name:"opencode",version:"1.0",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!1}},{name:"claude-code",version:"0.1",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}},{name:"cursor",version:"0.1",capabilities:{nativeSessionLifecycle:!1,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}}].map((N)=>({name:N.name,version:N.version,enabled:E[N.name]??!1,capabilities:N.capabilities}))}getConfigAuditTimeline(){if(this.configAuditStore)return this.configAuditStore.list();return[...this.configAuditLogFallback].reverse()}trackConfigAudit(E){if(this.configAuditStore){this.configAuditStore.append(E);return}this.configAuditLogFallback.push(E)}async rollbackConfig(E){let M=this.configAuditStore?this.configAuditStore.getById(E):this.configAuditLogFallback.find((V)=>V.id===E)??null;if(!M)return null;if(!M.previousValues||typeof M.previousValues!=="object")return null;let{patchConfig:N}=await Promise.resolve().then(() => (X0(),O0)),_=M.previousValues;try{await N(this.projectPath,_)}catch(V){let S={id:`rollback-failed-${Z0()}`,timestamp:new Date().toISOString(),patch:M.previousValues,previousValues:M.patch,source:"rollback-failed"};throw this.trackConfigAudit(S),V}let J={id:`rollback-${Z0()}`,timestamp:new Date().toISOString(),patch:M.previousValues,previousValues:M.patch,source:"rollback"};return this.trackConfigAudit(J),J}getMaintenanceHistory(){if(this.maintenanceHistoryStore)return this.maintenanceHistoryStore.list();return[...this.maintenanceLogFallback].reverse()}trackMaintenanceResult(E){if(this.maintenanceHistoryStore){this.maintenanceHistoryStore.append(E);return}this.maintenanceLogFallback.push(E)}}function d(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class WE{db;constructor(E){this.db=E}list(){return this.db.all("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events ORDER BY timestamp DESC").map((E)=>({id:E.id,timestamp:E.timestamp,patch:d(E.patch),previousValues:d(E.previous_values),source:E.source}))}getById(E){let M=this.db.get("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events WHERE id = ?",[E]);if(!M)return null;return{id:M.id,timestamp:M.timestamp,patch:d(M.patch),previousValues:d(M.previous_values),source:M.source}}append(E){this.db.run("INSERT INTO config_audit_events (id, timestamp, patch, previous_values, source) VALUES (?, ?, ?, ?, ?)",[E.id,E.timestamp,JSON.stringify(E.patch??{}),JSON.stringify(E.previousValues??{}),E.source])}}import{Database as U0}from"bun:sqlite";import{existsSync as YE,mkdirSync as vM,unlinkSync as K0}from"fs";import*as H0 from"sqlite-vec";class i{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let E=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let M of E)try{if(YE(M))return U0.setCustomSQLite(M),!0}catch{return!1}return!1}constructor(E){this.dbPath=E,this.db=this.open(E),this.configure()}open(E){let M=E.lastIndexOf("/");if(M>0){let N=E.substring(0,M);vM(N,{recursive:!0})}return new U0(E,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(E){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",E.message);try{this.db.close()}catch{}this.deleteSidecarFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after removing WAL/SHM files");return}catch(M){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",M.message);try{this.db.close()}catch{}this.deleteDatabaseFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after full database recreation");return}catch(N){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",N.message),E}}}}applyPragmas(){this.db.exec("PRAGMA journal_mode = WAL"),this.db.exec("PRAGMA synchronous = NORMAL"),this.db.exec("PRAGMA foreign_keys = ON"),this.db.exec("PRAGMA busy_timeout = 5000")}loadExtensions(){try{H0.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let E of["-wal","-shm"]){let M=this.dbPath+E;try{if(YE(M))K0(M)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(YE(this.dbPath))K0(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
|
|
36
36
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
37
37
|
version INTEGER PRIMARY KEY,
|
|
38
38
|
name TEXT NOT NULL,
|
|
39
39
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
40
40
|
)
|
|
41
|
-
`)}migrate(E){this.ensureMigrationTable();let M=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),N=new Set(M.map((J)=>J.version)),_=E.filter((J)=>!N.has(J.version)).sort((J,
|
|
41
|
+
`)}migrate(E){this.ensureMigrationTable();let M=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),N=new Set(M.map((J)=>J.version)),_=E.filter((J)=>!N.has(J.version)).sort((J,V)=>J.version-V.version);for(let J of _)this.db.transaction(()=>{this.db.exec(J.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:J.version,$name:J.name})})()}run(E,M){let N=this.db.query(E);if(M)N.run(...M);else N.run()}get(E,M){let N=this.db.query(E);return M?N.get(...M):N.get()}all(E,M){let N=this.db.query(E);return M?N.all(...M):N.all()}exec(E){this.db.exec(E)}transaction(E){return this.db.transaction(E)()}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function r(E){return new i(E)}import{randomUUID as z0}from"crypto";class BE{db;constructor(E){this.db=E}upsertEntity(E,M){let N=z0(),_=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
|
|
42
42
|
VALUES (?, ?, ?, ?, ?, 1)
|
|
43
43
|
ON CONFLICT(name, entity_type) DO UPDATE SET
|
|
44
44
|
mention_count = mention_count + 1,
|
|
45
|
-
last_seen_at = ?`,[N,E,M,_,_,_]);let J=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[E,M]);if(!J)throw Error(`Failed to upsert entity: ${E} (${M})`);return this.mapEntityRow(J)}createRelation(E,M,N,_){let J=
|
|
45
|
+
last_seen_at = ?`,[N,E,M,_,_,_]);let J=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[E,M]);if(!J)throw Error(`Failed to upsert entity: ${E} (${M})`);return this.mapEntityRow(J)}createRelation(E,M,N,_){let J=z0(),V=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
|
|
46
46
|
(id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
|
|
47
|
-
VALUES (?, ?, ?, ?, ?, ?)`,[J,E,M,N,_,
|
|
48
|
-
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[E,M,N]);return
|
|
47
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[J,E,M,N,_,V])}catch{return null}let S=this.db.get(`SELECT * FROM entity_relations
|
|
48
|
+
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[E,M,N]);return S?this.mapRelationRow(S):null}linkObservation(E,M){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[E,M])}findByName(E){try{return this.db.all(`SELECT e.*
|
|
49
49
|
FROM entities e
|
|
50
50
|
JOIN entities_fts fts ON e._rowid = fts.rowid
|
|
51
51
|
WHERE entities_fts MATCH ?
|
|
52
52
|
ORDER BY rank`,[E]).map((N)=>this.mapEntityRow(N))}catch{return[]}}getRelationsFor(E){return this.db.all(`SELECT * FROM entity_relations
|
|
53
|
-
WHERE source_entity_id = ? OR target_entity_id = ?`,[E,E]).map((N)=>this.mapRelationRow(N))}traverseRelations(E,M=1){let N=Math.min(M,2),_=100,J=new Set,
|
|
53
|
+
WHERE source_entity_id = ? OR target_entity_id = ?`,[E,E]).map((N)=>this.mapRelationRow(N))}traverseRelations(E,M=1){let N=Math.min(M,2),_=100,J=new Set,V=[{id:E,currentDepth:0}];J.add(E);while(V.length>0){if(J.size>=100)break;let S=V.shift();if(!S)continue;if(S.currentDepth>=N)continue;let A=this.getRelationsFor(S.id);for(let $ of A){let O=$.sourceEntityId===S.id?$.targetEntityId:$.sourceEntityId;if(!J.has(O))J.add(O),V.push({id:O,currentDepth:S.currentDepth+1})}}return J}getObservationsForEntity(E){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[E]).map((N)=>N.observation_id)}getById(E){let M=this.db.get("SELECT * FROM entities WHERE id = ?",[E]);return M?this.mapEntityRow(M):null}mapEntityRow(E){return{id:E.id,name:E.name,entityType:E.entity_type,firstSeenAt:E.first_seen_at,lastSeenAt:E.last_seen_at,mentionCount:E.mention_count}}mapRelationRow(E){return{id:E.id,sourceEntityId:E.source_entity_id,targetEntityId:E.target_entity_id,relationship:E.relationship,observationId:E.observation_id,createdAt:E.created_at}}}function pM(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class LE{db;constructor(E){this.db=E}list(){return this.db.all("SELECT id, timestamp, action, dry_run, result FROM maintenance_history ORDER BY timestamp DESC").map((E)=>({id:E.id,timestamp:E.timestamp,action:E.action,dryRun:E.dry_run===1,result:pM(E.result)}))}append(E){this.db.run("INSERT INTO maintenance_history (id, timestamp, action, dry_run, result) VALUES (?, ?, ?, ?, ?)",[E.id,E.timestamp,E.action,E.dryRun?1:0,JSON.stringify(E.result??{})])}}import{randomUUID as gM}from"crypto";import{embed as wM}from"ai";async function a(E,M){try{let{embedding:N}=await wM({model:E,value:M});return N}catch{return null}}function q(E,M){if(E.length!==M.length||E.length===0)return 0;let N=0,_=0,J=0;for(let S=0;S<E.length;S++)N+=E[S]*M[S],_+=E[S]*E[S],J+=M[S]*M[S];let V=Math.sqrt(_)*Math.sqrt(J);if(V===0)return 0;return N/V}function lM(E){return E.replace(/[%_\\]/g,"\\$&")}class RE{db;constructor(E){this.db=E}create(E){let M=gM(),N=new Date().toISOString(),_=E.discoveryTokens??0,J=E.importance??3,V=E.scope??"project";return this.db.run(`INSERT INTO observations
|
|
54
54
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
55
55
|
concepts, files_read, files_modified, raw_tool_output,
|
|
56
56
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
57
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,
|
|
57
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,V,E.type,E.title,E.subtitle,JSON.stringify(E.facts),E.narrative,JSON.stringify(E.concepts),JSON.stringify(E.filesRead),JSON.stringify(E.filesModified),E.rawToolOutput,E.toolName,N,E.tokenCount,_,J,null,null]),{...E,id:M,scope:V,createdAt:N,discoveryTokens:_,importance:J,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(E){this.db.run(`INSERT INTO observations
|
|
58
58
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
59
59
|
concepts, files_read, files_modified, raw_tool_output,
|
|
60
60
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
@@ -69,23 +69,23 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
69
69
|
WHERE s.project_path = ? AND o.created_at < ?
|
|
70
70
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
71
71
|
ORDER BY o.created_at DESC
|
|
72
|
-
LIMIT ?`,[_,E,M]).reverse():[],
|
|
72
|
+
LIMIT ?`,[_,E,M]).reverse():[],V=N>0?this.db.all(`SELECT o.*
|
|
73
73
|
FROM observations o
|
|
74
74
|
JOIN sessions s ON o.session_id = s.id
|
|
75
75
|
WHERE s.project_path = ? AND o.created_at > ?
|
|
76
76
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
77
77
|
ORDER BY o.created_at ASC
|
|
78
|
-
LIMIT ?`,[_,E,N]):[];return[...J,...
|
|
78
|
+
LIMIT ?`,[_,E,N]):[];return[...J,...V].map((S)=>this.mapRow(S))}listByProject(E,M={}){let{limit:N=50,offset:_=0,type:J,state:V,sessionId:S}=M,A=`SELECT o.*
|
|
79
79
|
FROM observations o
|
|
80
80
|
JOIN sessions s ON o.session_id = s.id
|
|
81
|
-
WHERE s.project_path = ?`,$=[E];if(
|
|
81
|
+
WHERE s.project_path = ?`,$=[E];if(S)A+=" AND o.session_id = ?",$.push(S);if(J)A+=" AND o.type = ?",$.push(J);if(V==="current")A+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(V==="superseded")A+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(V==="tombstoned")A+=" AND o.deleted_at IS NOT NULL";else A+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return A+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",$.push(N,_),this.db.all(A,$).map((O)=>this.mapRow(O))}search(E){let M=!!E.projectPath,N=`
|
|
82
82
|
SELECT o.*, rank
|
|
83
83
|
FROM observations o
|
|
84
84
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
85
85
|
${M?"JOIN sessions s ON o.session_id = s.id":""}
|
|
86
86
|
WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
87
|
-
`,_=[E.query];if(M&&E.projectPath)N+=" AND s.project_path = ?",_.push(E.projectPath);if(E.sessionId)N+=" AND o.session_id = ?",_.push(E.sessionId);if(E.type)N+=" AND o.type = ?",_.push(E.type);if(E.importanceMin!==void 0)N+=" AND o.importance >= ?",_.push(E.importanceMin);if(E.importanceMax!==void 0)N+=" AND o.importance <= ?",_.push(E.importanceMax);if(E.createdAfter)N+=" AND o.created_at >= ?",_.push(E.createdAfter);if(E.createdBefore)N+=" AND o.created_at <= ?",_.push(E.createdBefore);if(E.concepts&&E.concepts.length>0){let J=E.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");N+=` AND (${J.join(" OR ")})`;for(let
|
|
88
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);N+=` AND (${J.join(" OR ")})`;for(let
|
|
87
|
+
`,_=[E.query];if(M&&E.projectPath)N+=" AND s.project_path = ?",_.push(E.projectPath);if(E.sessionId)N+=" AND o.session_id = ?",_.push(E.sessionId);if(E.type)N+=" AND o.type = ?",_.push(E.type);if(E.importanceMin!==void 0)N+=" AND o.importance >= ?",_.push(E.importanceMin);if(E.importanceMax!==void 0)N+=" AND o.importance <= ?",_.push(E.importanceMax);if(E.createdAfter)N+=" AND o.created_at >= ?",_.push(E.createdAfter);if(E.createdBefore)N+=" AND o.created_at <= ?",_.push(E.createdBefore);if(E.concepts&&E.concepts.length>0){let J=E.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");N+=` AND (${J.join(" OR ")})`;for(let V of E.concepts)_.push(V)}if(E.files&&E.files.length>0){let J=E.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
|
|
88
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);N+=` AND (${J.join(" OR ")})`;for(let V of E.files){let S=`%${lM(V)}%`;_.push(S,S)}}return N+=" ORDER BY rank LIMIT ? OFFSET ?",_.push(E.limit??10),_.push(E.offset??0),this.db.all(N,_).map((J)=>({observation:this.mapRow(J),rank:J.rank,snippet:J.title}))}searchByConcept(E,M=10,N){let _=!!N,J=`SELECT o.*
|
|
89
89
|
FROM observations o
|
|
90
90
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
91
91
|
${_?"JOIN sessions s ON o.session_id = s.id":""}
|
|
@@ -93,7 +93,7 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
93
93
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
94
94
|
${_?"AND s.project_path = ?":""}
|
|
95
95
|
ORDER BY rank
|
|
96
|
-
LIMIT ?`,
|
|
96
|
+
LIMIT ?`,V=[`concepts:${E}`];if(_&&N)V.push(N);return V.push(M),this.db.all(J,V).map((S)=>this.mapRow(S))}searchByFile(E,M=10,N){let _=!!N,J=`SELECT o.*
|
|
97
97
|
FROM observations o
|
|
98
98
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
99
99
|
${_?"JOIN sessions s ON o.session_id = s.id":""}
|
|
@@ -101,7 +101,7 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
101
101
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
102
102
|
${_?"AND s.project_path = ?":""}
|
|
103
103
|
ORDER BY rank
|
|
104
|
-
LIMIT ?`,
|
|
104
|
+
LIMIT ?`,V=[`files_read:"${E.replace(/"/g,'""')}" OR files_modified:"${E.replace(/"/g,'""')}"`];if(_&&N)V.push(N);return V.push(M),this.db.all(J,V).map((S)=>this.mapRow(S))}setEmbedding(E,M){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(M),E])}getWithEmbeddings(E,M){return this.db.all(`SELECT o.id, o.embedding, o.title
|
|
105
105
|
FROM observations o
|
|
106
106
|
JOIN sessions s ON o.session_id = s.id
|
|
107
107
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
@@ -109,14 +109,14 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
109
109
|
LIMIT ?`,[E,M]).map((N)=>{try{return{id:N.id,embedding:JSON.parse(N.embedding),title:N.title}}catch{return null}}).filter((N)=>N!==null)}findSimilar(E,M,N,_){let J=this.db.all(`SELECT id, embedding FROM observations
|
|
110
110
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
111
111
|
ORDER BY created_at DESC
|
|
112
|
-
LIMIT 200`,[M]),
|
|
112
|
+
LIMIT 200`,[M]),V=[];for(let S of J)try{let A=JSON.parse(S.embedding);if(!Array.isArray(A)||A.length!==E.length)continue;let $=q(E,A);if($>=N)V.push({id:S.id,similarity:$})}catch{}return V.sort((S,A)=>A.similarity-S.similarity).slice(0,_)}insertVecEmbedding(E,M){let N=new Float32Array(M);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[E]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[E,N]),this.db.run("COMMIT")}catch(_){throw this.db.run("ROLLBACK"),_}}migrateExistingEmbeddings(E){let M=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),N=0,_=0;for(let J of M)try{let V=JSON.parse(J.embedding);if(!Array.isArray(V)||V.length!==E){_++;continue}this.insertVecEmbedding(J.id,V),N++}catch{_++}return{migrated:N,skipped:_}}getVecEmbeddingMatches(E,M){try{let N=new Float32Array(E);return this.db.all(`SELECT observation_id, distance
|
|
113
113
|
FROM observation_embeddings
|
|
114
|
-
WHERE embedding MATCH ? AND k = ?`,[N,M]).map((_)=>({observationId:_.observation_id,distance:_.distance}))}catch{return[]}}searchVecSubset(E,M,N){if(M.length===0)return[];try{let _=new Float32Array(E),J=Math.max(N*5,M.length),
|
|
114
|
+
WHERE embedding MATCH ? AND k = ?`,[N,M]).map((_)=>({observationId:_.observation_id,distance:_.distance}))}catch{return[]}}searchVecSubset(E,M,N){if(M.length===0)return[];try{let _=new Float32Array(E),J=Math.max(N*5,M.length),V=this.db.all(`SELECT observation_id, distance
|
|
115
115
|
FROM observation_embeddings
|
|
116
|
-
WHERE embedding MATCH ? AND k = ?`,[_,J]),
|
|
116
|
+
WHERE embedding MATCH ? AND k = ?`,[_,J]),S=new Set(M);return V.filter((A)=>S.has(A.observation_id)).slice(0,N).map((A)=>({observationId:A.observation_id,distance:A.distance}))}catch{return[]}}update(E,M){let N=this.getById(E);if(!N)return null;if(Object.keys(M).length===0)return N;let _=this.create({sessionId:N.sessionId,scope:N.scope??"project",type:M.type??N.type,title:M.title??N.title,subtitle:M.subtitle??N.subtitle,facts:M.facts??N.facts,narrative:M.narrative??N.narrative,concepts:M.concepts??N.concepts,filesRead:M.filesRead??N.filesRead,filesModified:M.filesModified??N.filesModified,rawToolOutput:N.rawToolOutput,toolName:"mem-revise",tokenCount:N.tokenCount,discoveryTokens:N.discoveryTokens,importance:M.importance??N.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[E,_.id]),this.supersede(E,_.id),this.getById(_.id)}supersede(E,M){let N=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[M,N,E])}delete(E){if(this.db.all("SELECT id FROM observations WHERE id = ?",[E]).length===0)return!1;let N=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[N,E]),this.deleteEmbeddingsForObservations([E]),!0}getLineage(E){let M=this.getByIdIncludingArchived(E);if(!M)return[];let N=new Set([M.id]),_=[M];while(_[0].revisionOf){let J=this.getByIdIncludingArchived(_[0].revisionOf);if(!J||N.has(J.id))break;_.unshift(J),N.add(J.id)}while(_[_.length-1].supersededBy){let J=_[_.length-1].supersededBy;if(!J)break;let V=this.getByIdIncludingArchived(J);if(!V||N.has(V.id))break;_.push(V),N.add(V.id)}return _}deleteOlderThan(E){return this.db.all(`DELETE FROM observations
|
|
117
117
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
118
118
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
119
|
-
RETURNING id`,[E]).length}deleteEmbeddingsForObservations(E){if(E.length===0)return;let M=E.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${M})`,E)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${M})`,E)}mapRow(E){return{id:E.id,sessionId:E.session_id,scope:E.scope??"project",type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),rawToolOutput:E.raw_tool_output,toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,discoveryTokens:E.discovery_tokens??0,importance:E.importance??3,revisionOf:E.revision_of??null,deletedAt:E.deleted_at??null,supersededBy:E.superseded_by??null,supersededAt:E.superseded_at??null}}}var
|
|
119
|
+
RETURNING id`,[E]).length}deleteEmbeddingsForObservations(E){if(E.length===0)return;let M=E.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${M})`,E)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${M})`,E)}mapRow(E){return{id:E.id,sessionId:E.session_id,scope:E.scope??"project",type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),rawToolOutput:E.raw_tool_output,toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,discoveryTokens:E.discovery_tokens??0,importance:E.importance??3,revisionOf:E.revision_of??null,deletedAt:E.deleted_at??null,supersededBy:E.superseded_by??null,supersededAt:E.superseded_at??null}}}var cM=[{version:1,name:"create-schema",up:`
|
|
120
120
|
-- Sessions table
|
|
121
121
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
122
122
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -410,11 +410,11 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
410
410
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
411
411
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
412
412
|
END;
|
|
413
|
-
`}];function
|
|
413
|
+
`}];function Q0(E,M){if(E.migrate(cM),M?.hasVectorExtension&&M?.embeddingDimension&&M.embeddingDimension>0)bM(E,M.embeddingDimension)}function bM(E,M){if(E.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let _=E.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(_&&Number(_.value)!==M){console.warn(`[open-mem] vec0 table exists with dimension ${_.value}, but config specifies ${M}. Drop observation_embeddings to re-create with new dimension.`);return}}else E.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
414
414
|
observation_id TEXT PRIMARY KEY,
|
|
415
415
|
embedding float[${M}] distance_metric=cosine
|
|
416
|
-
)`);E.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(M)])}class
|
|
417
|
-
VALUES (?, ?, ?, 'active')`,[E,M,N]),this.getById(E)}getOrCreate(E,M){let N=this.getById(E);if(N)return N;return this.create(E,M)}getById(E){let M=this.db.get("SELECT * FROM sessions WHERE id = ?",[E]);return M?this.mapRow(M):null}getRecent(E,M=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[E,M]).map((N)=>this.mapRow(N))}getAll(E){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[E]).map((M)=>this.mapRow(M))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((E)=>this.mapRow(E))}updateStatus(E,M){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[M,E])}markCompleted(E){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[E])}incrementObservationCount(E){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[E])}setSummary(E,M){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[M,E])}mapRow(E){return{id:E.id,projectPath:E.project_path,startedAt:E.started_at,endedAt:E.ended_at??null,status:E.status,observationCount:E.observation_count,summaryId:E.summary_id??null}}}import{randomUUID as
|
|
416
|
+
)`);E.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(M)])}class CE{db;constructor(E){this.db=E}create(E,M){let N=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
|
|
417
|
+
VALUES (?, ?, ?, 'active')`,[E,M,N]),this.getById(E)}getOrCreate(E,M){let N=this.getById(E);if(N)return N;return this.create(E,M)}getById(E){let M=this.db.get("SELECT * FROM sessions WHERE id = ?",[E]);return M?this.mapRow(M):null}getRecent(E,M=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[E,M]).map((N)=>this.mapRow(N))}getAll(E){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[E]).map((M)=>this.mapRow(M))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((E)=>this.mapRow(E))}updateStatus(E,M){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[M,E])}markCompleted(E){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[E])}incrementObservationCount(E){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[E])}setSummary(E,M){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[M,E])}mapRow(E){return{id:E.id,projectPath:E.project_path,startedAt:E.started_at,endedAt:E.ended_at??null,status:E.status,observationCount:E.observation_count,summaryId:E.summary_id??null}}}import{randomUUID as nM}from"crypto";class GE{db;constructor(E){this.db=E}create(E){let M=nM(),N=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
|
|
418
418
|
(id, session_id, summary, key_decisions, files_modified,
|
|
419
419
|
concepts, created_at, token_count,
|
|
420
420
|
request, investigated, learned, completed, next_steps)
|
|
@@ -427,7 +427,7 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
427
427
|
JOIN summaries_fts fts ON ss._rowid = fts.rowid
|
|
428
428
|
WHERE summaries_fts MATCH ?
|
|
429
429
|
ORDER BY rank
|
|
430
|
-
LIMIT ?`,[E,M]).map((N)=>this.mapRow(N))}mapRow(E){return{id:E.id,sessionId:E.session_id,summary:E.summary,keyDecisions:JSON.parse(E.key_decisions),filesModified:JSON.parse(E.files_modified),concepts:JSON.parse(E.concepts),createdAt:E.created_at,tokenCount:E.token_count,request:E.request||void 0,investigated:E.investigated||void 0,learned:E.learned||void 0,completed:E.completed||void 0,nextSteps:E.next_steps||void 0}}}import{randomUUID as
|
|
430
|
+
LIMIT ?`,[E,M]).map((N)=>this.mapRow(N))}mapRow(E){return{id:E.id,sessionId:E.session_id,summary:E.summary,keyDecisions:JSON.parse(E.key_decisions),filesModified:JSON.parse(E.files_modified),concepts:JSON.parse(E.concepts),createdAt:E.created_at,tokenCount:E.token_count,request:E.request||void 0,investigated:E.investigated||void 0,learned:E.learned||void 0,completed:E.completed||void 0,nextSteps:E.next_steps||void 0}}}import{randomUUID as dM}from"crypto";var iM=[{version:1,name:"create-user-observations",up:`
|
|
431
431
|
CREATE TABLE IF NOT EXISTS user_observations (
|
|
432
432
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
433
433
|
id TEXT UNIQUE NOT NULL,
|
|
@@ -498,7 +498,7 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
498
498
|
new.facts, new.concepts, new.files_read, new.files_modified
|
|
499
499
|
);
|
|
500
500
|
END;
|
|
501
|
-
`}];class
|
|
501
|
+
`}];class DE{db;constructor(E){let M=rM(E);this.db=r(M),this.initializeUserSchema()}initializeUserSchema(){this.db.migrate(iM)}get database(){return this.db}close(){this.db.close()}}class FE{db;constructor(E){this.db=E}create(E){let M=dM(),N=new Date().toISOString();return this.db.run(`INSERT INTO user_observations
|
|
502
502
|
(id, type, title, subtitle, facts, narrative,
|
|
503
503
|
concepts, files_read, files_modified, tool_name,
|
|
504
504
|
created_at, token_count, importance, source_project)
|
|
@@ -508,7 +508,7 @@ ${C}`}return O}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
508
508
|
JOIN user_observations_fts fts ON o._rowid = fts.rowid
|
|
509
509
|
WHERE user_observations_fts MATCH ?
|
|
510
510
|
`,N=[E.query];if(E.sourceProject)M+=" AND o.source_project = ?",N.push(E.sourceProject);return M+=" ORDER BY rank LIMIT ?",N.push(E.limit??10),this.db.all(M,N).map((_)=>({observation:this.mapRow(_),rank:_.rank}))}catch{return[]}}getIndex(E,M){let N=`SELECT id, type, title, token_count, created_at, importance, source_project
|
|
511
|
-
FROM user_observations`,_=[];if(M)N+=" WHERE source_project = ?",_.push(M);return N+=" ORDER BY created_at DESC LIMIT ?",_.push(E??20),this.db.all(N,_).map((J)=>({id:J.id,sessionId:"",type:J.type,title:J.title,tokenCount:J.token_count,discoveryTokens:0,createdAt:J.created_at,importance:J.importance??3}))}getById(E){let M=this.db.get("SELECT * FROM user_observations WHERE id = ?",[E]);return M?this.mapRow(M):null}delete(E){return this.db.all("DELETE FROM user_observations WHERE id = ? RETURNING id",[E]).length>0}mapRow(E){return{id:E.id,type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,importance:E.importance??3,sourceProject:E.source_project}}}function
|
|
511
|
+
FROM user_observations`,_=[];if(M)N+=" WHERE source_project = ?",_.push(M);return N+=" ORDER BY created_at DESC LIMIT ?",_.push(E??20),this.db.all(N,_).map((J)=>({id:J.id,sessionId:"",type:J.type,title:J.title,tokenCount:J.token_count,discoveryTokens:0,createdAt:J.created_at,importance:J.importance??3}))}getById(E){let M=this.db.get("SELECT * FROM user_observations WHERE id = ?",[E]);return M?this.mapRow(M):null}delete(E){return this.db.all("DELETE FROM user_observations WHERE id = ? RETURNING id",[E]).length>0}mapRow(E){return{id:E.id,type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,importance:E.importance??3,sourceProject:E.source_project}}}function rM(E){if(E.startsWith("~/")){let M=process.env.HOME||process.env.USERPROFILE||"";if(!M)throw Error("Cannot resolve user DB path: HOME environment variable is not set");let N=`${M}${E.slice(1)}`,_=N.substring(0,N.lastIndexOf("/"));return D("fs").mkdirSync(_,{recursive:!0}),N}return E}function x(E,M){if(M.type&&E.type!==M.type)return!1;if(M.importanceMin!==void 0&&E.importance<M.importanceMin)return!1;if(M.importanceMax!==void 0&&E.importance>M.importanceMax)return!1;if(M.createdAfter&&E.createdAt<M.createdAfter)return!1;if(M.createdBefore&&E.createdAt>M.createdBefore)return!1;if(M.concepts&&M.concepts.length>0){if(!M.concepts.some((_)=>E.concepts.some((J)=>J.toLowerCase().includes(_.toLowerCase()))))return!1}if(M.files&&M.files.length>0){let N=[...E.filesRead,...E.filesModified];if(!M.files.some((J)=>N.some((V)=>V.toLowerCase().includes(J.toLowerCase()))))return!1}return!0}async function W0(E,M,N,_,J){if(!E.trim())return M;let V=aM(E),S=new Set;for(let O of V){let X=N.findByName(O);for(let U of X){let L=N.traverseRelations(U.id,1);for(let z of L){let Q=N.getObservationsForEntity(z);for(let B of Q)S.add(B)}}}if(S.size===0)return M;let A=new Set(M.map((O)=>O.observation.id)),$=[];for(let O of S){if(A.has(O))continue;let X=_.getById(O);if(!X)continue;if(X.supersededBy)continue;$.push({observation:X,rank:0,snippet:X.title,source:"project",rankingSource:"graph",explain:{strategy:"hybrid",matchedBy:["graph"]}})}return[...M,...$].slice(0,J)}function aM(E){let M=E.split(/\s+/).filter((_)=>_.length>=2),N=[];for(let _ of M)N.push(_);for(let _=0;_<M.length-1;_++)N.push(`${M[_]} ${M[_+1]}`);return N}var Y0=60;async function B0(E,M,N,_){let J=_.limit??10,V=oM(M,E,_,J);if(!N)return V;let S=await a(N,E);if(!S)return V;let A=V.map((O)=>O.observation.id),$=tM(M,S,_.projectPath,_,J,_.hasVectorExtension??!1,A);if($.length===0)return V;return EN(V,$,J)}function oM(E,M,N,_){try{return E.search({query:M,type:N.type,limit:_,projectPath:N.projectPath,importanceMin:N.importanceMin,importanceMax:N.importanceMax,createdAfter:N.createdAfter,createdBefore:N.createdBefore,concepts:N.concepts,files:N.files})}catch{return[]}}function tM(E,M,N,_,J,V,S){if(V)return eM(E,M,_,J,S);return sM(E,M,N,_,J)}function eM(E,M,N,_,J){try{let V;if(J.length>0){if(V=E.searchVecSubset(M,J,_*3),V.length===0)V=E.getVecEmbeddingMatches(M,_*3)}else V=E.getVecEmbeddingMatches(M,_*3);if(V.length===0)return[];let S=[];for(let{observationId:A,distance:$}of V){if(S.length>=_)break;let O=E.getById(A);if(!O)continue;if(!x(O,N))continue;S.push({observation:O,rank:$-1,snippet:O.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:$}})}return S}catch{return[]}}function sM(E,M,N,_,J){let V=E.getWithEmbeddings(N,J*10);if(V.length===0)return[];let S=V.map(($)=>({id:$.id,similarity:q(M,$.embedding)})).filter(({similarity:$})=>$>=0.3).sort(($,O)=>O.similarity-$.similarity),A=[];for(let{id:$,similarity:O}of S){if(A.length>=J)break;let X=E.getById($);if(!X)continue;if(!x(X,_))continue;A.push({observation:X,rank:-O,snippet:X.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorSimilarity:O}})}return A}function EN(E,M,N){let _=new Map;for(let J=0;J<E.length;J++){let V=E[J],S=1/(Y0+J+1);_.set(V.observation.id,{score:S,result:{...V,rankingSource:"fts",explain:{strategy:"hybrid",matchedBy:["fts"],ftsRank:V.rank}}})}for(let J=0;J<M.length;J++){let V=M[J],S=1/(Y0+J+1),A=_.get(V.observation.id);if(A)A.score+=S,A.result={...A.result,explain:{strategy:"hybrid",matchedBy:["fts","vector"],ftsRank:A.result.explain?.ftsRank??A.result.rank,vectorDistance:V.explain?.vectorDistance,vectorSimilarity:V.explain?.vectorSimilarity}};else _.set(V.observation.id,{score:S,result:{...V,explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:V.explain?.vectorDistance,vectorSimilarity:V.explain?.vectorSimilarity}}})}return[..._.values()].sort((J,V)=>V.score-J.score).slice(0,N).map(({score:J,result:V})=>({...V,explain:{...V.explain??{strategy:"hybrid",matchedBy:[]},strategy:"hybrid",matchedBy:V.explain?.matchedBy??[],rrfScore:J,ftsRank:V.explain?.ftsRank,vectorDistance:V.explain?.vectorDistance,vectorSimilarity:V.explain?.vectorSimilarity}}))}class kE{observations;embeddingModel;hasVectorExtension;reranker;userObservationRepo;entityRepo;constructor(E,M,N,_=null,J=null,V=null){this.observations=E;this.embeddingModel=M;this.hasVectorExtension=N;this.reranker=_;this.userObservationRepo=J;this.entityRepo=V}async search(E,M){let N=M.strategy??"hybrid",_=M.limit??10,J;switch(N){case"filter-only":J=this.filterOnlySearch(E,M,_);break;case"semantic":J=await this.semanticSearch(E,M,_);break;case"hybrid":J=await this.hybridSearchStrategy(E,M,_);break}for(let V of J)V.source="project";if(this.entityRepo&&E.trim())J=await W0(E,J,this.entityRepo,this.observations,_);if(this.userObservationRepo){let V=this.searchUserMemory(E,M,_);J=this.mergeResults(J,V,_)}if(this.reranker&&J.length>1)return this.reranker.rerank(E,J,_);return J}filterOnlySearch(E,M,N){if(M.concept)return this.observations.searchByConcept(M.concept,N,M.projectPath).map((J)=>({observation:J,rank:0,snippet:J.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["concept-filter"]}}));if(M.file)return this.observations.searchByFile(M.file,N,M.projectPath).map((J)=>({observation:J,rank:0,snippet:J.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["file-filter"]}}));return this.observations.search({query:E,type:M.type,limit:N,projectPath:M.projectPath,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.createdAfter,createdBefore:M.createdBefore,concepts:M.concepts,files:M.files})}async semanticSearch(E,M,N){if(!this.embeddingModel)return this.filterOnlySearch(E,M,N);let _=await a(this.embeddingModel,E);if(!_)return this.filterOnlySearch(E,M,N);if(this.hasVectorExtension)return this.nativeVectorSearch(_,M,N);return this.jsFallbackVectorSearch(_,M,N)}async hybridSearchStrategy(E,M,N){return B0(E,this.observations,this.embeddingModel,{type:M.type,limit:N,projectPath:M.projectPath,hasVectorExtension:this.hasVectorExtension,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.createdAfter,createdBefore:M.createdBefore,concepts:M.concepts,files:M.files})}nativeVectorSearch(E,M,N){try{let _=this.observations.getVecEmbeddingMatches(E,N*3);if(_.length===0)return[];let J=[];for(let{observationId:V,distance:S}of _){if(J.length>=N)break;let A=this.observations.getById(V);if(!A)continue;if(!x(A,M))continue;J.push({observation:A,rank:S-1,snippet:A.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorDistance:S}})}return J}catch{return[]}}jsFallbackVectorSearch(E,M,N){let _=this.observations.getWithEmbeddings(M.projectPath,N*10);if(_.length===0)return[];let J=_.map((S)=>({id:S.id,similarity:q(E,S.embedding)})).filter(({similarity:S})=>S>=0.3).sort((S,A)=>A.similarity-S.similarity),V=[];for(let{id:S,similarity:A}of J){if(V.length>=N)break;let $=this.observations.getById(S);if(!$)continue;if(!x($,M))continue;V.push({observation:$,rank:-A,snippet:$.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorSimilarity:A}})}return V}searchUserMemory(E,M,N){if(!this.userObservationRepo)return[];try{return this.userObservationRepo.search({query:E,limit:N}).map(({observation:J,rank:V})=>({observation:MN(J),rank:V,snippet:J.title,source:"user",rankingSource:"user-memory",explain:{strategy:"filter-only",matchedBy:["user-memory"]}}))}catch{return[]}}mergeResults(E,M,N){let _=new Set(E.map((S)=>S.observation.id)),J=new Set(E.map((S)=>`${S.observation.title}::${S.observation.narrative}`)),V=M.filter((S)=>{if(_.has(S.observation.id))return!1;let A=`${S.observation.title}::${S.observation.narrative}`;if(J.has(A))return!1;return J.add(A),!0});return[...E,...V].slice(0,N)}}function MN(E){return{id:E.id,sessionId:"",type:E.type,title:E.title,subtitle:E.subtitle,facts:E.facts,narrative:E.narrative,concepts:E.concepts,filesRead:E.filesRead,filesModified:E.filesModified,rawToolOutput:"",toolName:E.toolName,createdAt:E.createdAt,tokenCount:E.tokenCount,discoveryTokens:0,importance:E.importance}}import{generateText as _N}from"ai";function L0(E,M){let N=M.map((_,J)=>` <candidate index="${J}"><title>${_.title}</title><narrative>${_.narrative}</narrative></candidate>`).join(`
|
|
512
512
|
`);return`<rerank_request>
|
|
513
513
|
<query>${E}</query>
|
|
514
514
|
<candidates>
|
|
@@ -523,4 +523,4 @@ Respond with EXACTLY this XML format:
|
|
|
523
523
|
<index>0</index>
|
|
524
524
|
</reranked>
|
|
525
525
|
</instructions>
|
|
526
|
-
</rerank_request>`}var
|
|
526
|
+
</rerank_request>`}var NN={"gemini-2.5-flash-lite":10,"gemini-2.5-flash":10,"gemini-2.5-pro":5,"gemini-2.0-flash":15,"gemini-2.0-flash-lite":30,"gemini-3-flash":5},R0=0;async function C0(E,M){if(!M)return;let N=NN[E]||5,_=Math.ceil(60000/N)+100,V=Date.now()-R0;if(V<_){let S=_-V;await new Promise((A)=>setTimeout(A,S))}R0=Date.now()}class G0{languageModel;maxCandidates;provider;modelName;rateLimitingEnabled;_generate=_N;constructor(E,M){this.languageModel=E,this.maxCandidates=M.rerankingMaxCandidates,this.provider=M.provider??"",this.modelName=M.model??"",this.rateLimitingEnabled=M.rateLimitingEnabled??!0}async rerank(E,M,N){if(M.length<=1)return M;let _=M.slice(0,this.maxCandidates),J=M.slice(this.maxCandidates),V=L0(E,_.map((A)=>({title:A.observation.title,narrative:A.observation.narrative}))),S=2;for(let A=0;A<=S;A++)try{if(this.provider==="google")await C0(this.modelName,this.rateLimitingEnabled);let{text:$}=await this._generate({model:this.languageModel,maxOutputTokens:512,prompt:V}),O=vE($);if(!O)return M.slice(0,N);let X=this.applyReranking(_,O,N);for(let U of J){if(X.length>=N)break;X.push(U)}return X}catch($){if(JN($)&&A<S){await VN(2**A*1000);continue}return M.slice(0,N)}return M.slice(0,N)}applyReranking(E,M,N){let _=[],J=new Set;for(let V of M)if(V>=0&&V<E.length&&!J.has(V)){if(J.add(V),_.push(E[V]),_.length>=N)break}if(_.length<N){for(let V=0;V<E.length&&_.length<N;V++)if(!J.has(V))_.push(E[V])}return _}}class D0{async rerank(E,M,N){if(M.length<=1)return M.slice(0,N);let _=jE(E),J=M.map((V)=>({result:V,score:this.scoreCandidate(V,_)}));return J.sort((V,S)=>S.score-V.score),J.slice(0,N).map((V)=>V.result)}scoreCandidate(E,M){let N=E.observation,_=jE(N.title),J=jE(N.narrative),V=new Set(N.concepts.map((G)=>G.toLowerCase())),S=0,A=0,$=0;for(let G of M){if(_.has(G))S++;if(J.has(G))A++;if(V.has(G))$++}let O=M.size||1,X=S/O*0.4,U=A/O*0.3,L=$/O*0.15,Q=(Date.now()-new Date(N.createdAt).getTime())/86400000,B=Q<1?0.1:Q<7?0.05:0,j=N.importance/5*0.05;return X+U+L+B+j}}function F0(E,M){if(!E.rerankingEnabled)return null;if(M)return new G0(M,E);return new D0}function jE(E){return new Set(E.toLowerCase().split(/[\s\-_./\\,;:!?()[\]{}'"]+/).filter((M)=>M.length>1))}function JN(E){if(typeof E!=="object"||E===null)return!1;let M=E,N=M.status;if(N===429||N===500||N===503)return!0;let _=M.error;if(typeof _==="object"&&_!==null&&_.type==="overloaded_error")return!0;return!1}function VN(E){return new Promise((M)=>setTimeout(M,E))}function k0(E){return E}function j0(E){return E}function T0(E){return E}function y0(E){if(!E)return null;return E}import{spawnSync as P0}from"child_process";import{dirname as SN,resolve as m0}from"path";function AN(E){try{let M=P0("git",["rev-parse","--git-common-dir"],{cwd:E,encoding:"utf-8",timeout:5000});if(M.status!==0||!M.stdout)return null;let N=M.stdout.trim();if(N===".git")return null;let _=P0("git",["rev-parse","--git-dir"],{cwd:E,encoding:"utf-8",timeout:5000});if(_.status!==0||!_.stdout)return null;let J=_.stdout.trim(),V=m0(E,N),S=m0(E,J);if(V===S)return null;let A=SN(V);if(A===V||A==="/")return null;return A}catch{return null}}function I0(E){return AN(E)??E}var __dirname="/Users/clopca/dev/github/open-mem/src",{values:q0}=XN({options:{project:{type:"string",short:"p"}},strict:!1}),ZN=typeof q0.project==="string"?q0.project:process.cwd(),x0=I0(ZN),K=f(x0);i.enableExtensionSupport();var R=r(K.dbPath);Q0(R,{hasVectorExtension:R.hasVectorExtension,embeddingDimension:K.embeddingDimension});var UN=new CE(R),h0=new RE(R),KN=new GE(R),HN=new WE(R),zN=new LE(R),h=null,TE=null;if(K.userMemoryEnabled)try{h=new DE(K.userMemoryDbPath),TE=new FE(h.database)}catch(E){console.error(`[open-mem-mcp] Failed to initialize user-level memory: ${E}`)}var u0=K.provider!=="bedrock",QN=K.compressionEnabled&&(!u0||K.apiKey)?mE({provider:K.provider,model:K.model,apiKey:K.apiKey}):null,WN=F0(K,K.rerankingEnabled&&(!u0||K.apiKey)?qE({provider:K.provider,model:K.model,apiKey:K.apiKey},IE(K)):null),YN=new BE(R),BN=new kE(h0,QN,R.hasVectorExtension,WN,TE,YN),LN=JSON.parse($N(ON(__dirname,"..","package.json"),"utf-8")),RN=new e({memoryEngine:new QE({observations:k0(h0),sessions:j0(UN),summaries:T0(KN),searchOrchestrator:BN,projectPath:x0,config:K,userObservationRepo:y0(TE),configAuditStore:HN,maintenanceHistoryStore:zN}),version:LN.version,compatibilityMode:K.mcpCompatibilityMode,protocolVersion:K.mcpProtocolVersion,supportedProtocolVersions:K.mcpSupportedProtocolVersions}),o=!1,f0=()=>{if(!o){if(o=!0,h)h.close();R.close()}process.exit(0)};process.on("SIGINT",f0);process.on("SIGTERM",f0);process.on("beforeExit",()=>{if(!o){if(o=!0,h)h.close();R.close()}});RN.start();
|