open-mem 0.7.3 → 0.9.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/README.md +10 -0
- package/dist/adapters/mcp/server.d.ts.map +1 -1
- package/dist/adapters/opencode/tools.d.ts.map +1 -1
- package/dist/claude-code.js +80 -73
- package/dist/config.d.ts.map +1 -1
- package/dist/context/builder.d.ts.map +1 -1
- package/dist/contracts/api.d.ts +1 -0
- package/dist/contracts/api.d.ts.map +1 -1
- package/dist/core/contracts.d.ts +3 -2
- package/dist/core/contracts.d.ts.map +1 -1
- package/dist/core/memory-engine.d.ts +2 -2
- package/dist/core/memory-engine.d.ts.map +1 -1
- package/dist/cursor.js +80 -73
- package/dist/daemon.js +2 -2
- package/dist/db/observations.d.ts.map +1 -1
- package/dist/hooks/session-events.d.ts.map +1 -1
- package/dist/index.js +110 -103
- package/dist/maintenance.js +43 -42
- package/dist/mcp.js +49 -48
- package/dist/tools/save.d.ts.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/agents-md.d.ts +13 -3
- package/dist/utils/agents-md.d.ts.map +1 -1
- package/dist/utils/folder-context-maintenance.d.ts +11 -3
- package/dist/utils/folder-context-maintenance.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -1,59 +1,60 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var RM=Object.defineProperty;var HM=(E,M)=>{for(var N in M)RM(E,N,{get:M[N],enumerable:!0,configurable:!0,set:(_)=>M[N]=()=>_})};var ZE=(E,M)=>()=>(E&&(M=E(E=0)),M);var U=import.meta.require;import{existsSync as UM,readFileSync as BM}from"fs";function FM(){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_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;return E}function GM(E){let M=`${E}/.open-mem/config.json`;if(!UM(M))return{};try{let N=BM(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}function DM(E){switch(E){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function m(E,M){let N=GM(E),_=FM(),O={...LE,...N,..._,...M};if(!O.dbPath.startsWith("/"))O.dbPath=`${E}/${O.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!M?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)O.provider="google";else if(process.env.ANTHROPIC_API_KEY)O.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)O.provider="bedrock"}if(!O.apiKey)switch(O.provider){case"google":O.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":O.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":O.apiKey=process.env.OPENAI_API_KEY;break;case"bedrock":break}if(O.embeddingDimension===void 0)O.embeddingDimension=DM(O.provider);return O}function d(){return{...LE}}var LE;var i=ZE(()=>{LE={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,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}});var hE={};HM(hE,{writeProjectConfig:()=>IE,validatePatch:()=>t,readProjectConfig:()=>q,previewConfig:()=>R0,patchConfig:()=>H0,getEffectiveConfig:()=>p,getConfigSchema:()=>Z0});import{existsSync as O0}from"fs";import{mkdir as J0,readFile as S0,writeFile as V0}from"fs/promises";import{dirname as C0,join as A0}from"path";function vE(E){return A0(E,".open-mem","config.json")}function gE(E){return pE.find((M)=>M.key===E)}function X0(E,M){let N=gE(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 Z0(){return pE}async function q(E){let M=vE(E);if(!O0(M))return{};try{let N=await S0(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}async function IE(E,M){let N=vE(E),O={...await q(E),...M};await J0(C0(N),{recursive:!0}),await V0(N,JSON.stringify(O,null,2),"utf-8")}function t(E){let M=[];for(let[N,_]of Object.entries(E)){let J=X0(N,_);if(J)M.push(J)}return M}async function p(E){let M=d(),N=await q(E),_=m(E),O=[],J={};for(let[S,V]of Object.entries(M)){let C=S,A=gE(C),H=($0[C]??[]).some((D)=>typeof process.env[D]==="string"),Y=Object.hasOwn(N,C),B="default";if(Y)B="file";if(H)B="env";if(J[C]={source:B,locked:H,restartRequired:A?.restartRequired??!1,liveApply:A?.liveApply??!1},B==="env"&&Y)O.push(`${String(C)} is overridden by environment variable.`);if(_[C]===void 0&&V!==void 0)O.push(`${String(C)} resolved to undefined unexpectedly.`)}return{config:_,meta:J,warnings:O}}async function R0(E,M){let N=t(M);if(N.length>0)return{...await p(E),warnings:N};let _=d(),O=await q(E),J={..._,...O,...M},V={...m(E,M),...J},C=(await p(E)).meta;return{config:V,meta:C,warnings:[]}}async function H0(E,M){let N=t(M);if(N.length>0)return{...await p(E),warnings:N};return await IE(E,M),p(E)}var pE,$0;var qE=ZE(()=>{i();pE=[{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}],$0={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 x0}from"fs";import{join as u0}from"path";import{parseArgs as w0}from"util";import{createInterface as KM}from"readline";import{z as F}from"zod";import{z as X}from"zod";var v=X.enum(["decision","bugfix","feature","refactor","discovery","change"]);function K(E,M={}){return{data:E,error:null,meta:M}}function z(E,M,N){return{data:null,error:{code:E,message:M,details:N},meta:{}}}var Z={find:X.object({query:X.string().min(1),scope:X.enum(["project","user","all"]).optional().default("project"),types:X.array(v).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()}),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:v,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:v.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:v.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"])}),help:X.object({})};var LM="2024-11-05",QM=F.object({name:F.string().min(1),arguments:F.record(F.string(),F.unknown()).optional()});function zM(E){if(typeof E!=="object"||E===null)return!1;let M=E;return M.jsonrpc==="2.0"&&typeof M.method==="string"}function Q(E){let N=F.toJSONSchema(E);return{type:"object",properties:N.properties??{},required:N.required??void 0,additionalProperties:!1}}function RE(E){return E.issues.map((M)=>{return`${M.path.length>0?M.path.join("."):"input"}: ${M.message}`}).join("; ")}class n{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??LM,this.supportedProtocolVersions=E.supportedProtocolVersions&&E.supportedProtocolVersions.length>0?E.supportedProtocolVersions:[this.protocolVersion]}start(){let E=KM({input:process.stdin,terminal:!1});E.on("line",(M)=>{let N=M.trim();if(!N)return;try{let _=JSON.parse(N);if(!zM(_)){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:"memory.find",description:"Find relevant memory records.",inputSchema:Q(Z.find)},{name:"memory.history",description:"Browse session history.",inputSchema:Q(Z.history)},{name:"memory.get",description:"Fetch full memory records by id.",inputSchema:Q(Z.get)},{name:"memory.create",description:"Create a memory record.",inputSchema:Q(Z.create)},{name:"memory.revise",description:"Create a revised memory revision.",inputSchema:Q(Z.revise)},{name:"memory.remove",description:"Tombstone a memory record.",inputSchema:Q(Z.remove)},{name:"memory.transfer.export",description:"Export memory.",inputSchema:Q(Z.transferExport)},{name:"memory.transfer.import",description:"Import memory payload.",inputSchema:Q(Z.transferImport)},{name:"memory.maintenance",description:"Run maintenance action.",inputSchema:Q(Z.maintenance)},{name:"memory.help",description:"Show memory workflow guidance.",inputSchema:Q(Z.help)}]}async handleToolCall(E,M){let N=QM.safeParse(M??{});if(!N.success){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(z("VALIDATION_ERROR",RE(N.error)),null,2)}],isError:!0}});return}let _=N.data.name,O=N.data.arguments??{};try{let J=await this.executeTool(_,O);this.send({jsonrpc:"2.0",id:E,result:J})}catch(J){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(z("INTERNAL_ERROR",String(J)),null,2)}],isError:!0}})}}async executeTool(E,M){let N=async()=>{switch(E){case"memory.find":{let _=Z.find.parse(M),O=await this.memoryEngine.search(_.query,{limit:_.limit,type:_.types?.[0]});return JSON.stringify(K({results:O}),null,2)}case"memory.history":{let _=Z.history.parse(M);return JSON.stringify(K({items:await this.memoryEngine.timeline({limit:_.limit,sessionId:_.sessionId})}),null,2)}case"memory.get":{let _=Z.get.parse(M);return JSON.stringify(K({observations:await this.memoryEngine.recall(_.ids,_.limit)}),null,2)}case"memory.create":{let _=Z.create.parse(M),O=await this.memoryEngine.save({..._,sessionId:"mcp"});return JSON.stringify(O?K({observation:O}):z("CONFLICT","Unable to create memory"),null,2)}case"memory.revise":{let _=Z.revise.parse(M),O=await this.memoryEngine.update(_);return JSON.stringify(O?K({previousId:_.id,newId:O.id,observation:O}):z("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"memory.remove":{let _=Z.remove.parse(M),O=await this.memoryEngine.delete([_.id]);return JSON.stringify(O>0?K({id:_.id,tombstoned:!0}):z("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"memory.transfer.export":{let _=Z.transferExport.parse(M),O=await this.memoryEngine.export("project",{type:_.type,limit:_.limit});return JSON.stringify(K({payload:O,format:_.format}),null,2)}case"memory.transfer.import":{let _=Z.transferImport.parse(M),O=_.mode==="replace"?"overwrite":"skip-duplicates",J=await this.memoryEngine.import(_.payload,{mode:O});return JSON.stringify(K({imported:J.imported,skipped:J.skipped,mode:_.mode}),null,2)}case"memory.maintenance":{let _=Z.maintenance.parse(M);if(_.action==="folderContextDryRun")return JSON.stringify(K(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(_.action==="folderContextClean")return JSON.stringify(K(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);return JSON.stringify(K(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"memory.help":return JSON.stringify(K({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(z("NOT_FOUND",`Unknown tool: ${E}`),null,2)}};try{let _=await N(),O=_.includes('"error": {')&&!_.includes('"error": null');return{content:[{type:"text",text:_}],isError:O}}catch(_){if(_ instanceof F.ZodError)return{content:[{type:"text",text:JSON.stringify(z("VALIDATION_ERROR",RE(_)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(z("INTERNAL_ERROR",String(_)),null,2)}],isError:!0}}}send(E){process.stdout.write(`${JSON.stringify(E)}
|
|
4
|
-
`)}}var
|
|
5
|
-
`)}function
|
|
6
|
-
**Read cost:** ~${M}t | **Discovery cost:** ~${N}t | **Savings:** ${
|
|
3
|
+
var yM=Object.defineProperty;var TM=(E,M)=>{for(var N in M)yM(E,N,{get:M[N],enumerable:!0,configurable:!0,set:(_)=>M[N]=()=>_})};var YE=(E,M)=>()=>(E&&(M=E(E=0)),M);var k=import.meta.require;import{existsSync as vM,readFileSync as xM}from"fs";function qM(){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;return E}function uM(E){let M=`${E}/.open-mem/config.json`;if(!vM(M))return{};try{let N=xM(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}function hM(E){switch(E){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function g(E,M){let N=uM(E),_=qM(),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"}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"bedrock":break}if(J.embeddingDimension===void 0)J.embeddingDimension=hM(J.provider);return J}function a(){return{...FE}}var FE;var o=YE(()=>{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}});var tE={};TM(tE,{writeProjectConfig:()=>oE,validatePatch:()=>VE,readProjectConfig:()=>c,previewConfig:()=>z0,patchConfig:()=>Q0,getEffectiveConfig:()=>x,getConfigSchema:()=>H0});import{existsSync as A0}from"fs";import{mkdir as $0,readFile as X0,writeFile as Z0}from"fs/promises";import{dirname as U0,join as K0}from"path";function rE(E){return K0(E,".open-mem","config.json")}function aE(E){return iE.find((M)=>M.key===E)}function L0(E,M){let N=aE(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 H0(){return iE}async function c(E){let M=rE(E);if(!A0(M))return{};try{let N=await X0(M,"utf-8"),_=JSON.parse(N);if(!_||typeof _!=="object"||Array.isArray(_))return{};return _}catch{return{}}}async function oE(E,M){let N=rE(E),J={...await c(E),...M};await $0(U0(N),{recursive:!0}),await Z0(N,JSON.stringify(J,null,2),"utf-8")}function VE(E){let M=[];for(let[N,_]of Object.entries(E)){let S=L0(N,_);if(S)M.push(S)}return M}async function x(E){let M=a(),N=await c(E),_=g(E),J=[],S={};for(let[O,V]of Object.entries(M)){let C=O,A=aE(C),Z=(R0[C]??[]).some((L)=>typeof process.env[L]==="string"),z=Object.hasOwn(N,C),R="default";if(z)R="file";if(Z)R="env";if(S[C]={source:R,locked:Z,restartRequired:A?.restartRequired??!1,liveApply:A?.liveApply??!1},R==="env"&&z)J.push(`${String(C)} is overridden by environment variable.`);if(_[C]===void 0&&V!==void 0)J.push(`${String(C)} resolved to undefined unexpectedly.`)}return{config:_,meta:S,warnings:J}}async function z0(E,M){let N=VE(M);if(N.length>0)return{...await x(E),warnings:N};let _=a(),J=await c(E),S={..._,...J,...M},V={...g(E,M),...S},C=(await x(E)).meta;return{config:V,meta:C,warnings:[]}}async function Q0(E,M){let N=VE(M);if(N.length>0)return{...await x(E),warnings:N};return await oE(E,M),x(E)}var iE,R0;var eE=YE(()=>{o();iE=[{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}],R0={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 b0}from"fs";import{join as n0}from"path";import{parseArgs as d0}from"util";import{createInterface as mM}from"readline";import{z as j}from"zod";import{z as X}from"zod";var q=X.enum(["decision","bugfix","feature","refactor","discovery","change"]);function H(E,M={}){return{data:E,error:null,meta:M}}function D(E,M,N){return{data:null,error:{code:E,message:M,details:N},meta:{}}}var U={find:X.object({query:X.string().min(1),scope:X.enum(["project","user","all"]).optional().default("project"),types:X.array(q).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()}),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:q,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:q.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:q.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 fM="2024-11-05",PM=j.object({name:j.string().min(1),arguments:j.record(j.string(),j.unknown()).optional()});function pM(E){if(typeof E!=="object"||E===null)return!1;let M=E;return M.jsonrpc==="2.0"&&typeof M.method==="string"}function G(E){let N=j.toJSONSchema(E);return{type:"object",properties:N.properties??{},required:N.required??void 0,additionalProperties:!1}}function BE(E){return E.issues.map((M)=>{return`${M.path.length>0?M.path.join("."):"input"}: ${M.message}`}).join("; ")}class r{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??fM,this.supportedProtocolVersions=E.supportedProtocolVersions&&E.supportedProtocolVersions.length>0?E.supportedProtocolVersions:[this.protocolVersion]}start(){let E=mM({input:process.stdin,terminal:!1});E.on("line",(M)=>{let N=M.trim();if(!N)return;try{let _=JSON.parse(N);if(!pM(_)){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:G(U.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:G(U.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:G(U.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:G(U.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:G(U.revise)},{name:"mem-remove",description:"Tombstone an obsolete or incorrect memory. Use to clean up memories that are no longer accurate or relevant.",inputSchema:G(U.remove)},{name:"mem-export",description:"Export project memories as portable JSON for backup or transfer between machines.",inputSchema:G(U.transferExport)},{name:"mem-import",description:"Import memories from a JSON export. Skips duplicates by default.",inputSchema:G(U.transferImport)},{name:"mem-maintenance",description:"Run folder context maintenance \u2014 clean, rebuild, purge, or dry-run AGENTS.md files.",inputSchema:G(U.maintenance)},{name:"mem-help",description:"Show detailed memory workflow guidance including when to save, what to save, and memory type reference.",inputSchema:G(U.help)}]}async handleToolCall(E,M){let N=PM.safeParse(M??{});if(!N.success){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(D("VALIDATION_ERROR",BE(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(D("INTERNAL_ERROR",String(S)),null,2)}],isError:!0}})}}async executeTool(E,M){let N=async()=>{switch(E){case"mem-find":{let _=U.find.parse(M),J=await this.memoryEngine.search(_.query,{limit:_.limit,type:_.types?.[0]});return JSON.stringify(H({results:J}),null,2)}case"mem-history":{let _=U.history.parse(M);return JSON.stringify(H({items:await this.memoryEngine.timeline({limit:_.limit,sessionId:_.sessionId})}),null,2)}case"mem-get":{let _=U.get.parse(M);return JSON.stringify(H({observations:await this.memoryEngine.recall(_.ids,_.limit)}),null,2)}case"mem-create":{let _=U.create.parse(M),J=await this.memoryEngine.save({..._,sessionId:"mcp"});return JSON.stringify(J?H({observation:J}):D("CONFLICT","Unable to create memory"),null,2)}case"mem-revise":{let _=U.revise.parse(M),J=await this.memoryEngine.update(_);return JSON.stringify(J?H({previousId:_.id,newId:J.id,observation:J}):D("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-remove":{let _=U.remove.parse(M),J=await this.memoryEngine.delete([_.id]);return JSON.stringify(J>0?H({id:_.id,tombstoned:!0}):D("NOT_FOUND",`Observation ${_.id} not found`),null,2)}case"mem-export":{let _=U.transferExport.parse(M),J=await this.memoryEngine.export("project",{type:_.type,limit:_.limit});return JSON.stringify(H({payload:J,format:_.format}),null,2)}case"mem-import":{let _=U.transferImport.parse(M),J=_.mode==="replace"?"overwrite":"skip-duplicates",S=await this.memoryEngine.import(_.payload,{mode:J});return JSON.stringify(H({imported:S.imported,skipped:S.skipped,mode:_.mode}),null,2)}case"mem-maintenance":{let _=U.maintenance.parse(M);if(_.action==="folderContextDryRun")return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(_.action==="folderContextClean")return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);if(_.action==="folderContextPurge")return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("purge",!1)),null,2);return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"mem-help":return JSON.stringify(H({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(D("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 j.ZodError)return{content:[{type:"text",text:JSON.stringify(D("VALIDATION_ERROR",BE(_)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(D("INTERNAL_ERROR",String(_)),null,2)}],isError:!0}}}send(E){process.stdout.write(`${JSON.stringify(E)}
|
|
4
|
+
`)}}var gM={"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 IM(E){if(E.includes("."))return E;return gM[E]||`us.anthropic.${E}-v1:0`}function GE(E){switch(E.provider){case"anthropic":{let{createAnthropic:M}=k("@ai-sdk/anthropic");return M({apiKey:E.apiKey})(E.model)}case"bedrock":{let{createAmazonBedrock:M}=k("@ai-sdk/amazon-bedrock");return M()(IM(E.model))}case"openai":{let{createOpenAI:M}=k("@ai-sdk/openai");return M({apiKey:E.apiKey})(E.model)}case"google":{let{createGoogleGenerativeAI:M}=k("@ai-sdk/google");return M({apiKey:E.apiKey})(E.model)}default:throw Error(`Unknown provider: ${E.provider}. Supported: anthropic, bedrock, openai, google`)}}function DE(E){try{switch(E.provider){case"google":{let{createGoogleGenerativeAI:M}=k("@ai-sdk/google");return M({apiKey:E.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:M}=k("@ai-sdk/openai");return M({apiKey:E.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:M}=k("@ai-sdk/amazon-bedrock");return M().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;default:return null}}catch{return null}}o();import{randomUUID as sE}from"crypto";function wM(E,M){let N=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"i"),_=E.match(N);return _?_[1].trim():""}function cM(E,M){let N=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"gi"),_=[];for(let J of E.matchAll(N)){let S=J[1].trim();if(S)_.push(S)}return _}function kE(E){let M=wM(E,"reranked");if(!M)return null;let N=cM(M,"index");if(N.length===0)return null;let _=[];for(let J of N){let S=Number.parseInt(J,10);if(Number.isNaN(S)||S<0)return null;_.push(S)}return _}function F(E){return Math.ceil(E.length/4)}var lM={showTokenCosts:!0,observationTypes:"all",fullObservationCount:3,showLastSummary:!0},I={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"};function jE(E,M=lM){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 O of E.recentSummaries){let V=O.keyDecisions.length>0?O.keyDecisions.join("; "):"\u2014";N.push(`| ${O.sessionId} | ${O.summary} | ${V} |`)}}let _=M.observationTypes==="all"?E.observationIndex:E.observationIndex.filter((O)=>M.observationTypes.includes(O.type));if(_.length>0){N.push(""),N.push(`### Recent Observations (${_.length} entries)`);let O=nM(_,E.fullObservations);for(let[V,C]of O){if(N.push(""),N.push(`**${V}**`),M.showTokenCosts)N.push("| ID | Type | Title | ~Tokens |"),N.push("|----|------|-------|---------|");else N.push("| ID | Type | Title |"),N.push("|----|------|-------|");for(let A of C){let $=I[A.type]||"\uD83D\uDCDD";if(M.showTokenCosts)N.push(`| ${A.id} | ${$} | ${A.title} | ~${A.tokenCount} |`);else N.push(`| ${A.id} | ${$} | ${A.title} |`)}}}let J=E.fullObservations.slice(0,M.fullObservationCount);if(J.length>0){N.push(""),N.push("### Full Details (most recent)");for(let O of J){let V=I[O.type]||"\uD83D\uDCDD";if(N.push(""),N.push(`#### ${V} ${O.title} (${O.id})`),N.push(O.narrative),O.facts.length>0)N.push(`**Facts:** ${O.facts.map((A)=>`- ${A}`).join(" ")}`);if(O.concepts.length>0)N.push(`**Concepts:** ${O.concepts.join(", ")}`);let C=[...O.filesRead,...O.filesModified];if(C.length>0)N.push(`**Files:** ${C.join(", ")}`)}}let S=bM(E);if(S)N.push(""),N.push(S);return N.join(`
|
|
5
|
+
`)}function bM(E){let M=0,N=0,_=new Set(E.observationIndex.map((O)=>O.id));for(let O of E.observationIndex)M+=O.tokenCount,N+=O.discoveryTokens;for(let O of E.fullObservations)if(!_.has(O.id))M+=O.tokenCount,N+=O.discoveryTokens;if(N===0)return null;let J=N-M,S=Math.max(0,Math.round(J/N*100));return`### \uD83D\uDCB0 Memory Economics
|
|
6
|
+
**Read cost:** ~${M}t | **Discovery cost:** ~${N}t | **Savings:** ${S}% (${J}t saved)`}function nM(E,M){let N=new Map;for(let J of M){let S=J.filesModified[0]||J.filesRead[0];if(S)N.set(J.id,S)}let _=new Map;for(let J of E){let S=N.get(J.id)??"General",O=_.get(S)??[];O.push(J),_.set(S,O)}return _}function yE(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
|
-
`)}
|
|
8
|
+
Recent observations (${E.observationIndex.length} entries):`);for(let N of E.observationIndex)M.push(`- ${I[N.type]||"\uD83D\uDCDD"} ${N.title}`)}return M.join(`
|
|
9
|
+
`)}function TE(E,M){if(E.length===0)return"";let N=M,_=[];for(let S of E){let O=S.tokenCount||F(S.title);if(N-O<0)break;_.push(S),N-=O}if(_.length===0)return"";let J=[];J.push("### Cross-Project Memory"),J.push(""),J.push("| ID | Type | Title | ~Tokens |"),J.push("|----|------|-------|---------|");for(let S of _){let O=I[S.type]||"\uD83D\uDCDD";J.push(`| ${S.id} | ${O} | ${S.title} | ~${S.tokenCount} |`)}return J.join(`
|
|
10
|
+
`)}function mE(E,M){if(E.length===0)return"";let N=M,_=[];for(let S of E){let O=S.tokenCount||F(S.title);if(N-O<0)break;_.push(S),N-=O}if(_.length===0)return"";let J=[];J.push(`
|
|
11
|
+
Cross-project observations (${_.length} entries):`);for(let S of _)J.push(`- ${I[S.type]||"\uD83D\uDCDD"} ${S.title}`);return J.join(`
|
|
12
|
+
`)}var u={recency:0.4,typeImportance:0.3,sessionAffinity:0.2,tokenEfficiency:0.1},dM={decision:1,bugfix:0.9,feature:0.8,refactor:0.6,discovery:0.5,change:0.4};function iM(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 rM(E){return dM[E]??0.3}function aM(E,M){if(!M)return 0.5;return E===M?1:0.3}function oM(E){if(E<=10)return 1;if(E>=200)return 0.2;return 1-(E-10)/190*0.8}function tM(E,M){let N=iM(E.createdAt,M.now),_=rM(E.type),J=aM(E.sessionId,M.currentSessionId),S=oM(E.tokenCount);return N*u.recency+_*u.typeImportance+J*u.sessionAffinity+S*u.tokenEfficiency}function fE(E,M){let N=new Map;for(let _ of E)N.set(_.id,tM(_,M));return[...E].sort((_,J)=>{let S=N.get(_.id)??0,O=N.get(J.id)??0;if(O!==S)return O-S;return new Date(J.createdAt).getTime()-new Date(_.createdAt).getTime()})}function PE(E,M,N,_,J=[],S){let O=_,V=[],C=[];for(let $ of M){let Z=$.tokenCount||F($.summary);if(O-Z<0)break;V.push($),O-=Z}let A=S?fE(N,S):N;for(let $ of A){let Z=$.tokenCount||F($.title);if(O-Z<0)break;C.push($),O-=Z}return{recentSummaries:V,observationIndex:C,fullObservations:[...J],totalTokens:_-O}}import{existsSync as _E}from"fs";import{readdir as C0,readFile as hE,unlink as NE,writeFile as wE}from"fs/promises";import{join as JE,resolve as SE}from"path";import{existsSync as gE}from"fs";import{mkdir as eM,readFile as sM,rename as E0,unlink as M0,writeFile as N0}from"fs/promises";import{dirname as h,isAbsolute as s,join as v,normalize as _0,relative as EE,resolve as m,sep as t}from"path";var T="<!-- 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"},pE=new Map,J0=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function vE(E,M,N){if(M.length===0)return;if(N.mode==="single")return S0(E,M,N);let{maxDepth:_,filename:J}=N,S=[];for(let C of M){for(let A of C.filesModified)S.push(A);for(let A of C.filesRead)S.push(A)}let O=qE(S,E,_);if(O.size===0)return;let V=uE(M,O,E);for(let[C,A]of V)try{let $=O0(C,A,E);await xE(C,$,J)}catch($){console.error(`[open-mem] Failed to update AGENTS.md in ${C}:`,$)}}async function S0(E,M,N){let{maxDepth:_,filename:J}=N,S=M.filter(e);if(S.length===0)return;let O=[];for(let R of S){for(let L of R.filesModified)O.push(L);for(let L of R.filesRead)O.push(L)}let V=qE(O,E,_),C=uE(S,V,E),A=S.filter((R)=>{return[...R.filesModified,...R.filesRead].some((Q)=>{if(!Q)return!1;let Y=s(Q)?Q:v(E,Q);return m(h(Y))===m(E)})});if(A.length>0)C.set(m(E),A);if(C.size===0)return;let $=[];$.push("## Project Activity (auto-generated by open-mem)"),$.push("");let Z=[...C.entries()].map(([R,L])=>({relPath:EE(E,R)||".",observations:L})).sort((R,L)=>R.relPath.localeCompare(L.relPath));for(let{relPath:R,observations:L}of Z){let Q=L.filter(e).sort((Y,B)=>B.createdAt.localeCompare(Y.createdAt)).slice(0,10);if(Q.length===0)continue;$.push(`### ${R}/`),$.push("| Type | Title | Date |"),$.push("|------|-------|------|");for(let Y of Q){let B=IE[Y.type]||"\uD83D\uDCDD",kM=Y.createdAt.split("T")[0],jM=Y.title.replace(/\|/g,"\\|");$.push(`| ${B} ${Y.type} | ${jM} | ${kM} |`)}$.push("")}$.push("\uD83D\uDCA1 *Use `mem-find` to search full details. Use `mem-create` to save important decisions.*");let z=$.join(`
|
|
13
|
+
`);await xE(E,z,J)}function e(E){return!/^\w[\w-]*\s+execution$/i.test(E.title)}function O0(E,M,N){let _=[...M].filter(e).sort((A,$)=>$.createdAt.localeCompare(A.createdAt)).slice(0,10),J=EE(N,E)||".",S=[];S.push(`## Recent Activity in \`${J}/\` (auto-generated by open-mem)`),S.push(""),S.push("| Type | Title | Date |"),S.push("|------|-------|------|");for(let A of _){let $=IE[A.type]||"\uD83D\uDCDD",Z=A.createdAt.split("T")[0],z=A.title.replace(/\|/g,"\\|");S.push(`| ${$} ${A.type} | ${z} | ${Z} |`)}let O=new Set;for(let A of _)for(let $ of A.concepts)O.add($);if(O.size>0){let A=[...O].slice(0,10).join(", ");S.push(""),S.push(`**Key concepts:** ${A}`)}let V=_.filter((A)=>A.type==="decision").map((A)=>A.title);if(V.length>0)S.push(""),S.push(`**Recent decisions:** ${V.slice(0,5).join("; ")}`);let C=_.filter((A)=>A.type==="decision"&&A.narrative).slice(0,3);if(C.length>0){S.push(""),S.push("**Decision details:**");for(let A of C){let $=A.narrative.split(/[.!?]\s/)[0],Z=$.length>120?`${$.slice(0,117)}...`:$;S.push(`- \u2696\uFE0F ${A.title}: ${Z}`)}}return S.push(""),S.push("\uD83D\uDCA1 *Use `mem-find` to search full details across all sessions. Use `mem-create` to save important decisions.*"),S.join(`
|
|
14
|
+
`)}async function xE(E,M,N){if(!gE(E))return;let J=(pE.get(E)??Promise.resolve()).then(async()=>{let S=v(E,N),O=v(E,`.${N}.tmp`),V="";try{V=await sM(S,"utf-8")}catch{}let C=V0(V,M);try{await eM(h(O),{recursive:!0}),await N0(O,C,"utf-8"),await E0(O,S)}catch(A){try{await M0(O)}catch{}throw A}});return pE.set(E,J.catch(()=>{})),J}function V0(E,M){if(!E)return`${T}
|
|
14
15
|
${M}
|
|
15
|
-
${
|
|
16
|
-
`;let N=E.indexOf(
|
|
16
|
+
${y}
|
|
17
|
+
`;let N=E.indexOf(T),_=E.indexOf(y);if(N!==-1&&_!==-1&&_>N){let S=E.substring(0,N),O=E.substring(_+y.length);return`${S}${T}
|
|
17
18
|
${M}
|
|
18
|
-
${
|
|
19
|
+
${y}${O}`}let J=E;if(N!==-1&&_===-1)J=J.replace(T,"").trim();else if(N===-1&&_!==-1)J=J.replace(y,"").trim();else if(N!==-1&&_!==-1&&_<=N)J=J.replace(y,"").replace(T,"").trim();return`${J}
|
|
19
20
|
|
|
20
|
-
${
|
|
21
|
+
${T}
|
|
21
22
|
${M}
|
|
22
|
-
${
|
|
23
|
-
`}function
|
|
24
|
-
`:""}if(M===-1&&N!==-1){let
|
|
25
|
-
`:""}if(N<=M){let
|
|
26
|
-
`:""}let _=E.slice(0,M).trimEnd(),
|
|
27
|
-
`;if(!
|
|
23
|
+
${y}
|
|
24
|
+
`}function qE(E,M,N){let _=new Set,J=m(M);for(let S of E){if(!S||!S.trim())continue;if(S.startsWith("~")||S.startsWith("http"))continue;let O=s(S)?S:v(M,S),V=h(O),C=m(V);if(!C.startsWith(J+t)&&C!==J)continue;if(C===J)continue;let A=EE(J,C);if(A.split(t).length>N)continue;if(_0(A).split(t).some((z)=>J0.has(z)))continue;if(!gE(C))continue;_.add(C)}return _}function uE(E,M,N){let _=new Map;for(let J of E){let S=[...J.filesModified,...J.filesRead],O=new Set;for(let V of S){if(!V)continue;let C=s(V)?V:v(N,V),A=m(h(C));if(M.has(A))O.add(A)}for(let V of O){let C=_.get(V)??[];C.push(J),_.set(V,C)}}return _}var ME="<!-- open-mem-context -->",w="<!-- /open-mem-context -->";async function lE(E,M,N){let _;try{_=await C0(E,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(let J of _){let S=String(J.name);if(S===".git"||S==="node_modules"||S===".open-mem"||S==="dist")continue;let O=JE(E,S);if(J.isDirectory())await lE(O,M,N);else if(J.isFile()&&S===M)N.push(O)}}async function OE(E,M){let N=SE(E),_=[];return await lE(N,M,_),_}function cE(E){let M=E.indexOf(ME),N=E.indexOf(w);if(M===-1&&N===-1)return E;if(M!==-1&&N===-1){let S=E.replace(ME,"").trim();return S?`${S}
|
|
25
|
+
`:""}if(M===-1&&N!==-1){let S=E.replace(w,"").trim();return S?`${S}
|
|
26
|
+
`:""}if(N<=M){let S=E.replace(ME,"").replace(w,"").trim();return S?`${S}
|
|
27
|
+
`:""}let _=E.slice(0,M).trimEnd(),J=E.slice(N+w.length).trimStart();if(!_&&!J)return"";if(!_)return`${J}
|
|
28
|
+
`;if(!J)return`${_}
|
|
28
29
|
`;return`${_}
|
|
29
30
|
|
|
30
|
-
${
|
|
31
|
-
`}async function
|
|
31
|
+
${J}
|
|
32
|
+
`}async function bE(E,M,N=!1){let _=await OE(E,M),J=0;for(let S of _){let O=await hE(S,"utf-8"),V=cE(O);if(V!==O){if(J+=1,!N)if(V==="")await NE(S);else await wE(S,V,"utf-8")}}if(M){let S=JE(SE(E),M);if(_E(S))try{let O=await hE(S,"utf-8"),V=cE(O);if(V!==O){if(J+=1,!N)if(V==="")await NE(S);else await wE(S,V,"utf-8")}if(!_.includes(S))_.push(S)}catch{}}return{files:_,changed:J}}async function nE(E,M){let N=await OE(E,M);if(M){let J=JE(SE(E),M);if(_E(J)&&!N.includes(J))N.push(J)}let _=0;for(let J of N)try{await NE(J),_++}catch{}return{deleted:_,files:N}}async function dE(E,M,N,_,J=!1){let O=M.getAll(E).flatMap((C)=>N.getBySession(C.id));if(J){let C=new Set;for(let A of O)for(let $ of[...A.filesRead,...A.filesModified])C.add($);return{observations:O.length,filesTouched:C.size}}if(!_E(E))return{observations:0,filesTouched:0};await vE(E,O,{maxDepth:_.maxDepth,mode:_.mode,filename:_.filename});let V=await OE(E,_.filename);return{observations:O.length,filesTouched:V.length}}class CE{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.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 S=this.userObservationRepo.getById(_);if(!S)continue;N.push({...S,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:F(`${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:F(`${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 V of N)_.push(...this.observations.getBySession(V.id));if(M.type)_=_.filter((V)=>V.type===M.type);if(_.sort((V,C)=>new Date(V.createdAt).getTime()-new Date(C.createdAt).getTime()),M.limit&&M.limit<_.length)_=_.slice(0,M.limit);let J=_.map(({rawToolOutput:V,...C})=>C),S=N.map((V)=>this.summaries.getBySessionId(V.id)).filter((V)=>V!==null);return{version:1,exportedAt:new Date().toISOString(),project:this.projectPath,observations:J,summaries:S}}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",S=0,O=0;for(let V of _.observations){let C=this.observations.getById(V.id);if(C&&J==="skip-duplicates"){O+=1;continue}if(C&&J==="overwrite")this.observations.delete(V.id);this.sessions.getOrCreate(V.sessionId,this.projectPath),this.observations.importObservation({id:V.id,sessionId:V.sessionId,type:V.type,title:V.title,subtitle:V.subtitle??"",facts:V.facts??[],narrative:V.narrative??"",concepts:V.concepts??[],filesRead:V.filesRead??[],filesModified:V.filesModified??[],rawToolOutput:V.rawToolOutput??"",toolName:V.toolName??"unknown",createdAt:V.createdAt,tokenCount:V.tokenCount??0,discoveryTokens:V.discoveryTokens??0,importance:V.importance??3,supersededBy:V.supersededBy??null,supersededAt:V.supersededAt??null}),this.sessions.incrementObservationCount(V.sessionId),S+=1}for(let V of _.summaries??[]){let C=this.summaries.getBySessionId(V.sessionId);if(C&&J==="skip-duplicates")continue;if(C&&J==="overwrite")continue;this.sessions.getOrCreate(V.sessionId,this.projectPath),this.summaries.importSummary(V),this.sessions.setSummary(V.sessionId,V.id)}return{imported:S,skipped:O}}async buildContext(E,M="normal"){let N=this.sessions.getRecent(this.projectPath,5),_=N.map(($)=>$.summaryId?this.summaries.getBySessionId($.id):null).filter(($)=>$!==null),J=this.observations.getIndex(this.projectPath,this.config.maxObservations),O=J.slice(0,this.config.contextFullObservationCount).map(($)=>$.id).map(($)=>this.observations.getById($)).filter(($)=>$!==null),V=PE(N,_,J,this.config.maxContextTokens,O);if(M==="compaction"){let $=yE(V);if(this.config.userMemoryEnabled&&this.userObservationRepo)$+=mE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);return $}let C={showTokenCosts:this.config.contextShowTokenCosts,observationTypes:this.config.contextObservationTypes,fullObservationCount:this.config.contextFullObservationCount,showLastSummary:this.config.contextShowLastSummary},A=jE(V,C);if(this.config.userMemoryEnabled&&this.userObservationRepo){let $=TE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);if($)A+=`
|
|
32
33
|
|
|
33
|
-
${$}`}return A}guide(){return["open-mem
|
|
34
|
-
`)}listObservations(E){let{limit:M=50,offset:N=0,type:_,sessionId:
|
|
34
|
+
${$}`}return A}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:S}=E;if(S)return this.listByProjectWithState({limit:M,offset:N,type:_,state:S,sessionId:J});if(J){let C=this.observations.getBySession(J);if(_)C=C.filter((A)=>A.type===_);return C.slice(N,N+M)}let V=this.observations.getIndex(this.projectPath,N+M).slice(N);if(_)V=V.filter((C)=>C.type===_);return V.map((C)=>this.observations.getById(C.id)).filter((C)=>C!==null)}getObservation(E){return this.observations.getById(E)}getLineage(E){let N=this.getByIdIncludingArchived(E);if(!N)return null;let _=N,J=0,S=new Set([N.id]);while(_.revisionOf&&J<256){let $=this.getByIdIncludingArchived(_.revisionOf);if(!$||S.has($.id))break;_=$,S.add($.id),J+=1}let O=[],V=_,C=new Set,A=0;while(V&&!C.has(V.id)&&A<256){C.add(V.id);let $=V.deletedAt?"tombstoned":V.supersededBy?"superseded":"current";O.push({id:V.id,revisionOf:V.revisionOf??null,supersededBy:V.supersededBy??null,supersededAt:V.supersededAt??null,deletedAt:V.deletedAt??null,state:$,observation:V}),V=V.supersededBy?this.getByIdIncludingArchived(V.supersededBy):null,A+=1}return O}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,S=0,O={};for(let A of _)J+=A.tokenCount,S+=A.discoveryTokens,O[A.type]=(O[A.type]||0)+1;let V=S-J,C=_.length>0?Math.round(J/_.length):0;return{totalObservations:E,totalSessions:N,totalTokensSaved:V,averageObservationSize:C,typeBreakdown:O}}async maintainFolderContext(E,M){if(E==="purge")return{action:"purge",dryRun:!1,...await nE(this.projectPath,this.config.folderContextFilename)};if(E==="rebuild"){let _=await dE(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 bE(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=[],S=(V,C,A)=>{if(JSON.stringify(C)!==JSON.stringify(A))J.push({field:V,before:C,after:A})};S("title",_.title,N.title),S("subtitle",_.subtitle,N.subtitle),S("narrative",_.narrative,N.narrative),S("type",_.type,N.type),S("facts",_.facts,N.facts),S("concepts",_.concepts,N.concepts),S("filesRead",_.filesRead,N.filesRead),S("filesModified",_.filesModified,N.filesModified),S("importance",_.importance,N.importance);let O=J.length===0?"No material changes between revisions.":`Changed ${J.length} field${J.length===1?"":"s"}: ${J.map((V)=>V.field).join(", ")}.`;return{fromId:M,toId:E,summary:O,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((S)=>S.id===E)??null;if(!M)return null;if(!M.previousValues||typeof M.previousValues!=="object")return null;let{patchConfig:N}=await Promise.resolve().then(() => (eE(),tE)),_=M.previousValues;try{await N(this.projectPath,_)}catch(S){let O={id:`rollback-failed-${sE()}`,timestamp:new Date().toISOString(),patch:M.previousValues,previousValues:M.patch,source:"rollback-failed"};throw this.trackConfigAudit(O),S}let J={id:`rollback-${sE()}`,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 l(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class AE{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:l(E.patch),previousValues:l(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:l(M.patch),previousValues:l(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 EM}from"bun:sqlite";import{existsSync as $E,mkdirSync as W0,unlinkSync as MM}from"fs";import*as NM from"sqlite-vec";class b{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($E(M))return EM.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);W0(N,{recursive:!0})}return new EM(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{NM.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($E(M))MM(M)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if($E(this.dbPath))MM(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
|
|
35
36
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
36
37
|
version INTEGER PRIMARY KEY,
|
|
37
38
|
name TEXT NOT NULL,
|
|
38
39
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
39
40
|
)
|
|
40
|
-
`)}migrate(E){this.ensureMigrationTable();let M=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),N=new Set(M.map((
|
|
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,S)=>J.version-S.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 n(E){return new b(E)}import{randomUUID as _M}from"crypto";class XE{db;constructor(E){this.db=E}upsertEntity(E,M){let N=_M(),_=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
|
|
41
42
|
VALUES (?, ?, ?, ?, ?, 1)
|
|
42
43
|
ON CONFLICT(name, entity_type) DO UPDATE SET
|
|
43
44
|
mention_count = mention_count + 1,
|
|
44
|
-
last_seen_at = ?`,[N,E,M,_,_,_]);let
|
|
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=_M(),S=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
|
|
45
46
|
(id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
|
|
46
|
-
VALUES (?, ?, ?, ?, ?, ?)`,[
|
|
47
|
-
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[E,M,N]);return
|
|
47
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[J,E,M,N,_,S])}catch{return null}let O=this.db.get(`SELECT * FROM entity_relations
|
|
48
|
+
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[E,M,N]);return O?this.mapRelationRow(O):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.*
|
|
48
49
|
FROM entities e
|
|
49
50
|
JOIN entities_fts fts ON e._rowid = fts.rowid
|
|
50
51
|
WHERE entities_fts MATCH ?
|
|
51
52
|
ORDER BY rank`,[E]).map((N)=>this.mapEntityRow(N))}catch{return[]}}getRelationsFor(E){return this.db.all(`SELECT * FROM entity_relations
|
|
52
|
-
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,
|
|
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,S=[{id:E,currentDepth:0}];J.add(E);while(S.length>0){if(J.size>=100)break;let O=S.shift();if(!O)continue;if(O.currentDepth>=N)continue;let V=this.getRelationsFor(O.id);for(let C of V){let A=C.sourceEntityId===O.id?C.targetEntityId:C.sourceEntityId;if(!J.has(A))J.add(A),S.push({id:A,currentDepth:O.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 Y0(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class ZE{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:Y0(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 G0}from"crypto";import{embed as B0}from"ai";async function d(E,M){try{let{embedding:N}=await B0({model:E,value:M});return N}catch{return null}}function f(E,M){if(E.length!==M.length||E.length===0)return 0;let N=0,_=0,J=0;for(let O=0;O<E.length;O++)N+=E[O]*M[O],_+=E[O]*E[O],J+=M[O]*M[O];let S=Math.sqrt(_)*Math.sqrt(J);if(S===0)return 0;return N/S}function D0(E){return E.replace(/[%_\\]/g,"\\$&")}class UE{db;constructor(E){this.db=E}create(E){let M=G0(),N=new Date().toISOString(),_=E.discoveryTokens??0,J=E.importance??3,S=E.scope??"project";return this.db.run(`INSERT INTO observations
|
|
53
54
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
54
55
|
concepts, files_read, files_modified, raw_tool_output,
|
|
55
56
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
56
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,
|
|
57
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,S,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:S,createdAt:N,discoveryTokens:_,importance:J,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(E){this.db.run(`INSERT INTO observations
|
|
57
58
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
58
59
|
concepts, files_read, files_modified, raw_tool_output,
|
|
59
60
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
@@ -62,17 +63,17 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
62
63
|
JOIN sessions s ON o.session_id = s.id
|
|
63
64
|
WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
64
65
|
ORDER BY o.created_at DESC
|
|
65
|
-
LIMIT ?`,[E,M]).map((N)=>({id:N.id,sessionId:N.session_id,type:N.type,title:N.title,tokenCount:N.token_count,discoveryTokens:N.discovery_tokens??0,createdAt:N.created_at,importance:N.importance??3}))}listByProject(E,M={}){let{limit:N=50,offset:_=0,type:
|
|
66
|
+
LIMIT ?`,[E,M]).map((N)=>({id:N.id,sessionId:N.session_id,type:N.type,title:N.title,tokenCount:N.token_count,discoveryTokens:N.discovery_tokens??0,createdAt:N.created_at,importance:N.importance??3}))}listByProject(E,M={}){let{limit:N=50,offset:_=0,type:J,state:S,sessionId:O}=M,V=`SELECT o.*
|
|
66
67
|
FROM observations o
|
|
67
68
|
JOIN sessions s ON o.session_id = s.id
|
|
68
|
-
WHERE s.project_path = ?`,C=[E];if(
|
|
69
|
+
WHERE s.project_path = ?`,C=[E];if(O)V+=" AND o.session_id = ?",C.push(O);if(J)V+=" AND o.type = ?",C.push(J);if(S==="current")V+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(S==="superseded")V+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(S==="tombstoned")V+=" AND o.deleted_at IS NOT NULL";else V+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return V+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",C.push(N,_),this.db.all(V,C).map((A)=>this.mapRow(A))}search(E){let M=!!E.projectPath,N=`
|
|
69
70
|
SELECT o.*, rank
|
|
70
71
|
FROM observations o
|
|
71
72
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
72
73
|
${M?"JOIN sessions s ON o.session_id = s.id":""}
|
|
73
74
|
WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
74
|
-
`,_=[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
|
|
75
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);N+=` AND (${
|
|
75
|
+
`,_=[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 S of E.concepts)_.push(S)}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 '\\')
|
|
76
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);N+=` AND (${J.join(" OR ")})`;for(let S of E.files){let O=`%${D0(S)}%`;_.push(O,O)}}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.*
|
|
76
77
|
FROM observations o
|
|
77
78
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
78
79
|
${_?"JOIN sessions s ON o.session_id = s.id":""}
|
|
@@ -80,7 +81,7 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
80
81
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
81
82
|
${_?"AND s.project_path = ?":""}
|
|
82
83
|
ORDER BY rank
|
|
83
|
-
LIMIT ?`,
|
|
84
|
+
LIMIT ?`,S=[`concepts:${E}`];if(_&&N)S.push(N);return S.push(M),this.db.all(J,S).map((O)=>this.mapRow(O))}searchByFile(E,M=10,N){let _=!!N,J=`SELECT o.*
|
|
84
85
|
FROM observations o
|
|
85
86
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
86
87
|
${_?"JOIN sessions s ON o.session_id = s.id":""}
|
|
@@ -88,22 +89,22 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
88
89
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
89
90
|
${_?"AND s.project_path = ?":""}
|
|
90
91
|
ORDER BY rank
|
|
91
|
-
LIMIT ?`,
|
|
92
|
+
LIMIT ?`,S=[`files_read:"${E.replace(/"/g,'""')}" OR files_modified:"${E.replace(/"/g,'""')}"`];if(_&&N)S.push(N);return S.push(M),this.db.all(J,S).map((O)=>this.mapRow(O))}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
|
|
92
93
|
FROM observations o
|
|
93
94
|
JOIN sessions s ON o.session_id = s.id
|
|
94
95
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
95
96
|
ORDER BY o.created_at DESC
|
|
96
|
-
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
|
|
97
|
+
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
|
|
97
98
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
98
99
|
ORDER BY created_at DESC
|
|
99
|
-
LIMIT 200`,[M]),
|
|
100
|
+
LIMIT 200`,[M]),S=[];for(let O of J)try{let V=JSON.parse(O.embedding);if(!Array.isArray(V)||V.length!==E.length)continue;let C=f(E,V);if(C>=N)S.push({id:O.id,similarity:C})}catch{}return S.sort((O,V)=>V.similarity-O.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 S=JSON.parse(J.embedding);if(!Array.isArray(S)||S.length!==E){_++;continue}this.insertVecEmbedding(J.id,S),N++}catch{_++}return{migrated:N,skipped:_}}getVecEmbeddingMatches(E,M){try{let N=new Float32Array(E);return this.db.all(`SELECT observation_id, distance
|
|
100
101
|
FROM observation_embeddings
|
|
101
|
-
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),
|
|
102
|
+
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),S=this.db.all(`SELECT observation_id, distance
|
|
102
103
|
FROM observation_embeddings
|
|
103
|
-
WHERE embedding MATCH ? AND k = ?`,[_,
|
|
104
|
+
WHERE embedding MATCH ? AND k = ?`,[_,J]),O=new Set(M);return S.filter((V)=>O.has(V.observation_id)).slice(0,N).map((V)=>({observationId:V.observation_id,distance:V.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 S=this.getByIdIncludingArchived(J);if(!S||N.has(S.id))break;_.push(S),N.add(S.id)}return _}deleteOlderThan(E){return this.db.all(`DELETE FROM observations
|
|
104
105
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
105
106
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
106
|
-
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
|
|
107
|
+
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 F0=[{version:1,name:"create-schema",up:`
|
|
107
108
|
-- Sessions table
|
|
108
109
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
109
110
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -397,11 +398,11 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
397
398
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
398
399
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
399
400
|
END;
|
|
400
|
-
`}];function
|
|
401
|
+
`}];function JM(E,M){if(E.migrate(F0),M?.hasVectorExtension&&M?.embeddingDimension&&M.embeddingDimension>0)k0(E,M.embeddingDimension)}function k0(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(
|
|
401
402
|
observation_id TEXT PRIMARY KEY,
|
|
402
403
|
embedding float[${M}] distance_metric=cosine
|
|
403
|
-
)`);E.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(M)])}class
|
|
404
|
-
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
|
|
404
|
+
)`);E.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(M)])}class KE{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)
|
|
405
|
+
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 j0}from"crypto";class RE{db;constructor(E){this.db=E}create(E){let M=j0(),N=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
|
|
405
406
|
(id, session_id, summary, key_decisions, files_modified,
|
|
406
407
|
concepts, created_at, token_count,
|
|
407
408
|
request, investigated, learned, completed, next_steps)
|
|
@@ -414,7 +415,7 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
414
415
|
JOIN summaries_fts fts ON ss._rowid = fts.rowid
|
|
415
416
|
WHERE summaries_fts MATCH ?
|
|
416
417
|
ORDER BY rank
|
|
417
|
-
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
|
|
418
|
+
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 y0}from"crypto";var T0=[{version:1,name:"create-user-observations",up:`
|
|
418
419
|
CREATE TABLE IF NOT EXISTS user_observations (
|
|
419
420
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
420
421
|
id TEXT UNIQUE NOT NULL,
|
|
@@ -485,7 +486,7 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
485
486
|
new.facts, new.concepts, new.files_read, new.files_modified
|
|
486
487
|
);
|
|
487
488
|
END;
|
|
488
|
-
`}];class
|
|
489
|
+
`}];class LE{db;constructor(E){let M=m0(E);this.db=n(M),this.initializeUserSchema()}initializeUserSchema(){this.db.migrate(T0)}get database(){return this.db}close(){this.db.close()}}class HE{db;constructor(E){this.db=E}create(E){let M=y0(),N=new Date().toISOString();return this.db.run(`INSERT INTO user_observations
|
|
489
490
|
(id, type, title, subtitle, facts, narrative,
|
|
490
491
|
concepts, files_read, files_modified, tool_name,
|
|
491
492
|
created_at, token_count, importance, source_project)
|
|
@@ -495,7 +496,7 @@ ${$}`}return A}guide(){return["open-mem workflow:","1) Use memory.find to find c
|
|
|
495
496
|
JOIN user_observations_fts fts ON o._rowid = fts.rowid
|
|
496
497
|
WHERE user_observations_fts MATCH ?
|
|
497
498
|
`,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
|
|
498
|
-
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((
|
|
499
|
+
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 m0(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 k("fs").mkdirSync(_,{recursive:!0}),N}return E}function P(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((S)=>S.toLowerCase().includes(J.toLowerCase()))))return!1}return!0}async function SM(E,M,N,_,J){if(!E.trim())return M;let S=f0(E),O=new Set;for(let A of S){let $=N.findByName(A);for(let Z of $){let z=N.traverseRelations(Z.id,1);for(let R of z){let L=N.getObservationsForEntity(R);for(let Q of L)O.add(Q)}}}if(O.size===0)return M;let V=new Set(M.map((A)=>A.observation.id)),C=[];for(let A of O){if(V.has(A))continue;let $=_.getById(A);if(!$)continue;if($.supersededBy)continue;C.push({observation:$,rank:0,snippet:$.title,source:"project",rankingSource:"graph",explain:{strategy:"hybrid",matchedBy:["graph"]}})}return[...M,...C].slice(0,J)}function f0(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 OM=60;async function VM(E,M,N,_){let J=_.limit??10,S=P0(M,E,_,J);if(!N)return S;let O=await d(N,E);if(!O)return S;let V=S.map((A)=>A.observation.id),C=p0(M,O,_.projectPath,_,J,_.hasVectorExtension??!1,V);if(C.length===0)return S;return v0(S,C,J)}function P0(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 p0(E,M,N,_,J,S,O){if(S)return g0(E,M,_,J,O);return I0(E,M,N,_,J)}function g0(E,M,N,_,J){try{let S;if(J.length>0){if(S=E.searchVecSubset(M,J,_*3),S.length===0)S=E.getVecEmbeddingMatches(M,_*3)}else S=E.getVecEmbeddingMatches(M,_*3);if(S.length===0)return[];let O=[];for(let{observationId:V,distance:C}of S){if(O.length>=_)break;let A=E.getById(V);if(!A)continue;if(!P(A,N))continue;O.push({observation:A,rank:C-1,snippet:A.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:C}})}return O}catch{return[]}}function I0(E,M,N,_,J){let S=E.getWithEmbeddings(N,J*10);if(S.length===0)return[];let O=S.map((C)=>({id:C.id,similarity:f(M,C.embedding)})).filter(({similarity:C})=>C>=0.3).sort((C,A)=>A.similarity-C.similarity),V=[];for(let{id:C,similarity:A}of O){if(V.length>=J)break;let $=E.getById(C);if(!$)continue;if(!P($,_))continue;V.push({observation:$,rank:-A,snippet:$.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorSimilarity:A}})}return V}function v0(E,M,N){let _=new Map;for(let J=0;J<E.length;J++){let S=E[J],O=1/(OM+J+1);_.set(S.observation.id,{score:O,result:{...S,rankingSource:"fts",explain:{strategy:"hybrid",matchedBy:["fts"],ftsRank:S.rank}}})}for(let J=0;J<M.length;J++){let S=M[J],O=1/(OM+J+1),V=_.get(S.observation.id);if(V)V.score+=O,V.result={...V.result,explain:{strategy:"hybrid",matchedBy:["fts","vector"],ftsRank:V.result.explain?.ftsRank??V.result.rank,vectorDistance:S.explain?.vectorDistance,vectorSimilarity:S.explain?.vectorSimilarity}};else _.set(S.observation.id,{score:O,result:{...S,explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:S.explain?.vectorDistance,vectorSimilarity:S.explain?.vectorSimilarity}}})}return[..._.values()].sort((J,S)=>S.score-J.score).slice(0,N).map(({score:J,result:S})=>({...S,explain:{...S.explain??{strategy:"hybrid",matchedBy:[]},strategy:"hybrid",matchedBy:S.explain?.matchedBy??[],rrfScore:J,ftsRank:S.explain?.ftsRank,vectorDistance:S.explain?.vectorDistance,vectorSimilarity:S.explain?.vectorSimilarity}}))}class zE{observations;embeddingModel;hasVectorExtension;reranker;userObservationRepo;entityRepo;constructor(E,M,N,_=null,J=null,S=null){this.observations=E;this.embeddingModel=M;this.hasVectorExtension=N;this.reranker=_;this.userObservationRepo=J;this.entityRepo=S}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 S of J)S.source="project";if(this.entityRepo&&E.trim())J=await SM(E,J,this.entityRepo,this.observations,_);if(this.userObservationRepo){let S=this.searchUserMemory(E,M,_);J=this.mergeResults(J,S,_)}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 d(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 VM(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:S,distance:O}of _){if(J.length>=N)break;let V=this.observations.getById(S);if(!V)continue;if(!P(V,M))continue;J.push({observation:V,rank:O-1,snippet:V.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorDistance:O}})}return J}catch{return[]}}jsFallbackVectorSearch(E,M,N){let _=this.observations.getWithEmbeddings(M.projectPath,N*10);if(_.length===0)return[];let J=_.map((O)=>({id:O.id,similarity:f(E,O.embedding)})).filter(({similarity:O})=>O>=0.3).sort((O,V)=>V.similarity-O.similarity),S=[];for(let{id:O,similarity:V}of J){if(S.length>=N)break;let C=this.observations.getById(O);if(!C)continue;if(!P(C,M))continue;S.push({observation:C,rank:-V,snippet:C.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorSimilarity:V}})}return S}searchUserMemory(E,M,N){if(!this.userObservationRepo)return[];try{return this.userObservationRepo.search({query:E,limit:N}).map(({observation:J,rank:S})=>({observation:x0(J),rank:S,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((O)=>O.observation.id)),J=new Set(E.map((O)=>`${O.observation.title}::${O.observation.narrative}`)),S=M.filter((O)=>{if(_.has(O.observation.id))return!1;let V=`${O.observation.title}::${O.observation.narrative}`;if(J.has(V))return!1;return J.add(V),!0});return[...E,...S].slice(0,N)}}function x0(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 u0}from"ai";function CM(E,M){let N=M.map((_,J)=>` <candidate index="${J}"><title>${_.title}</title><narrative>${_.narrative}</narrative></candidate>`).join(`
|
|
499
500
|
`);return`<rerank_request>
|
|
500
501
|
<query>${E}</query>
|
|
501
502
|
<candidates>
|
|
@@ -510,4 +511,4 @@ Respond with EXACTLY this XML format:
|
|
|
510
511
|
<index>0</index>
|
|
511
512
|
</reranked>
|
|
512
513
|
</instructions>
|
|
513
|
-
</rerank_request>`}var
|
|
514
|
+
</rerank_request>`}var q0={"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},AM=0;async function $M(E,M){if(!M)return;let N=q0[E]||5,_=Math.ceil(60000/N)+100,S=Date.now()-AM;if(S<_){let O=_-S;await new Promise((V)=>setTimeout(V,O))}AM=Date.now()}class XM{languageModel;maxCandidates;provider;modelName;rateLimitingEnabled;_generate=u0;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),S=CM(E,_.map((V)=>({title:V.observation.title,narrative:V.observation.narrative}))),O=2;for(let V=0;V<=O;V++)try{if(this.provider==="google")await $M(this.modelName,this.rateLimitingEnabled);let{text:C}=await this._generate({model:this.languageModel,maxOutputTokens:512,prompt:S}),A=kE(C);if(!A)return M.slice(0,N);let $=this.applyReranking(_,A,N);for(let Z of J){if($.length>=N)break;$.push(Z)}return $}catch(C){if(h0(C)&&V<O){await w0(2**V*1000);continue}return M.slice(0,N)}return M.slice(0,N)}applyReranking(E,M,N){let _=[],J=new Set;for(let S of M)if(S>=0&&S<E.length&&!J.has(S)){if(J.add(S),_.push(E[S]),_.length>=N)break}if(_.length<N){for(let S=0;S<E.length&&_.length<N;S++)if(!J.has(S))_.push(E[S])}return _}}class ZM{async rerank(E,M,N){if(M.length<=1)return M.slice(0,N);let _=QE(E),J=M.map((S)=>({result:S,score:this.scoreCandidate(S,_)}));return J.sort((S,O)=>O.score-S.score),J.slice(0,N).map((S)=>S.result)}scoreCandidate(E,M){let N=E.observation,_=QE(N.title),J=QE(N.narrative),S=new Set(N.concepts.map((B)=>B.toLowerCase())),O=0,V=0,C=0;for(let B of M){if(_.has(B))O++;if(J.has(B))V++;if(S.has(B))C++}let A=M.size||1,$=O/A*0.4,Z=V/A*0.3,z=C/A*0.15,L=(Date.now()-new Date(N.createdAt).getTime())/86400000,Q=L<1?0.1:L<7?0.05:0,Y=N.importance/5*0.05;return $+Z+z+Q+Y}}function UM(E,M){if(!E.rerankingEnabled)return null;if(M)return new XM(M,E);return new ZM}function QE(E){return new Set(E.toLowerCase().split(/[\s\-_./\\,;:!?()[\]{}'"]+/).filter((M)=>M.length>1))}function h0(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 w0(E){return new Promise((M)=>setTimeout(M,E))}function KM(E){return E}function RM(E){return E}function LM(E){return E}function HM(E){if(!E)return null;return E}import{spawnSync as zM}from"child_process";import{dirname as c0,resolve as QM}from"path";function l0(E){try{let M=zM("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 _=zM("git",["rev-parse","--git-dir"],{cwd:E,encoding:"utf-8",timeout:5000});if(_.status!==0||!_.stdout)return null;let J=_.stdout.trim(),S=QM(E,N),O=QM(E,J);if(S===O)return null;let V=c0(S);if(V===S||V==="/")return null;return V}catch{return null}}function WM(E){return l0(E)??E}var __dirname="/Users/clopca/dev/github/open-mem/src",{values:YM}=d0({options:{project:{type:"string",short:"p"}},strict:!1}),i0=typeof YM.project==="string"?YM.project:process.cwd(),BM=WM(i0),K=g(BM);b.enableExtensionSupport();var W=n(K.dbPath);JM(W,{hasVectorExtension:W.hasVectorExtension,embeddingDimension:K.embeddingDimension});var r0=new KE(W),GM=new UE(W),a0=new RE(W),o0=new AE(W),t0=new ZE(W),p=null,WE=null;if(K.userMemoryEnabled)try{p=new LE(K.userMemoryDbPath),WE=new HE(p.database)}catch(E){console.error(`[open-mem-mcp] Failed to initialize user-level memory: ${E}`)}var DM=K.provider!=="bedrock",e0=K.compressionEnabled&&(!DM||K.apiKey)?DE({provider:K.provider,model:K.model,apiKey:K.apiKey}):null,s0=UM(K,K.rerankingEnabled&&(!DM||K.apiKey)?GE({provider:K.provider,model:K.model,apiKey:K.apiKey}):null),EN=new XE(W),MN=new zE(GM,e0,W.hasVectorExtension,s0,WE,EN),NN=JSON.parse(b0(n0(__dirname,"..","package.json"),"utf-8")),_N=new r({memoryEngine:new CE({observations:KM(GM),sessions:RM(r0),summaries:LM(a0),searchOrchestrator:MN,projectPath:BM,config:K,userObservationRepo:HM(WE),configAuditStore:o0,maintenanceHistoryStore:t0}),version:NN.version,compatibilityMode:K.mcpCompatibilityMode,protocolVersion:K.mcpProtocolVersion,supportedProtocolVersions:K.mcpSupportedProtocolVersions}),i=!1,FM=()=>{if(!i){if(i=!0,p)p.close();W.close()}process.exit(0)};process.on("SIGINT",FM);process.on("SIGTERM",FM);process.on("beforeExit",()=>{if(!i){if(i=!0,p)p.close();W.close()}});_N.start();
|