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