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.
- package/CHANGELOG.md +7 -0
- package/README.md +73 -565
- package/dist/adapters/http/loopback.d.ts +3 -0
- package/dist/adapters/http/loopback.d.ts.map +1 -0
- package/dist/adapters/http/server.d.ts.map +1 -1
- package/dist/adapters/mcp/server.d.ts +0 -2
- package/dist/adapters/mcp/server.d.ts.map +1 -1
- package/dist/adapters/opencode/tools.d.ts.map +1 -1
- package/dist/ai/fallback-policy.d.ts +18 -0
- package/dist/ai/fallback-policy.d.ts.map +1 -0
- package/dist/ai/fallback.d.ts +3 -1
- package/dist/ai/fallback.d.ts.map +1 -1
- package/dist/ai/provider.d.ts +2 -1
- package/dist/ai/provider.d.ts.map +1 -1
- package/dist/claude-code.js +87 -87
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/contracts/api.d.ts +2 -120
- package/dist/contracts/api.d.ts.map +1 -1
- package/dist/contracts/schemas.d.ts +134 -0
- package/dist/contracts/schemas.d.ts.map +1 -0
- package/dist/cursor.js +87 -87
- package/dist/daemon.js +70 -70
- package/dist/db/observations.d.ts.map +1 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -122
- package/dist/maintenance.js +43 -43
- package/dist/mcp.js +73 -73
- package/dist/modes/loader.d.ts.map +1 -1
- package/dist/modes/resolver.d.ts +21 -0
- package/dist/modes/resolver.d.ts.map +1 -0
- package/dist/platform-worker.d.ts.map +1 -1
- package/dist/search/orchestrator.d.ts +4 -13
- package/dist/search/orchestrator.d.ts.map +1 -1
- package/dist/search/registry.d.ts +19 -0
- package/dist/search/registry.d.ts.map +1 -0
- package/dist/search/strategies/filter-only.d.ts +4 -0
- package/dist/search/strategies/filter-only.d.ts.map +1 -0
- package/dist/search/strategies/hybrid.d.ts +3 -0
- package/dist/search/strategies/hybrid.d.ts.map +1 -0
- package/dist/search/strategies/semantic.d.ts +4 -0
- package/dist/search/strategies/semantic.d.ts.map +1 -0
- package/dist/search/strategies/types.d.ts +22 -0
- package/dist/search/strategies/types.d.ts.map +1 -0
- package/dist/services/readiness.d.ts +26 -0
- package/dist/services/readiness.d.ts.map +1 -0
- package/dist/services/setup-diagnostics.d.ts +23 -0
- package/dist/services/setup-diagnostics.d.ts.map +1 -0
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- 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
|
|
5
|
-
`)}function
|
|
6
|
-
**Read cost:** ~${
|
|
7
|
-
Recent sessions:`);for(let
|
|
8
|
-
Recent observations (${
|
|
9
|
-
`)}function
|
|
10
|
-
`)}function
|
|
11
|
-
Cross-project observations (${
|
|
12
|
-
`)}var
|
|
13
|
-
`);await
|
|
14
|
-
`)}async function
|
|
15
|
-
${
|
|
16
|
-
${
|
|
17
|
-
`;let
|
|
18
|
-
${
|
|
19
|
-
${
|
|
20
|
-
|
|
21
|
-
${
|
|
22
|
-
${
|
|
23
|
-
${
|
|
24
|
-
`}function
|
|
25
|
-
`:""}if(
|
|
26
|
-
`:""}if(
|
|
27
|
-
`:""}let
|
|
28
|
-
`;if(!
|
|
29
|
-
`;return`${
|
|
30
|
-
|
|
31
|
-
${
|
|
32
|
-
`}async function
|
|
33
|
-
|
|
34
|
-
${
|
|
35
|
-
`)}listObservations(
|
|
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(
|
|
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 = ?`,[
|
|
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 (?, ?, ?, ?, ?, ?)`,[
|
|
48
|
-
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[
|
|
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`,[
|
|
53
|
-
WHERE source_entity_id = ? OR target_entity_id = ?`,[
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
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 ?`,[
|
|
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 ?`,[
|
|
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 ?`,[
|
|
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 =
|
|
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
|
-
${
|
|
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
|
-
`,
|
|
88
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);
|
|
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
|
-
${
|
|
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
|
-
${
|
|
94
|
+
${e?"AND s.project_path = ?":""}
|
|
95
95
|
ORDER BY rank
|
|
96
|
-
LIMIT ?`,
|
|
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
|
-
${
|
|
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
|
-
${
|
|
102
|
+
${e?"AND s.project_path = ?":""}
|
|
103
103
|
ORDER BY rank
|
|
104
|
-
LIMIT ?`,
|
|
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 ?`,[
|
|
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`,[
|
|
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 = ?`,[
|
|
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 = ?`,[
|
|
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`,[
|
|
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
|
|
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[${
|
|
416
|
-
)`);
|
|
417
|
-
VALUES (?, ?, ?, 'active')`,[
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
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 ?`,[
|
|
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
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
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
|
-
`,
|
|
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>${
|
|
513
|
+
<query>${n}</query>
|
|
514
514
|
<candidates>
|
|
515
|
-
${
|
|
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
|
|
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();
|