open-mem 0.14.0 → 0.14.2
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 +6 -0
- package/README.md +58 -1
- package/dist/claude-code.js +88 -87
- package/dist/cursor.js +88 -87
- package/dist/daemon/manager.d.ts +33 -5
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/pid.d.ts +23 -0
- package/dist/daemon/pid.d.ts.map +1 -1
- package/dist/daemon.js +35 -34
- package/dist/db/advisory-lock.d.ts +40 -0
- package/dist/db/advisory-lock.d.ts.map +1 -0
- package/dist/db/database.d.ts +37 -4
- package/dist/db/database.d.ts.map +1 -1
- package/dist/doctor.js +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +99 -98
- package/dist/maintenance.js +48 -45
- package/dist/mcp.js +72 -71
- package/dist/platform-worker.d.ts.map +1 -1
- package/dist/runtime/queue-runtime.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/mcp.js
CHANGED
|
@@ -1,122 +1,123 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
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
|
|
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 y
|
|
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
|
-
|
|
3
|
+
var Ru=Object.defineProperty;var Nu=(y,S)=>{for(var u in S)Ru(y,u,{get:S[u],enumerable:!0,configurable:!0,set:(n)=>S[u]=()=>n})};var e=(y,S)=>()=>(y&&(S=y(y=0)),S);var H=import.meta.require;import{existsSync as Bu,readdirSync as Zu,readFileSync as Xu}from"fs";import{join as Hu}from"path";function W(y){return{...y,observationTypes:[...y.observationTypes],conceptVocabulary:[...y.conceptVocabulary],entityTypes:[...y.entityTypes],relationshipTypes:[...y.relationshipTypes],promptOverrides:y.promptOverrides?{...y.promptOverrides}:void 0}}function Ku(y){if(!y||typeof y!=="object")return!1;let S=y,u=(O)=>Array.isArray(O)&&O.every((M)=>typeof M==="string"),n=(O)=>typeof O==="object"&&O!==null&&!Array.isArray(O)&&Object.values(O).every((M)=>typeof M==="string");return typeof S.id==="string"&&(S.extends===void 0||typeof S.extends==="string")&&(S.locale===void 0||typeof S.locale==="string")&&(S.name===void 0||typeof S.name==="string")&&(S.description===void 0||typeof S.description==="string")&&(S.observationTypes===void 0||u(S.observationTypes))&&(S.conceptVocabulary===void 0||u(S.conceptVocabulary))&&(S.entityTypes===void 0||u(S.entityTypes))&&(S.relationshipTypes===void 0||u(S.relationshipTypes))&&(S.promptOverrides===void 0||n(S.promptOverrides))}function Yu(y){return typeof y.name==="string"&&typeof y.description==="string"&&Array.isArray(y.observationTypes)&&Array.isArray(y.conceptVocabulary)&&Array.isArray(y.entityTypes)&&Array.isArray(y.relationshipTypes)}function Py(y,S){return{...y,...S,id:S.id,name:S.name??y.name,description:S.description??y.description,observationTypes:S.observationTypes??y.observationTypes,conceptVocabulary:S.conceptVocabulary??y.conceptVocabulary,entityTypes:S.entityTypes??y.entityTypes,relationshipTypes:S.relationshipTypes??y.relationshipTypes,promptOverrides:{...y.promptOverrides??{},...S.promptOverrides??{}}}}class Ry{modesDir;constructor(y){this.modesDir=y}loadAllRaw(){let y=new Map;if(!Bu(this.modesDir))return y;for(let S of Zu(this.modesDir)){if(!S.endsWith(".json"))continue;let u=Hu(this.modesDir,S);try{let n=Xu(u,"utf-8"),O=JSON.parse(n);if(!Ku(O))continue;if(y.has(O.id))console.warn(`[open-mem] Duplicate mode id "${O.id}" in ${u}; overriding previous definition.`);y.set(O.id,O)}catch{}}return y}resolveById(y,S){let u=new Set,n=!1,O=(f)=>{if(u.has(f))return n=!0,W(L);u.add(f);let p=S.get(f);if(!p)return W(L);if(!p.extends){if(!Yu(p))return W(L);return Py(W(L),p)}let E=O(p.extends);if(n)return W(L);return Py(E,p)},M=O(y);return n?W(L):W(M)}}var L;var ry=e(()=>{L={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 cu}from"path";function Qu(){if(i)return i;return i=Wu.loadAllRaw(),i}function ey(){return[...Qu().keys()].sort()}var zu,Wu,i=null;var iy=e(()=>{ry();zu=cu(import.meta.dir,"."),Wu=new Ry(zu)});import{existsSync as Lu,readFileSync as Fu}from"fs";function Du(){let y={};if(process.env.OPEN_MEM_DB_PATH)y.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)y.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)y.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)y.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")y.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")y.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)y.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((S)=>S.trim());if(process.env.OPEN_MEM_BATCH_SIZE)y.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)y.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)y.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")y.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)y.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((S)=>S.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)y.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)y.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")y.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")y.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")y.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)y.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")y.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")y.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)y.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")y.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")y.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)y.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")y.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")y.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")y.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)y.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)y.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((S)=>S.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)y.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")y.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let S=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(S))y.conflictSimilarityBandLow=S}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let S=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(S))y.conflictSimilarityBandHigh=S}if(process.env.OPEN_MEM_USER_MEMORY==="true")y.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)y.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)y.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")y.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)y.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")y.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)y.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((S)=>S.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)y.mode=process.env.OPEN_MEM_MODE;return y}function Gu(y){let S=`${y}/.open-mem/config.json`;if(!Lu(S))return{};try{let u=Fu(S,"utf-8"),n=JSON.parse(u);if(!n||typeof n!=="object"||Array.isArray(n))return{};return n}catch{return{}}}function Tu(y){switch(y){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function q(y,S){let u=Gu(y),n=Du(),O={...by,...u,...n,...S};if(!O.dbPath.startsWith("/"))O.dbPath=`${y}/${O.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!S?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)O.provider="google";else if(process.env.ANTHROPIC_API_KEY)O.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)O.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)O.provider="openrouter"}if(!O.apiKey)switch(O.provider){case"google":O.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":O.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":O.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":O.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(O.provider==="openrouter"&&O.model==="gemini-2.5-flash-lite")O.model="google/gemini-2.5-flash-lite";if(O.embeddingDimension===void 0)O.embeddingDimension=Tu(O.provider);if(O.mode&&!ey().includes(O.mode))O.mode="code";return O}function Ny(){return{...by}}var by;var my=e(()=>{iy();by={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:"single",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 BS={};Nu(BS,{writeProjectConfig:()=>US,validatePatch:()=>Xy,readProjectConfig:()=>d,previewConfig:()=>Vn,patchConfig:()=>Jn,getEffectiveConfig:()=>P,getConfigSchema:()=>mn});import{existsSync as nn}from"fs";import{mkdir as On,readFile as Mn,writeFile as fn}from"fs/promises";import{dirname as pn,join as En}from"path";function gS(y){return En(y,".open-mem","config.json")}function CS(y){return $S.find((S)=>S.key===y)}function Nn(y,S){let u=CS(y);if(!u)return null;if(u.type==="string"&&typeof S!=="string")return`${String(y)} must be a string`;if(u.type==="number"&&typeof S!=="number")return`${String(y)} must be a number`;if(u.type==="boolean"&&typeof S!=="boolean")return`${String(y)} must be a boolean`;if(u.type==="array"&&!Array.isArray(S))return`${String(y)} must be an array`;if(u.enum&&typeof S==="string"&&!u.enum.includes(S))return`${String(y)} must be one of: ${u.enum.join(", ")}`;if(typeof S==="number"){if(u.min!==void 0&&S<u.min)return`${String(y)} must be >= ${u.min}`;if(u.max!==void 0&&S>u.max)return`${String(y)} must be <= ${u.max}`}return null}function mn(){return $S}async function d(y){let S=gS(y);if(!nn(S))return{};try{let u=await Mn(S,"utf-8"),n=JSON.parse(u);if(!n||typeof n!=="object"||Array.isArray(n))return{};return n}catch{return{}}}async function US(y,S){let u=gS(y),O={...await d(y),...S};await On(pn(u),{recursive:!0}),await fn(u,JSON.stringify(O,null,2),"utf-8")}function Xy(y){let S=[];for(let[u,n]of Object.entries(y)){let M=Nn(u,n);if(M)S.push(M)}return S}async function P(y){let S=Ny(),u=await d(y),n=q(y),O=[],M={};for(let[f,p]of Object.entries(S)){let E=f,R=CS(E),V=(Rn[E]??[]).some(($)=>typeof process.env[$]==="string"),J=Object.hasOwn(u,E),_="default";if(J)_="file";if(V)_="env";if(M[E]={source:_,locked:V,restartRequired:R?.restartRequired??!1,liveApply:R?.liveApply??!1},_==="env"&&J)O.push(`${String(E)} is overridden by environment variable.`);if(n[E]===void 0&&p!==void 0)O.push(`${String(E)} resolved to undefined unexpectedly.`)}return{config:n,meta:M,warnings:O}}async function Vn(y,S){let u=Xy(S);if(u.length>0)return{...await P(y),warnings:u};let n=Ny(),O=await d(y),M={...n,...O,...S},p={...q(y,S),...M},E=(await P(y)).meta;return{config:p,meta:E,warnings:[]}}async function Jn(y,S){let u=Xy(S);if(u.length>0)return{...await P(y),warnings:u};return await US(y,S),P(y)}var $S,Rn;var ZS=e(()=>{my();$S=[{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}],Rn={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 RO}from"fs";import{join as NO}from"path";import{parseArgs as mO}from"util";import{createInterface as mu}from"readline";import{z}from"zod";import{z as m}from"zod";var k=m.enum(["decision","bugfix","feature","refactor","discovery","change"]),B={find:m.object({query:m.string().min(1),scope:m.enum(["project","user","all"]).optional().default("project"),types:m.array(k).optional(),limit:m.number().int().min(1).max(50).optional().default(10),cursor:m.string().optional(),include:m.object({snippets:m.boolean().optional(),scores:m.boolean().optional(),relations:m.boolean().optional()}).optional()}),history:m.object({limit:m.number().int().min(1).max(20).optional().default(5),cursor:m.string().optional(),sessionId:m.string().optional(),anchor:m.string().optional().describe("Observation ID to center the timeline around"),depthBefore:m.number().int().min(0).max(20).optional().default(5),depthAfter:m.number().int().min(0).max(20).optional().default(5)}),get:m.object({ids:m.array(m.string()).min(1),includeHistory:m.boolean().optional().default(!1),limit:m.number().int().min(1).max(50).optional().default(10)}),create:m.object({title:m.string(),type:k,narrative:m.string(),concepts:m.array(m.string()).optional(),files:m.array(m.string()).optional(),importance:m.number().int().min(1).max(5).optional(),scope:m.enum(["project","user"]).optional().default("project")}),revise:m.object({id:m.string(),title:m.string().optional(),narrative:m.string().optional(),type:k.optional(),concepts:m.array(m.string()).optional(),importance:m.number().int().min(1).max(5).optional(),reason:m.string().optional()}),remove:m.object({id:m.string(),reason:m.string().optional()}),transferExport:m.object({scope:m.enum(["project"]).optional().default("project"),type:k.optional(),limit:m.number().int().min(1).optional(),format:m.enum(["json"]).optional().default("json")}),transferImport:m.object({payload:m.string(),mode:m.enum(["skip","merge","replace"]).optional().default("skip")}),maintenance:m.object({action:m.enum(["folderContextDryRun","folderContextClean","folderContextRebuild","folderContextPurge"])}),help:m.object({})},My=[{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 C(y,S={}){return{data:y,error:null,meta:S}}function K(y,S,u){return{data:null,error:{code:y,message:S,details:u},meta:{}}}var Vu="2024-11-05",Ju=z.object({name:z.string().min(1),arguments:z.record(z.string(),z.unknown()).optional()});function _u(y){if(typeof y!=="object"||y===null)return!1;let S=y;return S.jsonrpc==="2.0"&&typeof S.method==="string"}function Au(y){let u=z.toJSONSchema(y);return{type:"object",properties:u.properties??{},required:u.required??void 0,additionalProperties:!1}}function xy(y){return y.issues.map((S)=>{return`${S.path.length>0?S.path.join("."):"input"}: ${S.message}`}).join("; ")}class fy{memoryEngine;version;protocolVersion;supportedProtocolVersions;initialized=!1;pendingOps=[];constructor(y){this.memoryEngine=y.memoryEngine,this.version=y.version,this.protocolVersion=y.protocolVersion??Vu,this.supportedProtocolVersions=y.supportedProtocolVersions&&y.supportedProtocolVersions.length>0?y.supportedProtocolVersions:[this.protocolVersion]}start(){let y=mu({input:process.stdin,terminal:!1});y.on("line",(S)=>{let u=S.trim();if(!u)return;try{let n=JSON.parse(u);if(!_u(n)){this.send({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Request"}});return}this.handle(n)}catch{this.send({jsonrpc:"2.0",id:null,error:{code:-32700,message:"Parse error"}})}}),y.on("close",()=>{Promise.allSettled(this.pendingOps).then(()=>process.exit(0))})}handle(y){if(y.method==="notifications/initialized"){this.initialized=!0;return}if(y.id===void 0||y.id===null)return;if(y.method==="initialize"){this.handleInitialize(y);return}if(!this.initialized){this.send({jsonrpc:"2.0",id:y.id,error:{code:-32002,message:"Server not initialized"}});return}switch(y.method){case"tools/list":this.send({jsonrpc:"2.0",id:y.id,result:{tools:this.getToolDefinitions()}});return;case"tools/call":{let S=this.handleToolCall(y.id,y.params);this.pendingOps.push(S),S.finally(()=>{this.pendingOps=this.pendingOps.filter((u)=>u!==S)});return}case"ping":this.send({jsonrpc:"2.0",id:y.id,result:{}});return;default:this.send({jsonrpc:"2.0",id:y.id,error:{code:-32601,message:`Method not found: ${y.method}`}})}}handleInitialize(y){let S=typeof y.params?.protocolVersion==="string"?y.params.protocolVersion:this.protocolVersion;if(!this.supportedProtocolVersions.includes(S)){this.send({jsonrpc:"2.0",id:y.id??null,error:{code:-32602,message:`Unsupported protocol version: ${S}`,data:{supported:this.supportedProtocolVersions}}});return}this.initialized=!0,this.send({jsonrpc:"2.0",id:y.id??null,result:{protocolVersion:S,capabilities:{tools:{listChanged:!1}},serverInfo:{name:"open-mem",version:this.version}}})}getToolDefinitions(){return My.map((y)=>({name:y.name,description:y.description,inputSchema:Au(B[y.schema])}))}async handleToolCall(y,S){let u=Ju.safeParse(S??{});if(!u.success){this.send({jsonrpc:"2.0",id:y,result:{content:[{type:"text",text:JSON.stringify(K("VALIDATION_ERROR",xy(u.error)),null,2)}],isError:!0}});return}let n=u.data.name,O=u.data.arguments??{};try{let M=await this.executeTool(n,O);this.send({jsonrpc:"2.0",id:y,result:M})}catch(M){this.send({jsonrpc:"2.0",id:y,result:{content:[{type:"text",text:JSON.stringify(K("INTERNAL_ERROR",String(M)),null,2)}],isError:!0}})}}async executeTool(y,S){let u=async()=>{switch(y){case"mem-find":{let n=B.find.parse(S),O=await this.memoryEngine.search(n.query,{limit:n.limit,type:n.types?.[0]});return JSON.stringify(C({results:O}),null,2)}case"mem-history":{let n=B.history.parse(S);return JSON.stringify(C({items:await this.memoryEngine.timeline({limit:n.limit,sessionId:n.sessionId,anchor:n.anchor,depthBefore:n.depthBefore,depthAfter:n.depthAfter})}),null,2)}case"mem-get":{let n=B.get.parse(S);return JSON.stringify(C({observations:await this.memoryEngine.recall(n.ids,n.limit)}),null,2)}case"mem-create":{let n=B.create.parse(S),O=await this.memoryEngine.save({...n,sessionId:"mcp"});return JSON.stringify(O?C({observation:O}):K("CONFLICT","Unable to create memory"),null,2)}case"mem-revise":{let n=B.revise.parse(S),O=await this.memoryEngine.update(n);return JSON.stringify(O?C({previousId:n.id,newId:O.id,observation:O}):K("NOT_FOUND",`Observation ${n.id} not found`),null,2)}case"mem-remove":{let n=B.remove.parse(S),O=await this.memoryEngine.delete([n.id]);return JSON.stringify(O>0?C({id:n.id,tombstoned:!0}):K("NOT_FOUND",`Observation ${n.id} not found`),null,2)}case"mem-export":{let n=B.transferExport.parse(S),O=await this.memoryEngine.export("project",{type:n.type,limit:n.limit});return JSON.stringify(C({payload:O,format:n.format}),null,2)}case"mem-import":{let n=B.transferImport.parse(S),O=n.mode==="replace"?"overwrite":"skip-duplicates",M=await this.memoryEngine.import(n.payload,{mode:O});return JSON.stringify(C({imported:M.imported,skipped:M.skipped,mode:n.mode}),null,2)}case"mem-maintenance":{let n=B.maintenance.parse(S);if(n.action==="folderContextDryRun")return JSON.stringify(C(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(n.action==="folderContextClean")return JSON.stringify(C(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);if(n.action==="folderContextPurge")return JSON.stringify(C(await this.memoryEngine.maintainFolderContext("purge",!1)),null,2);return JSON.stringify(C(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"mem-help":return JSON.stringify(C({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(K("NOT_FOUND",`Unknown tool: ${y}`),null,2)}};try{let n=await u(),O=n.includes('"error": {')&&!n.includes('"error": null');return{content:[{type:"text",text:n}],isError:O}}catch(n){if(n instanceof z.ZodError)return{content:[{type:"text",text:JSON.stringify(K("VALIDATION_ERROR",xy(n)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(K("INTERNAL_ERROR",String(n)),null,2)}],isError:!0}}}send(y){process.stdout.write(`${JSON.stringify(y)}
|
|
4
|
+
`)}}function ky(y){if(typeof y!=="object"||y===null)return!1;let S=y,u=S.status;if(u===429||u===500||u===503)return!0;let n=S.error;if(typeof n==="object"&&n!==null&&n.type==="overloaded_error")return!0;return!1}function I(y){if(y&&typeof y==="object"){let S=y.status;if(typeof S==="number")return S===400||S===401||S===403}return!1}class py{shouldFailover(y){let{error:S,attemptIndex:u,totalProviders:n}=y;if(I(S))return!1;if(u>=n-1)return!1;return ky(S)}onFailover(y){let S=y.error?.status??"unknown";if(!y.nextProvider)return;console.error(`[open-mem] Provider ${y.provider} failed (${S}), falling over to ${y.nextProvider}`)}}class Ey{specificationVersion;provider;modelId;supportedUrls;providers;policy;constructor(y,S=new py){if(y.length===0)throw Error("At least one provider required");let u=y[0].model;this.specificationVersion=u.specificationVersion,this.provider=u.provider,this.modelId=u.modelId,this.supportedUrls=u.supportedUrls,this.providers=y,this.policy=S}async doGenerate(y){let S;for(let u=0;u<this.providers.length;u++){let n=this.providers[u];try{return this.policy.onAttempt?.({error:null,provider:n.name,nextProvider:this.providers[u+1]?.name,attemptIndex:u,totalProviders:this.providers.length}),await n.model.doGenerate(y)}catch(O){if(S=O,I(O))throw O;let M=this.providers[u+1]?.name,f={error:O,provider:n.name,nextProvider:M,attemptIndex:u,totalProviders:this.providers.length};if(this.policy.shouldFailover(f)){this.policy.onFailover(f);continue}throw this.policy.onFinalFailure?.(f),O}}throw S}async doStream(y){let S;for(let u=0;u<this.providers.length;u++){let n=this.providers[u];try{return this.policy.onAttempt?.({error:null,provider:n.name,nextProvider:this.providers[u+1]?.name,attemptIndex:u,totalProviders:this.providers.length}),await n.model.doStream(y)}catch(O){if(S=O,I(O))throw O;let M=this.providers[u+1]?.name,f={error:O,provider:n.name,nextProvider:M,attemptIndex:u,totalProviders:this.providers.length};if(this.policy.shouldFailover(f)){this.policy.onFailover(f);continue}throw this.policy.onFinalFailure?.(f),O}}throw S}}var $u={"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 gu(y){if(y.includes("."))return y;return $u[y]||`us.anthropic.${y}-v1:0`}function Iy(y){switch(y.provider){case"anthropic":{let{createAnthropic:S}=H("@ai-sdk/anthropic");return S({apiKey:y.apiKey})(y.model)}case"bedrock":{let{createAmazonBedrock:S}=H("@ai-sdk/amazon-bedrock");return S()(gu(y.model))}case"openai":{let{createOpenAI:S}=H("@ai-sdk/openai");return S({apiKey:y.apiKey})(y.model)}case"google":{let{createGoogleGenerativeAI:S}=H("@ai-sdk/google");return S({apiKey:y.apiKey})(y.model)}case"openrouter":{let{createOpenRouter:S}=H("@openrouter/ai-sdk-provider");return S({apiKey:y.apiKey})(y.model)}default:throw Error(`Unknown provider: ${y.provider}. Supported: anthropic, bedrock, openai, google, openrouter`)}}function qy(y){try{switch(y.provider){case"google":{let{createGoogleGenerativeAI:S}=H("@ai-sdk/google");return S({apiKey:y.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:S}=H("@ai-sdk/openai");return S({apiKey:y.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:S}=H("@ai-sdk/amazon-bedrock");return S().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;case"openrouter":return null;default:return null}}catch{return null}}var Cu={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 Uu(y){switch(y){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 wy(y){if(!y.fallbackProviders||y.fallbackProviders.length===0)return[];return y.fallbackProviders.map((S)=>({provider:S,model:Cu[S]??"gemini-2.5-flash-lite",apiKey:Uu(S)}))}function ly(y,S=[],u){let n=Iy(y);if(S.length===0)return n;let O=[{name:y.provider,model:n},...S.map((M)=>({name:M.provider,model:Iy(M)}))];return new Ey(O,u)}my();import{randomUUID as XS}from"crypto";function hu(y,S){let u=new RegExp(`<${S}[^>]*>([\\s\\S]*?)</${S}>`,"i"),n=y.match(u);return n?n[1].trim():""}function ju(y,S){let u=new RegExp(`<${S}[^>]*>([\\s\\S]*?)</${S}>`,"gi"),n=[];for(let O of y.matchAll(u)){let M=O[1].trim();if(M)n.push(M)}return n}function ty(y){let S=hu(y,"reranked");if(!S)return null;let u=ju(S,"index");if(u.length===0)return null;let n=[];for(let O of u){let M=Number.parseInt(O,10);if(Number.isNaN(M)||M<0)return null;n.push(M)}return n}function Y(y){return Math.ceil(y.length/4)}var vu={showTokenCosts:!0,observationTypes:"all",fullObservationCount:3,showLastSummary:!0},w={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"};function oy(y,S=vu){let u=[];if(u.push("## open-mem: Past Session Memory"),u.push(""),u.push("**\uD83D\uDCA1 Progressive Disclosure:** This is a compact index showing WHAT was observed and retrieval COST."),u.push("Use `mem-find` to find observations by query, then `mem-get` with IDs to fetch full details."),u.push(""),u.push("**3-Layer Memory Access:**"),u.push("- **Layer 1** `mem-find` \u2014 Find observations by query (returns IDs + summaries)"),u.push("- **Layer 2** `mem-history` \u2014 Browse session history and drill into sessions"),u.push("- **Layer 3** `mem-get` \u2014 Get full details by ID (use IDs from search results or the index below)"),u.push(""),u.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."),S.showLastSummary&&y.recentSummaries.length>0){u.push(""),u.push("### Recent Sessions"),u.push("| Session | Summary | Decisions |"),u.push("|---------|---------|-----------|");for(let f of y.recentSummaries){let p=f.keyDecisions.length>0?f.keyDecisions.join("; "):"\u2014";u.push(`| ${f.sessionId} | ${f.summary} | ${p} |`)}}let n=S.observationTypes==="all"?y.observationIndex:y.observationIndex.filter((f)=>S.observationTypes.includes(f.type));if(n.length>0){u.push(""),u.push(`### Recent Observations (${n.length} entries)`);let f=ku(n,y.fullObservations);for(let[p,E]of f){if(u.push(""),u.push(`**${p}**`),S.showTokenCosts)u.push("| ID | Type | Title | ~Tokens |"),u.push("|----|------|-------|---------|");else u.push("| ID | Type | Title |"),u.push("|----|------|-------|");for(let R of E){let N=w[R.type]||"\uD83D\uDCDD";if(S.showTokenCosts)u.push(`| ${R.id} | ${N} | ${R.title} | ~${R.tokenCount} |`);else u.push(`| ${R.id} | ${N} | ${R.title} |`)}}}let O=y.fullObservations.slice(0,S.fullObservationCount);if(O.length>0){u.push(""),u.push("### Full Details (most recent)");for(let f of O){let p=w[f.type]||"\uD83D\uDCDD";if(u.push(""),u.push(`#### ${p} ${f.title} (${f.id})`),u.push(f.narrative),f.facts.length>0)u.push(`**Facts:** ${f.facts.map((R)=>`- ${R}`).join(" ")}`);if(f.concepts.length>0)u.push(`**Concepts:** ${f.concepts.join(", ")}`);let E=[...f.filesRead,...f.filesModified];if(E.length>0)u.push(`**Files:** ${E.join(", ")}`)}}let M=xu(y);if(M)u.push(""),u.push(M);return u.join(`
|
|
5
|
+
`)}function xu(y){let S=0,u=0,n=new Set(y.observationIndex.map((f)=>f.id));for(let f of y.observationIndex)S+=f.tokenCount,u+=f.discoveryTokens;for(let f of y.fullObservations)if(!n.has(f.id))S+=f.tokenCount,u+=f.discoveryTokens;if(u===0)return null;let O=u-S,M=Math.max(0,Math.round(O/u*100));return`### \uD83D\uDCB0 Memory Economics
|
|
6
|
+
**Read cost:** ~${S}t | **Discovery cost:** ~${u}t | **Savings:** ${M}% (${O}t saved)`}function ku(y,S){let u=new Map;for(let O of S){let M=O.filesModified[0]||O.filesRead[0];if(M)u.set(O.id,M)}let n=new Map;for(let O of y){let M=u.get(O.id)??"General",f=n.get(M)??[];f.push(O),n.set(M,f)}return n}function dy(y){let S=[];if(S.push("[open-mem] Memory context:"),y.recentSummaries.length>0){S.push(`
|
|
7
|
+
Recent sessions:`);for(let u of y.recentSummaries)S.push(`- ${u.summary}`)}if(y.observationIndex.length>0){S.push(`
|
|
8
|
+
Recent observations (${y.observationIndex.length} entries):`);for(let u of y.observationIndex)S.push(`- ${w[u.type]||"\uD83D\uDCDD"} ${u.title}`)}return S.join(`
|
|
9
|
+
`)}function ay(y,S){if(y.length===0)return"";let u=S,n=[];for(let M of y){let f=M.tokenCount||Y(M.title);if(u-f<0)break;n.push(M),u-=f}if(n.length===0)return"";let O=[];O.push("### Cross-Project Memory"),O.push(""),O.push("| ID | Type | Title | ~Tokens |"),O.push("|----|------|-------|---------|");for(let M of n){let f=w[M.type]||"\uD83D\uDCDD";O.push(`| ${M.id} | ${f} | ${M.title} | ~${M.tokenCount} |`)}return O.join(`
|
|
10
|
+
`)}function sy(y,S){if(y.length===0)return"";let u=S,n=[];for(let M of y){let f=M.tokenCount||Y(M.title);if(u-f<0)break;n.push(M),u-=f}if(n.length===0)return"";let O=[];O.push(`
|
|
11
|
+
Cross-project observations (${n.length} entries):`);for(let M of n)O.push(`- ${w[M.type]||"\uD83D\uDCDD"} ${M.title}`);return O.join(`
|
|
12
|
+
`)}var b={recency:0.4,typeImportance:0.3,sessionAffinity:0.2,tokenEfficiency:0.1},Iu={decision:1,bugfix:0.9,feature:0.8,refactor:0.6,discovery:0.5,change:0.4};function qu(y,S){let u=new Date(y),O=(S.getTime()-u.getTime())/3600000;if(O<0)return 1;if(O<24)return 1;if(O<48)return 0.8;if(O<168)return 0.5;return 0.2}function wu(y){return Iu[y]??0.3}function lu(y,S){if(!S)return 0.5;return y===S?1:0.3}function Pu(y){if(y<=10)return 1;if(y>=200)return 0.2;return 1-(y-10)/190*0.8}function ru(y,S){let u=qu(y.createdAt,S.now),n=wu(y.type),O=lu(y.sessionId,S.currentSessionId),M=Pu(y.tokenCount);return u*b.recency+n*b.typeImportance+O*b.sessionAffinity+M*b.tokenEfficiency}function yS(y,S){let u=new Map;for(let n of y)u.set(n.id,ru(n,S));return[...y].sort((n,O)=>{let M=u.get(n.id)??0,f=u.get(O.id)??0;if(f!==M)return f-M;return new Date(O.createdAt).getTime()-new Date(n.createdAt).getTime()})}function SS(y,S,u,n,O=[],M){let f=n,p=[],E=[];for(let N of S){let V=N.tokenCount||Y(N.summary);if(f-V<0)break;p.push(N),f-=V}let R=M?yS(u,M):u;for(let N of R){let V=N.tokenCount||Y(N.title);if(f-V<0)break;E.push(N),f-=V}return{recentSummaries:p,observationIndex:E,fullObservations:[...O],totalTokens:n-f}}import{existsSync as Cy}from"fs";import{readdir as un,readFile as RS,unlink as gy,writeFile as NS}from"fs/promises";import{join as Uy,resolve as By}from"path";import{existsSync as nS}from"fs";import{mkdir as eu,readFile as iu,rename as bu,unlink as tu,writeFile as ou}from"fs/promises";import{dirname as t,isAbsolute as _y,join as l,normalize as du,relative as Ay,resolve as D,sep as Vy}from"path";var F="<!-- open-mem-context -->",Q="<!-- /open-mem-context -->",OS={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},uS=new Map,au=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function MS(y,S,u){if(S.length===0)return;if(u.mode==="single")return su(y,S,u);let{maxDepth:n,filename:O}=u,M=[];for(let E of S){for(let R of E.filesModified)M.push(R);for(let R of E.filesRead)M.push(R)}let f=pS(M,y,n);if(f.size===0)return;let p=ES(S,f,y);for(let[E,R]of p)try{let N=yn(E,R,y);await fS(E,N,O)}catch(N){console.error(`[open-mem] Failed to update AGENTS.md in ${E}:`,N)}}async function su(y,S,u){let{maxDepth:n,filename:O}=u,M=S.filter(Jy);if(M.length===0)return;let f=[];for(let _ of M){for(let $ of _.filesModified)f.push($);for(let $ of _.filesRead)f.push($)}let p=pS(f,y,n),E=ES(M,p,y),R=M.filter((_)=>{return[..._.filesModified,..._.filesRead].some((U)=>{if(!U)return!1;let c=_y(U)?U:l(y,U);return D(t(c))===D(y)})});if(R.length>0)E.set(D(y),R);if(E.size===0)return;let N=[];N.push("## Project Activity (auto-generated by open-mem)"),N.push("");let V=[...E.entries()].map(([_,$])=>({relPath:Ay(y,_)||".",observations:$})).sort((_,$)=>_.relPath.localeCompare($.relPath));for(let{relPath:_,observations:$}of V){let U=$.filter(Jy).sort((g,x)=>x.createdAt.localeCompare(g.createdAt)).slice(0,10);if(U.length===0)continue;N.push(`### ${_}/`),N.push("| ID | Type | Title | Date |"),N.push("|----|------|-------|------|");for(let g of U){let x=OS[g.type]||"\uD83D\uDCDD",pu=g.createdAt.split("T")[0],Eu=g.title.replace(/\|/g,"\\|");N.push(`| ${g.id} | ${x} ${g.type} | ${Eu} | ${pu} |`)}let c=new Set;for(let g of U)for(let x of g.concepts)c.add(x);if(c.size>0){let g=[...c].slice(0,10).join(", ");N.push(""),N.push(`**Key concepts:** ${g}`)}let X=U.filter((g)=>g.type==="decision").map((g)=>g.title);if(X.length>0)N.push(""),N.push(`**Recent decisions:** ${X.slice(0,5).join("; ")}`);N.push("")}N.push("\uD83D\uDCA1 *Use `mem-find` to search full details. Use `mem-create` to save important decisions.*");let J=N.join(`
|
|
13
|
+
`);await fS(y,J,O)}function Jy(y){return!/^\w[\w-]*\s+execution$/i.test(y.title)}function yn(y,S,u){let n=[...S].filter(Jy).sort((R,N)=>N.createdAt.localeCompare(R.createdAt)).slice(0,10),O=Ay(u,y)||".",M=[];M.push(`## Recent Activity in \`${O}/\` (auto-generated by open-mem)`),M.push(""),M.push("| ID | Type | Title | Date |"),M.push("|----|------|-------|------|");for(let R of n){let N=OS[R.type]||"\uD83D\uDCDD",V=R.createdAt.split("T")[0],J=R.title.replace(/\|/g,"\\|");M.push(`| ${R.id} | ${N} ${R.type} | ${J} | ${V} |`)}let f=new Set;for(let R of n)for(let N of R.concepts)f.add(N);if(f.size>0){let R=[...f].slice(0,10).join(", ");M.push(""),M.push(`**Key concepts:** ${R}`)}let p=n.filter((R)=>R.type==="decision").map((R)=>R.title);if(p.length>0)M.push(""),M.push(`**Recent decisions:** ${p.slice(0,5).join("; ")}`);let E=n.filter((R)=>R.type==="decision"&&R.narrative).slice(0,3);if(E.length>0){M.push(""),M.push("**Decision details:**");for(let R of E){let N=R.narrative.split(/[.!?]\s/)[0],V=N.length>120?`${N.slice(0,117)}...`:N;M.push(`- \u2696\uFE0F ${R.title}: ${V}`)}}return M.push(""),M.push("\uD83D\uDCA1 *Use `mem-find` to search full details across all sessions. Use `mem-create` to save important decisions.*"),M.join(`
|
|
14
|
+
`)}async function fS(y,S,u){if(!nS(y))return;let O=(uS.get(y)??Promise.resolve()).then(async()=>{let M=l(y,u),f=l(y,`.${u}.tmp`),p="";try{p=await iu(M,"utf-8")}catch{}let E=Sn(p,S);try{await eu(t(f),{recursive:!0}),await ou(f,E,"utf-8"),await bu(f,M)}catch(R){try{await tu(f)}catch{}throw R}});return uS.set(y,O.catch(()=>{})),O}function Sn(y,S){if(!y)return`${F}
|
|
15
|
+
${S}
|
|
16
|
+
${Q}
|
|
17
|
+
`;let u=y.indexOf(F),n=y.indexOf(Q);if(u!==-1&&n!==-1&&n>u){let M=y.substring(0,u),f=y.substring(n+Q.length);return`${M}${F}
|
|
31
18
|
${S}
|
|
32
|
-
|
|
19
|
+
${Q}${f}`}let O=y;if(u!==-1&&n===-1)O=O.replace(F,"").trim();else if(u===-1&&n!==-1)O=O.replace(Q,"").trim();else if(u!==-1&&n!==-1&&n<=u)O=O.replace(Q,"").replace(F,"").trim();return`${O}
|
|
33
20
|
|
|
34
|
-
${
|
|
35
|
-
|
|
21
|
+
${F}
|
|
22
|
+
${S}
|
|
23
|
+
${Q}
|
|
24
|
+
`}function pS(y,S,u){let n=new Set,O=D(S);for(let M of y){if(!M||!M.trim())continue;if(M.startsWith("~")||M.startsWith("http"))continue;let f=_y(M)?M:l(S,M),p=t(f),E=D(p);if(!E.startsWith(O+Vy)&&E!==O)continue;if(E===O)continue;let R=Ay(O,E);if(R.split(Vy).length>u)continue;if(du(R).split(Vy).some((J)=>au.has(J)))continue;if(!nS(E))continue;n.add(E)}return n}function ES(y,S,u){let n=new Map;for(let O of y){let M=[...O.filesModified,...O.filesRead],f=new Set;for(let p of M){if(!p)continue;let E=_y(p)?p:l(u,p),R=D(t(E));if(S.has(R))f.add(R)}for(let p of f){let E=n.get(p)??[];E.push(O),n.set(p,E)}}return n}var $y="<!-- open-mem-context -->",o="<!-- /open-mem-context -->";async function VS(y,S,u){let n;try{n=await un(y,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(let O of n){let M=String(O.name);if(M===".git"||M==="node_modules"||M===".open-mem"||M==="dist")continue;let f=Uy(y,M);if(O.isDirectory())await VS(f,S,u);else if(O.isFile()&&M===S)u.push(f)}}async function Zy(y,S){let u=By(y),n=[];return await VS(u,S,n),n}function mS(y){let S=y.indexOf($y),u=y.indexOf(o);if(S===-1&&u===-1)return y;if(S!==-1&&u===-1){let M=y.replace($y,"").trim();return M?`${M}
|
|
25
|
+
`:""}if(S===-1&&u!==-1){let M=y.replace(o,"").trim();return M?`${M}
|
|
26
|
+
`:""}if(u<=S){let M=y.replace($y,"").replace(o,"").trim();return M?`${M}
|
|
27
|
+
`:""}let n=y.slice(0,S).trimEnd(),O=y.slice(u+o.length).trimStart();if(!n&&!O)return"";if(!n)return`${O}
|
|
28
|
+
`;if(!O)return`${n}
|
|
29
|
+
`;return`${n}
|
|
30
|
+
|
|
31
|
+
${O}
|
|
32
|
+
`}async function JS(y,S,u=!1){let n=await Zy(y,S),O=0;for(let M of n){let f=await RS(M,"utf-8"),p=mS(f);if(p!==f){if(O+=1,!u)if(p==="")await gy(M);else await NS(M,p,"utf-8")}}if(S){let M=Uy(By(y),S);if(Cy(M))try{let f=await RS(M,"utf-8"),p=mS(f);if(p!==f){if(O+=1,!u)if(p==="")await gy(M);else await NS(M,p,"utf-8")}if(!n.includes(M))n.push(M)}catch{}}return{files:n,changed:O}}async function _S(y,S){let u=await Zy(y,S);if(S){let O=Uy(By(y),S);if(Cy(O)&&!u.includes(O))u.push(O)}let n=0;for(let O of u)try{await gy(O),n++}catch{}return{deleted:n,files:u}}async function AS(y,S,u,n,O=!1){let f=S.getAll(y).flatMap((E)=>u.getBySession(E.id));if(O){let E=new Set;for(let R of f)for(let N of[...R.filesRead,...R.filesModified])E.add(N);return{observations:f.length,filesTouched:E.size}}if(!Cy(y))return{observations:0,filesTouched:0};await MS(y,f,{maxDepth:n.maxDepth,mode:n.mode,filename:n.filename});let p=await Zy(y,n.filename);return{observations:f.length,filesTouched:p.length}}class Hy{observations;sessions;summaries;searchOrchestrator;projectPath;config;userObservationRepo;runtimeSnapshotProvider;configAuditStore;maintenanceHistoryStore;configAuditLogFallback=[];maintenanceLogFallback=[];constructor(y){this.observations=y.observations,this.sessions=y.sessions,this.summaries=y.summaries,this.searchOrchestrator=y.searchOrchestrator,this.projectPath=y.projectPath,this.config=y.config,this.userObservationRepo=y.userObservationRepo??null,this.runtimeSnapshotProvider=y.runtimeSnapshotProvider??null,this.configAuditStore=y.configAuditStore??null,this.maintenanceHistoryStore=y.maintenanceHistoryStore??null}getByIdIncludingArchived(y){let S=this.observations;return S.getByIdIncludingArchived?S.getByIdIncludingArchived(y):this.observations.getById(y)}listByProjectWithState(y){let S=this.observations;if(S.listByProject)return S.listByProject(this.projectPath,y);if(y.state!=="current")return[];return this.listObservations({limit:y.limit,offset:y.offset,type:y.type,sessionId:y.sessionId})}async ingest(y){}async processPending(y){return 0}async search(y,S={}){return this.searchOrchestrator.search(y,{type:S.type,limit:S.limit??10,projectPath:this.projectPath,importanceMin:S.importanceMin,importanceMax:S.importanceMax,createdAfter:S.after,createdBefore:S.before,concepts:S.concepts,files:S.files})}async timeline(y={}){if(y.anchor){let u=this.observations.getById(y.anchor);if(!u)return[];let n=y.depthBefore??5,O=y.depthAfter??5,M=this.observations.getAroundTimestamp(u.createdAt,n,O,this.projectPath),f=[...M.filter((E)=>E.createdAt<u.createdAt),u,...M.filter((E)=>E.createdAt>u.createdAt)];return[{session:this.sessions.getById(u.sessionId)??{id:u.sessionId,projectPath:this.projectPath,startedAt:u.createdAt,endedAt:null,status:"completed",observationCount:0,summaryId:null},summary:null,observations:f}]}if(y.sessionId){let u=this.sessions.getById(y.sessionId);if(!u)return[];return[{session:u,summary:this.summaries.getBySessionId(u.id),observations:this.observations.getBySession(u.id)}]}return this.sessions.getRecent(this.projectPath,y.limit??5).map((u)=>({session:u,summary:this.summaries.getBySessionId(u.id),observations:[]}))}async recall(y,S=10){let u=[];for(let n of y.slice(0,S)){let O=this.observations.getById(n);if(O){u.push(O);continue}if(!this.userObservationRepo)continue;let M=this.userObservationRepo.getById(n);if(!M)continue;u.push({...M,sessionId:"",rawToolOutput:"",discoveryTokens:0})}return u}async save(y){if(y.scope==="user"){if(!this.userObservationRepo)return null;return{...this.userObservationRepo.create({type:y.type,title:y.title,subtitle:"",facts:[],narrative:y.narrative,concepts:y.concepts??[],filesRead:[],filesModified:y.files??[],toolName:"mem-create",tokenCount:Y(`${y.title} ${y.narrative}`),importance:y.importance??3,sourceProject:this.projectPath}),sessionId:"",rawToolOutput:"",discoveryTokens:0}}this.sessions.getOrCreate(y.sessionId,this.projectPath);let S=this.observations.create({sessionId:y.sessionId,type:y.type,title:y.title,subtitle:"",facts:[],narrative:y.narrative,concepts:y.concepts??[],filesRead:[],filesModified:y.files??[],rawToolOutput:`[Manual save] ${y.narrative}`,toolName:"mem-create",tokenCount:Y(`${y.title} ${y.narrative}`),discoveryTokens:0,importance:y.importance??3});return this.sessions.incrementObservationCount(y.sessionId),S}async update(y){let S=this.observations.getById(y.id);if(!S)return null;let u=this.sessions.getById(S.sessionId);if(!u||u.projectPath!==this.projectPath)return null;let{id:n,...O}=y;return this.observations.update(y.id,O)??null}async delete(y){let S=0;for(let u of y){let n=this.observations.getById(u);if(!n)continue;let O=this.sessions.getById(n.sessionId);if(!O||O.projectPath!==this.projectPath)continue;if(this.observations.delete(u))S+=1}return S}async export(y,S={}){if(y!=="project")throw Error("Only project scope export is supported.");let u=this.sessions.getAll(this.projectPath),n=[];for(let p of u)n.push(...this.observations.getBySession(p.id));if(S.type)n=n.filter((p)=>p.type===S.type);if(n.sort((p,E)=>new Date(p.createdAt).getTime()-new Date(E.createdAt).getTime()),S.limit&&S.limit<n.length)n=n.slice(0,S.limit);let O=n.map(({rawToolOutput:p,...E})=>E),M=u.map((p)=>this.summaries.getBySessionId(p.id)).filter((p)=>p!==null);return{version:1,exportedAt:new Date().toISOString(),project:this.projectPath,observations:O,summaries:M}}async import(y,S={}){let u;try{u=JSON.parse(y)}catch{throw Error("Invalid JSON payload.")}if(typeof u!=="object"||u===null)throw Error("Invalid import payload.");let n=u;if(n.version!==1||!Array.isArray(n.observations))throw Error("Unsupported export format.");let O=S.mode??"skip-duplicates",M=0,f=0;for(let p of n.observations){let E=this.observations.getById(p.id);if(E&&O==="skip-duplicates"){f+=1;continue}if(E&&O==="overwrite")this.observations.delete(p.id);this.sessions.getOrCreate(p.sessionId,this.projectPath),this.observations.importObservation({id:p.id,sessionId:p.sessionId,type:p.type,title:p.title,subtitle:p.subtitle??"",facts:p.facts??[],narrative:p.narrative??"",concepts:p.concepts??[],filesRead:p.filesRead??[],filesModified:p.filesModified??[],rawToolOutput:p.rawToolOutput??"",toolName:p.toolName??"unknown",createdAt:p.createdAt,tokenCount:p.tokenCount??0,discoveryTokens:p.discoveryTokens??0,importance:p.importance??3,supersededBy:p.supersededBy??null,supersededAt:p.supersededAt??null}),this.sessions.incrementObservationCount(p.sessionId),M+=1}for(let p of n.summaries??[]){let E=this.summaries.getBySessionId(p.sessionId);if(E&&O==="skip-duplicates")continue;if(E&&O==="overwrite")continue;this.sessions.getOrCreate(p.sessionId,this.projectPath),this.summaries.importSummary(p),this.sessions.setSummary(p.sessionId,p.id)}return{imported:M,skipped:f}}async buildContext(y,S="normal"){let u=this.sessions.getRecent(this.projectPath,5),n=u.map((N)=>N.summaryId?this.summaries.getBySessionId(N.id):null).filter((N)=>N!==null),O=this.observations.getIndex(this.projectPath,this.config.maxObservations),f=O.slice(0,this.config.contextFullObservationCount).map((N)=>N.id).map((N)=>this.observations.getById(N)).filter((N)=>N!==null),p=SS(u,n,O,this.config.maxContextTokens,f);if(S==="compaction"){let N=dy(p);if(this.config.userMemoryEnabled&&this.userObservationRepo)N+=sy(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);return N}let E={showTokenCosts:this.config.contextShowTokenCosts,observationTypes:this.config.contextObservationTypes,fullObservationCount:this.config.contextFullObservationCount,showLastSummary:this.config.contextShowLastSummary},R=oy(p,E);if(this.config.userMemoryEnabled&&this.userObservationRepo){let N=ay(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);if(N)R+=`
|
|
33
|
+
|
|
34
|
+
${N}`}return R}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(y){let{limit:S=50,offset:u=0,type:n,sessionId:O,state:M}=y;if(M)return this.listByProjectWithState({limit:S,offset:u,type:n,state:M,sessionId:O});if(O){let E=this.observations.getBySession(O);if(n)E=E.filter((R)=>R.type===n);return E.slice(u,u+S)}let p=this.observations.getIndex(this.projectPath,u+S).slice(u);if(n)p=p.filter((E)=>E.type===n);return p.map((E)=>this.observations.getById(E.id)).filter((E)=>E!==null)}getObservation(y){return this.observations.getById(y)}getLineage(y){let u=this.getByIdIncludingArchived(y);if(!u)return null;let n=u,O=0,M=new Set([u.id]);while(n.revisionOf&&O<256){let N=this.getByIdIncludingArchived(n.revisionOf);if(!N||M.has(N.id))break;n=N,M.add(N.id),O+=1}let f=[],p=n,E=new Set,R=0;while(p&&!E.has(p.id)&&R<256){E.add(p.id);let N=p.deletedAt?"tombstoned":p.supersededBy?"superseded":"current";f.push({id:p.id,revisionOf:p.revisionOf??null,supersededBy:p.supersededBy??null,supersededAt:p.supersededAt??null,deletedAt:p.deletedAt??null,state:N,observation:p}),p=p.supersededBy?this.getByIdIncludingArchived(p.supersededBy):null,R+=1}return f}listSessions(y){return this.sessions.getRecent(y.projectPath??this.projectPath,y.limit??20)}getSession(y){let S=this.sessions.getById(y);if(!S)return null;return{session:S,summary:this.summaries.getBySessionId(y),observations:this.observations.getBySession(y)}}stats(){let y=this.observations.getCount(),u=this.sessions.getAll(this.projectPath).length,n=this.observations.getIndex(this.projectPath,1e4),O=0,M=0,f={};for(let R of n)O+=R.tokenCount,M+=R.discoveryTokens,f[R.type]=(f[R.type]||0)+1;let p=M-O,E=n.length>0?Math.round(O/n.length):0;return{totalObservations:y,totalSessions:u,totalTokensSaved:p,averageObservationSize:E,typeBreakdown:f}}async maintainFolderContext(y,S){if(y==="purge")return{action:"purge",dryRun:!1,...await _S(this.projectPath,this.config.folderContextFilename)};if(y==="rebuild"){let n=await AS(this.projectPath,this.sessions,this.observations,{maxDepth:this.config.folderContextMaxDepth,mode:this.config.folderContextMode,filename:this.config.folderContextFilename},S);return{action:y,dryRun:S,...n}}let u=await JS(this.projectPath,this.config.folderContextFilename,S);return{action:"clean",dryRun:S,...u}}getRevisionDiff(y,S){let u=this.getByIdIncludingArchived(y),n=this.getByIdIncludingArchived(S);if(!u||!n)return null;let O=[],M=(p,E,R)=>{if(JSON.stringify(E)!==JSON.stringify(R))O.push({field:p,before:E,after:R})};M("title",n.title,u.title),M("subtitle",n.subtitle,u.subtitle),M("narrative",n.narrative,u.narrative),M("type",n.type,u.type),M("facts",n.facts,u.facts),M("concepts",n.concepts,u.concepts),M("filesRead",n.filesRead,u.filesRead),M("filesModified",n.filesModified,u.filesModified),M("importance",n.importance,u.importance);let f=O.length===0?"No material changes between revisions.":`Changed ${O.length} field${O.length===1?"":"s"}: ${O.map((p)=>p.field).join(", ")}.`;return{fromId:S,toId:y,summary:f,changedFields:O}}getHealth(){let y=this.runtimeSnapshotProvider?.(),S=y?.queue.lastError?"degraded":"ok";return{status:y?.status??"ok",timestamp:y?.timestamp??new Date().toISOString(),components:{database:{status:"ok"},search:{status:"ok"},config:{status:"ok"},queue:{status:S,detail:y?.queue.lastError??void 0}}}}getMetrics(){let y=this.stats();return{timestamp:this.runtimeSnapshotProvider?.()?.timestamp??new Date().toISOString(),memory:{totalObservations:y.totalObservations,totalSessions:y.totalSessions,totalTokensSaved:y.totalTokensSaved,averageObservationSize:y.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 y={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((u)=>({name:u.name,version:u.version,enabled:y[u.name]??!1,capabilities:u.capabilities}))}getConfigAuditTimeline(){if(this.configAuditStore)return this.configAuditStore.list();return[...this.configAuditLogFallback].reverse()}trackConfigAudit(y){if(this.configAuditStore){this.configAuditStore.append(y);return}this.configAuditLogFallback.push(y)}async rollbackConfig(y){let S=this.configAuditStore?this.configAuditStore.getById(y):this.configAuditLogFallback.find((M)=>M.id===y)??null;if(!S)return null;if(!S.previousValues||typeof S.previousValues!=="object")return null;let{patchConfig:u}=await Promise.resolve().then(() => (ZS(),BS)),n=S.previousValues;try{await u(this.projectPath,n)}catch(M){let f={id:`rollback-failed-${XS()}`,timestamp:new Date().toISOString(),patch:S.previousValues,previousValues:S.patch,source:"rollback-failed"};throw this.trackConfigAudit(f),M}let O={id:`rollback-${XS()}`,timestamp:new Date().toISOString(),patch:S.previousValues,previousValues:S.patch,source:"rollback"};return this.trackConfigAudit(O),O}getMaintenanceHistory(){if(this.maintenanceHistoryStore)return this.maintenanceHistoryStore.list();return[...this.maintenanceLogFallback].reverse()}trackMaintenanceResult(y){if(this.maintenanceHistoryStore){this.maintenanceHistoryStore.append(y);return}this.maintenanceLogFallback.push(y)}}function a(y){try{let S=JSON.parse(y);return S&&typeof S==="object"?S:{}}catch{return{}}}class Ky{db;constructor(y){this.db=y}list(){return this.db.all("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events ORDER BY timestamp DESC").map((y)=>({id:y.id,timestamp:y.timestamp,patch:a(y.patch),previousValues:a(y.previous_values),source:y.source}))}getById(y){let S=this.db.get("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events WHERE id = ?",[y]);if(!S)return null;return{id:S.id,timestamp:S.timestamp,patch:a(S.patch),previousValues:a(S.previous_values),source:S.source}}append(y){this.db.run("INSERT INTO config_audit_events (id, timestamp, patch, previous_values, source) VALUES (?, ?, ?, ?, ?)",[y.id,y.timestamp,JSON.stringify(y.patch??{}),JSON.stringify(y.previousValues??{}),y.source])}}import{Database as FS}from"bun:sqlite";import{existsSync as Yn,mkdirSync as cn}from"fs";import*as GS from"sqlite-vec";import{closeSync as _n,fsyncSync as An,openSync as $n,readFileSync as gn,unlinkSync as YS,writeFileSync as Cn}from"fs";import{hostname as cS}from"os";function HS(y){try{return process.kill(y,0),!0}catch(S){if(S instanceof Error&&"code"in S&&S.code==="EPERM")return!0;return!1}}var zS="plugin";class s extends Error{lockPath;role;waitDurationMs;owner;constructor(y){super(`Timed out acquiring advisory write lock after ${y.waitDurationMs}ms (role=${y.role}, lockPath=${y.lockPath})`);this.name="AdvisoryLockTimeoutError",this.lockPath=y.lockPath,this.role=y.role,this.waitDurationMs=y.waitDurationMs,this.owner=y.owner}}var Un=5000,Bn=50,G=new Map;function Zn(y){if(y<=0)return;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,y)}function KS(y,S){if(typeof y!=="number"||!Number.isFinite(y)||y<=0)return S;return Math.floor(y)}function WS(y){try{let S=gn(y,"utf8").trim();if(!S)return null;let u=JSON.parse(S);if(typeof u!=="object"||u===null||typeof u.pid!=="number"||typeof u.role!=="string"||typeof u.hostname!=="string"||typeof u.acquiredAt!=="string")return null;return{pid:u.pid,role:u.role,hostname:u.hostname,acquiredAt:u.acquiredAt,ownerId:typeof u.ownerId==="string"?u.ownerId:void 0}}catch{return null}}function Xn(y,S){if(!y||!S)return!1;return y.pid===S.pid&&y.role===S.role&&y.hostname===S.hostname&&y.acquiredAt===S.acquiredAt&&y.ownerId===S.ownerId}function Hn(y,S){if(!S)return!1;if(S.hostname!==cS())return!1;if(HS(S.pid))return!1;let u=WS(y);if(!Xn(u,S))return!1;try{return YS(y),!0}catch(n){if(n.code==="ENOENT")return!1;throw n}}function Yy(y,S){_n(S);try{YS(y)}catch(u){if(u.code!=="ENOENT")throw u}}function QS(y){return`${y}.write.lock`}function Kn(y,S){let u=S.now??Date.now,n=KS(S.timeoutMs,Un),O=KS(S.retryIntervalMs,Bn),M=G.get(y);if(M){M.count+=1;let R=!1;return{lockPath:y,role:S.role,waitDurationMs:0,reentrant:!0,release:()=>{if(R)return;R=!0;let N=G.get(y);if(!N)return;if(N.count-=1,N.count===0)G.delete(y),Yy(y,N.fd)}}}let f={pid:process.pid,role:S.role,hostname:cS(),acquiredAt:new Date(u()).toISOString(),ownerId:S.ownerId},p=u(),E=null;for(;;)try{let R=$n(y,"wx");try{Cn(R,JSON.stringify(f),"utf8"),An(R)}catch(V){throw Yy(y,R),V}G.set(y,{count:1,fd:R});let N=!1;return{lockPath:y,role:S.role,waitDurationMs:u()-p,reentrant:!1,release:()=>{if(N)return;N=!0;let V=G.get(y);if(!V)return;if(V.count-=1,V.count===0)G.delete(y),Yy(y,V.fd)}}}catch(R){if(R.code!=="EEXIST")throw R;if(E=WS(y),Hn(y,E))continue;let V=u()-p;if(V>=n)throw new s({lockPath:y,role:S.role,waitDurationMs:V,owner:E});Zn(Math.min(O,n-V))}}function LS(y,S,u){let n=Kn(y,S);try{return u()}finally{n.release()}}var zn=new Set(["SQLITE_BUSY","SQLITE_LOCKED","SQLITE_IOERR","SQLITE_IOERR_VNODE","SQLITE_IOERR_READ","SQLITE_IOERR_WRITE","SQLITE_IOERR_SHORT_READ","SQLITE_IOERR_FSYNC","SQLITE_PROTOCOL"]),Wn=3,DS=50,Qn=new Set(["INSERT","UPDATE","DELETE","REPLACE","CREATE","ALTER","DROP","VACUUM","REINDEX","ANALYZE","ATTACH","DETACH"]),Ln=new Set(["WAL_CHECKPOINT","OPTIMIZE","INCREMENTAL_VACUUM","SHRINK_MEMORY"]),Fn=/^(?:\s+|--[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)+/;function Dn(y){let S=y;for(;;){let u=S.replace(Fn,"");if(u===S)return S.trimStart();S=u}}function Gn(y){let S=[],u=0,n=!1,O=!1,M=!1,f=!1,p=!1,E=!1;for(let N=0;N<y.length;N+=1){let V=y[N],J=y[N+1];if(p){if(V===`
|
|
36
|
+
`)p=!1;continue}if(E){if(V==="*"&&J==="/")E=!1,N+=1;continue}if(n){if(V==="'")if(J==="'")N+=1;else n=!1;continue}if(O){if(V==='"')if(J==='"')N+=1;else O=!1;continue}if(M){if(V==="`")M=!1;continue}if(f){if(V==="]")f=!1;continue}if(V==="-"&&J==="-"){p=!0,N+=1;continue}if(V==="/"&&J==="*"){E=!0,N+=1;continue}if(V==="'"){n=!0;continue}if(V==='"'){O=!0;continue}if(V==="`"){M=!0;continue}if(V==="["){f=!0;continue}if(V===";"){let _=y.slice(u,N).trim();if(_.length>0)S.push(_);u=N+1}}let R=y.slice(u).trim();if(R.length>0)S.push(R);return S}function Tn(y){let S=Dn(y);if(!S)return!1;let u=S.toUpperCase();if(/\bRETURNING\b/.test(u))return!0;if(u.startsWith("PRAGMA")){if(/^PRAGMA\s+(?:[A-Z0-9_]+\.)?[A-Z0-9_]+\s*=/.test(u))return!0;let O=/^PRAGMA\s+(?:[A-Z0-9_]+\.)?([A-Z0-9_]+)/.exec(u)?.[1];if(!O)return!1;return Ln.has(O)}let n=/^[A-Z]+/.exec(u)?.[0];if(!n)return!1;if(Qn.has(n))return!0;if(n==="WITH")return/\b(INSERT|UPDATE|DELETE|REPLACE)\b/.test(u);return!1}function cy(y){let S=Gn(y);if(S.length===0)return!1;for(let u of S)if(Tn(u))return!0;return!1}var hn=new Set(["PASSIVE","FULL","RESTART","TRUNCATE"]);function r(y){if(y instanceof Error){let S=y.code;return{code:typeof S==="string"?S:"UNKNOWN",message:y.message}}return{code:"UNKNOWN",message:String(y)}}function jn(y){if(y&&typeof y==="object"&&"code"in y){let S=y.code;return zn.has(S)}return!1}class yy{db;dbPath;advisoryWriteLockPath;processRole;transactionDepth=0;_hasVectorExtension=!1;static enableExtensionSupport(){let y=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let S of y)try{if(Yn(S))return FS.setCustomSQLite(S),!0}catch{return!1}return!1}constructor(y,S={}){this.dbPath=y,this.processRole=S.processRole??zS,this.advisoryWriteLockPath=QS(y),this.db=this.open(y),this.configure()}open(y){let S=y.lastIndexOf("/");if(S>0){let u=y.substring(0,S);cn(u,{recursive:!0})}return new FS(y,{create:!0})}configure(){this.runConfigureStage("applyPragmas",()=>this.applyPragmas()),this.runConfigureStage("loadExtensions",()=>this.loadExtensions())}runConfigureStage(y,S){try{S()}catch(u){this.throwConfigureFailure(y,u)}}throwConfigureFailure(y,S){let u=r(S);try{this.db.close()}catch{}throw console.error("[open-mem] Database configure failed (non-destructive fail-safe)",{stage:y,dbPath:this.dbPath,sqliteCode:u.code,sqliteMessage:u.message,action:"startup-abort",deletionAttempted:!1}),Error(`Database startup failed during ${y} (fail-safe, non-destructive): [${u.code}] ${u.message}`)}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{GS.load(this.db),this._hasVectorExtension=!0}catch(y){let S=r(y);console.warn("[open-mem] SQLite extension load skipped",{stage:"loadExtensions",dbPath:this.dbPath,sqliteCode:S.code,sqliteMessage:S.message,action:"continue-without-extension"}),this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}ensureMigrationTable(){this.db.exec(`
|
|
36
37
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
37
38
|
version INTEGER PRIMARY KEY,
|
|
38
39
|
name TEXT NOT NULL,
|
|
39
40
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
40
41
|
)
|
|
41
|
-
`)}migrate(
|
|
42
|
+
`)}migrate(y){this.withAdvisoryWriteLock(this.processRole,()=>{this.ensureMigrationTable();let S=this.withRetry("migrate.applied_versions",()=>{return this.db.query("SELECT version FROM _migrations ORDER BY version").all()}),u=new Set(S.map((O)=>O.version)),n=y.filter((O)=>!u.has(O.version)).sort((O,M)=>O.version-M.version);for(let O of n)this.transaction(()=>{this.exec(O.up),this.run("INSERT INTO _migrations (version, name) VALUES ($version, $name)",[{$version:O.version,$name:O.name}])})})}withRetry(y,S){let u=this.transactionDepth>0?0:Wn,n;for(let O=0;O<=u;O++)try{return S()}catch(M){if(n=M,!jn(M)||O===u)throw M;let f=DS*2**O+Math.random()*DS;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,f);let p=r(M);console.warn("[open-mem] Retrying after transient SQLite error",{attempt:O+1,maxRetries:u,operation:y,role:this.processRole,dbPath:this.dbPath,sqliteCode:p.code,sqliteMessage:p.message})}throw n}run(y,S){this.withAdvisoryWriteLock(this.processRole,()=>{this.withRetry("run",()=>{let u=this.db.query(y);if(S)u.run(...S);else u.run()})})}get(y,S){let u=()=>{let n=this.db.query(y);return S?n.get(...S):n.get()};if(cy(y))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("get",u));return this.withRetry("get",u)}all(y,S){let u=()=>{let n=this.db.query(y);return S?n.all(...S):n.all()};if(cy(y))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("all",u));return this.withRetry("all",u)}exec(y){let S=()=>this.withRetry("exec",()=>this.db.exec(y));if(cy(y)){this.withAdvisoryWriteLock(this.processRole,S);return}S()}transaction(y){return this.withAdvisoryWriteLock(this.processRole,()=>{if(this.transactionDepth>0)return y();let S=this.db.transaction(y);if(typeof S.immediate==="function"){this.transactionDepth+=1;try{return S.immediate()}finally{this.transactionDepth-=1}}this.db.exec("BEGIN IMMEDIATE"),this.transactionDepth+=1;try{let u=y();return this.db.exec("COMMIT"),u}catch(u){let n=u;try{this.db.exec("ROLLBACK")}catch(O){if(n instanceof Error){let M=n;if(M.cause===void 0)M.cause=O;else M.suppressed=[...M.suppressed??[],O]}console.warn("[open-mem] Transaction rollback failed after transaction error",{dbPath:this.dbPath,originalError:r(n),rollbackError:r(O)})}throw n}finally{this.transactionDepth-=1}})}get writeLockPath(){return this.advisoryWriteLockPath}withAdvisoryWriteLock(y,S,u){try{return LS(this.advisoryWriteLockPath,{...u,role:y},S)}catch(n){if(n instanceof s)console.error("[open-mem] Advisory write lock timeout",{role:y,dbPath:this.dbPath,lockPath:n.lockPath,waitDurationMs:n.waitDurationMs,owner:n.owner});throw n}}checkpointWal(y="PASSIVE"){let S=typeof y==="string"?y.toUpperCase():"";if(!hn.has(S))throw Error(`Invalid wal_checkpoint mode: ${String(y)}`);return this.withAdvisoryWriteLock(this.processRole,()=>{return this.withRetry("maintenance.wal_checkpoint",()=>{let u=this.db.query(`PRAGMA wal_checkpoint(${S})`).get();if(!u)throw Error("wal_checkpoint returned no result row");return{mode:S,busy:u.busy??0,logFrames:u.log??0,checkpointedFrames:u.checkpointed??0}})})}integrityCheck(y=1){let S=Number.isFinite(y)?Math.max(1,Math.floor(y)):1;return this.withRetry("maintenance.integrity_check",()=>{let u=this.db.query(`PRAGMA integrity_check(${S})`).all();if(u.length===0)throw Error("integrity_check returned no result rows");let n=u.map((O)=>Object.values(O).find((M)=>typeof M==="string")).filter((O)=>typeof O==="string").map((O)=>O.trim()).filter((O)=>O.length>0);if(n.length===0)throw Error("integrity_check returned no diagnostic messages");return{ok:n.length===1&&n[0].toLowerCase()==="ok",messages:n,maxErrors:S}})}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function Sy(y,S){return new yy(y,S)}import{randomUUID as TS}from"crypto";class zy{db;constructor(y){this.db=y}upsertEntity(y,S){let u=TS(),n=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
|
|
42
43
|
VALUES (?, ?, ?, ?, ?, 1)
|
|
43
44
|
ON CONFLICT(name, entity_type) DO UPDATE SET
|
|
44
45
|
mention_count = mention_count + 1,
|
|
45
|
-
last_seen_at = ?`,[y,n,
|
|
46
|
+
last_seen_at = ?`,[u,y,S,n,n,n]);let O=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[y,S]);if(!O)throw Error(`Failed to upsert entity: ${y} (${S})`);return this.mapEntityRow(O)}createRelation(y,S,u,n){let O=TS(),M=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
|
|
46
47
|
(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 = ?`,[
|
|
48
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[O,y,S,u,n,M])}catch{return null}let f=this.db.get(`SELECT * FROM entity_relations
|
|
49
|
+
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[y,S,u]);return f?this.mapRelationRow(f):null}linkObservation(y,S){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[y,S])}findByName(y){try{return this.db.all(`SELECT e.*
|
|
49
50
|
FROM entities e
|
|
50
51
|
JOIN entities_fts fts ON e._rowid = fts.rowid
|
|
51
52
|
WHERE entities_fts MATCH ?
|
|
52
|
-
ORDER BY rank`,[
|
|
53
|
-
WHERE source_entity_id = ? OR target_entity_id = ?`,[
|
|
53
|
+
ORDER BY rank`,[y]).map((u)=>this.mapEntityRow(u))}catch{return[]}}getRelationsFor(y){return this.db.all(`SELECT * FROM entity_relations
|
|
54
|
+
WHERE source_entity_id = ? OR target_entity_id = ?`,[y,y]).map((u)=>this.mapRelationRow(u))}traverseRelations(y,S=1){let u=Math.min(S,2),n=100,O=new Set,M=[{id:y,currentDepth:0}];O.add(y);while(M.length>0){if(O.size>=100)break;let f=M.shift();if(!f)continue;if(f.currentDepth>=u)continue;let p=this.getRelationsFor(f.id);for(let E of p){let R=E.sourceEntityId===f.id?E.targetEntityId:E.sourceEntityId;if(!O.has(R))O.add(R),M.push({id:R,currentDepth:f.currentDepth+1})}}return O}getObservationsForEntity(y){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[y]).map((u)=>u.observation_id)}getById(y){let S=this.db.get("SELECT * FROM entities WHERE id = ?",[y]);return S?this.mapEntityRow(S):null}mapEntityRow(y){return{id:y.id,name:y.name,entityType:y.entity_type,firstSeenAt:y.first_seen_at,lastSeenAt:y.last_seen_at,mentionCount:y.mention_count}}mapRelationRow(y){return{id:y.id,sourceEntityId:y.source_entity_id,targetEntityId:y.target_entity_id,relationship:y.relationship,observationId:y.observation_id,createdAt:y.created_at}}}function vn(y){try{let S=JSON.parse(y);return S&&typeof S==="object"?S:{}}catch{return{}}}class Wy{db;constructor(y){this.db=y}list(){return this.db.all("SELECT id, timestamp, action, dry_run, result FROM maintenance_history ORDER BY timestamp DESC").map((y)=>({id:y.id,timestamp:y.timestamp,action:y.action,dryRun:y.dry_run===1,result:vn(y.result)}))}append(y){this.db.run("INSERT INTO maintenance_history (id, timestamp, action, dry_run, result) VALUES (?, ?, ?, ?, ?)",[y.id,y.timestamp,y.action,y.dryRun?1:0,JSON.stringify(y.result??{})])}}import{randomUUID as kn}from"crypto";import{embed as xn}from"ai";async function uy(y,S){try{let{embedding:u}=await xn({model:y,value:S});return u}catch{return null}}function T(y,S){if(y.length!==S.length||y.length===0)return 0;let u=0,n=0,O=0;for(let f=0;f<y.length;f++)u+=y[f]*S[f],n+=y[f]*y[f],O+=S[f]*S[f];let M=Math.sqrt(n)*Math.sqrt(O);if(M===0)return 0;return u/M}function In(y){return y.replace(/[%_\\]/g,"\\$&")}class Qy{db;constructor(y){this.db=y}create(y){let S=kn(),u=new Date().toISOString(),n=y.discoveryTokens??0,O=y.importance??3,M=y.scope??"project";return this.db.run(`INSERT INTO observations
|
|
54
55
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
55
56
|
concepts, files_read, files_modified, raw_tool_output,
|
|
56
57
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
57
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
58
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[S,y.sessionId,M,y.type,y.title,y.subtitle,JSON.stringify(y.facts),y.narrative,JSON.stringify(y.concepts),JSON.stringify(y.filesRead),JSON.stringify(y.filesModified),y.rawToolOutput,y.toolName,u,y.tokenCount,n,O,null,null]),{...y,id:S,scope:M,createdAt:u,discoveryTokens:n,importance:O,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(y){this.db.run(`INSERT INTO observations
|
|
58
59
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
59
60
|
concepts, files_read, files_modified, raw_tool_output,
|
|
60
61
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
61
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
62
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[y.id,y.sessionId,y.scope??"project",y.type,y.title,y.subtitle,JSON.stringify(y.facts),y.narrative,JSON.stringify(y.concepts),JSON.stringify(y.filesRead),JSON.stringify(y.filesModified),y.rawToolOutput,y.toolName,y.createdAt,y.tokenCount,y.discoveryTokens??0,y.importance??3,y.revisionOf??null,y.deletedAt??null])}getById(y){let S=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[y]);return S?this.mapRow(S):null}getByIdIncludingArchived(y){let S=this.db.get("SELECT * FROM observations WHERE id = ?",[y]);return S?this.mapRow(S):null}getBySession(y){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",[y]).map((S)=>this.mapRow(S))}getCount(y){if(y)return this.db.get("SELECT COUNT(*) as count FROM observations WHERE session_id = ?",[y])?.count??0;return this.db.get("SELECT COUNT(*) as count FROM observations")?.count??0}getIndex(y,S=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
63
|
FROM observations o
|
|
63
64
|
JOIN sessions s ON o.session_id = s.id
|
|
64
65
|
WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
65
66
|
ORDER BY o.created_at DESC
|
|
66
|
-
LIMIT ?`,[
|
|
67
|
+
LIMIT ?`,[y,S]).map((u)=>({id:u.id,sessionId:u.session_id,type:u.type,title:u.title,tokenCount:u.token_count,discoveryTokens:u.discovery_tokens??0,createdAt:u.created_at,importance:u.importance??3}))}getAroundTimestamp(y,S,u,n){let O=S>0?this.db.all(`SELECT o.*
|
|
67
68
|
FROM observations o
|
|
68
69
|
JOIN sessions s ON o.session_id = s.id
|
|
69
70
|
WHERE s.project_path = ? AND o.created_at < ?
|
|
70
71
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
71
72
|
ORDER BY o.created_at DESC
|
|
72
|
-
LIMIT ?`,[
|
|
73
|
+
LIMIT ?`,[n,y,S]).reverse():[],M=u>0?this.db.all(`SELECT o.*
|
|
73
74
|
FROM observations o
|
|
74
75
|
JOIN sessions s ON o.session_id = s.id
|
|
75
76
|
WHERE s.project_path = ? AND o.created_at > ?
|
|
76
77
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
77
78
|
ORDER BY o.created_at ASC
|
|
78
|
-
LIMIT ?`,[
|
|
79
|
+
LIMIT ?`,[n,y,u]):[];return[...O,...M].map((f)=>this.mapRow(f))}listByProject(y,S={}){let{limit:u=50,offset:n=0,type:O,state:M,sessionId:f}=S,p=`SELECT o.*
|
|
79
80
|
FROM observations o
|
|
80
81
|
JOIN sessions s ON o.session_id = s.id
|
|
81
|
-
WHERE s.project_path = ?`,
|
|
82
|
+
WHERE s.project_path = ?`,E=[y];if(f)p+=" AND o.session_id = ?",E.push(f);if(O)p+=" AND o.type = ?",E.push(O);if(M==="current")p+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(M==="superseded")p+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(M==="tombstoned")p+=" AND o.deleted_at IS NOT NULL";else p+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return p+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",E.push(u,n),this.db.all(p,E).map((R)=>this.mapRow(R))}search(y){let S=!!y.projectPath,u=`
|
|
82
83
|
SELECT o.*, rank
|
|
83
84
|
FROM observations o
|
|
84
85
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
85
|
-
${
|
|
86
|
+
${S?"JOIN sessions s ON o.session_id = s.id":""}
|
|
86
87
|
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 '\\'))`);
|
|
88
|
+
`,n=[y.query];if(S&&y.projectPath)u+=" AND s.project_path = ?",n.push(y.projectPath);if(y.sessionId)u+=" AND o.session_id = ?",n.push(y.sessionId);if(y.type)u+=" AND o.type = ?",n.push(y.type);if(y.importanceMin!==void 0)u+=" AND o.importance >= ?",n.push(y.importanceMin);if(y.importanceMax!==void 0)u+=" AND o.importance <= ?",n.push(y.importanceMax);if(y.createdAfter)u+=" AND o.created_at >= ?",n.push(y.createdAfter);if(y.createdBefore)u+=" AND o.created_at <= ?",n.push(y.createdBefore);if(y.concepts&&y.concepts.length>0){let O=y.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");u+=` AND (${O.join(" OR ")})`;for(let M of y.concepts)n.push(M)}if(y.files&&y.files.length>0){let O=y.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
|
|
89
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);u+=` AND (${O.join(" OR ")})`;for(let M of y.files){let f=`%${In(M)}%`;n.push(f,f)}}return u+=" ORDER BY rank LIMIT ? OFFSET ?",n.push(y.limit??10),n.push(y.offset??0),this.db.all(u,n).map((O)=>({observation:this.mapRow(O),rank:O.rank,snippet:O.title}))}searchByConcept(y,S=10,u){let n=!!u,O=`SELECT o.*
|
|
89
90
|
FROM observations o
|
|
90
91
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
91
|
-
${
|
|
92
|
+
${n?"JOIN sessions s ON o.session_id = s.id":""}
|
|
92
93
|
WHERE observations_fts MATCH ?
|
|
93
94
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
94
|
-
${
|
|
95
|
+
${n?"AND s.project_path = ?":""}
|
|
95
96
|
ORDER BY rank
|
|
96
|
-
LIMIT ?`,
|
|
97
|
+
LIMIT ?`,f=[`concepts:"${y.replace(/"/g,'""')}"`];if(n&&u)f.push(u);return f.push(S),this.db.all(O,f).map((p)=>this.mapRow(p))}searchByFile(y,S=10,u){let n=!!u,O=`SELECT o.*
|
|
97
98
|
FROM observations o
|
|
98
99
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
99
|
-
${
|
|
100
|
+
${n?"JOIN sessions s ON o.session_id = s.id":""}
|
|
100
101
|
WHERE observations_fts MATCH ?
|
|
101
102
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
102
|
-
${
|
|
103
|
+
${n?"AND s.project_path = ?":""}
|
|
103
104
|
ORDER BY rank
|
|
104
|
-
LIMIT ?`,
|
|
105
|
+
LIMIT ?`,M=[`files_read:"${y.replace(/"/g,'""')}" OR files_modified:"${y.replace(/"/g,'""')}"`];if(n&&u)M.push(u);return M.push(S),this.db.all(O,M).map((f)=>this.mapRow(f))}setEmbedding(y,S){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(S),y])}getWithEmbeddings(y,S){return this.db.all(`SELECT o.id, o.embedding, o.title
|
|
105
106
|
FROM observations o
|
|
106
107
|
JOIN sessions s ON o.session_id = s.id
|
|
107
108
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
108
109
|
ORDER BY o.created_at DESC
|
|
109
|
-
LIMIT ?`,[
|
|
110
|
+
LIMIT ?`,[y,S]).map((u)=>{try{return{id:u.id,embedding:JSON.parse(u.embedding),title:u.title}}catch{return null}}).filter((u)=>u!==null)}findSimilar(y,S,u,n){let O=this.db.all(`SELECT id, embedding FROM observations
|
|
110
111
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
111
112
|
ORDER BY created_at DESC
|
|
112
|
-
LIMIT 200`,[
|
|
113
|
+
LIMIT 200`,[S]),M=[];for(let f of O)try{let p=JSON.parse(f.embedding);if(!Array.isArray(p)||p.length!==y.length)continue;let E=T(y,p);if(E>=u)M.push({id:f.id,similarity:E})}catch{}return M.sort((f,p)=>p.similarity-f.similarity).slice(0,n)}insertVecEmbedding(y,S){let u=new Float32Array(S);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[y]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[y,u]),this.db.run("COMMIT")}catch(n){throw this.db.run("ROLLBACK"),n}}migrateExistingEmbeddings(y){let S=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),u=0,n=0;for(let O of S)try{let M=JSON.parse(O.embedding);if(!Array.isArray(M)||M.length!==y){n++;continue}this.insertVecEmbedding(O.id,M),u++}catch{n++}return{migrated:u,skipped:n}}getVecEmbeddingMatches(y,S){try{let u=new Float32Array(y);return this.db.all(`SELECT observation_id, distance
|
|
113
114
|
FROM observation_embeddings
|
|
114
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
115
|
+
WHERE embedding MATCH ? AND k = ?`,[u,S]).map((n)=>({observationId:n.observation_id,distance:n.distance}))}catch{return[]}}searchVecSubset(y,S,u){if(S.length===0)return[];try{let n=new Float32Array(y),O=Math.max(u*5,S.length),M=this.db.all(`SELECT observation_id, distance
|
|
115
116
|
FROM observation_embeddings
|
|
116
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
117
|
+
WHERE embedding MATCH ? AND k = ?`,[n,O]),f=new Set(S);return M.filter((p)=>f.has(p.observation_id)).slice(0,u).map((p)=>({observationId:p.observation_id,distance:p.distance}))}catch{return[]}}update(y,S){let u=this.getById(y);if(!u)return null;if(Object.keys(S).length===0)return u;let n=this.create({sessionId:u.sessionId,scope:u.scope??"project",type:S.type??u.type,title:S.title??u.title,subtitle:S.subtitle??u.subtitle,facts:S.facts??u.facts,narrative:S.narrative??u.narrative,concepts:S.concepts??u.concepts,filesRead:S.filesRead??u.filesRead,filesModified:S.filesModified??u.filesModified,rawToolOutput:u.rawToolOutput,toolName:"mem-revise",tokenCount:u.tokenCount,discoveryTokens:u.discoveryTokens,importance:S.importance??u.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[y,n.id]),this.supersede(y,n.id),this.getById(n.id)}supersede(y,S){let u=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[S,u,y])}delete(y){if(this.db.all("SELECT id FROM observations WHERE id = ?",[y]).length===0)return!1;let u=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[u,y]),this.deleteEmbeddingsForObservations([y]),!0}getLineage(y){let S=this.getByIdIncludingArchived(y);if(!S)return[];let u=new Set([S.id]),n=[S];while(n[0].revisionOf){let O=this.getByIdIncludingArchived(n[0].revisionOf);if(!O||u.has(O.id))break;n.unshift(O),u.add(O.id)}while(n[n.length-1].supersededBy){let O=n[n.length-1].supersededBy;if(!O)break;let M=this.getByIdIncludingArchived(O);if(!M||u.has(M.id))break;n.push(M),u.add(M.id)}return n}deleteOlderThan(y){return this.db.all(`DELETE FROM observations
|
|
117
118
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
118
119
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
119
|
-
RETURNING id`,[
|
|
120
|
+
RETURNING id`,[y]).length}deleteEmbeddingsForObservations(y){if(y.length===0)return;let S=y.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${S})`,y)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${S})`,y)}mapRow(y){return{id:y.id,sessionId:y.session_id,scope:y.scope??"project",type:y.type,title:y.title,subtitle:y.subtitle,facts:JSON.parse(y.facts),narrative:y.narrative,concepts:JSON.parse(y.concepts),filesRead:JSON.parse(y.files_read),filesModified:JSON.parse(y.files_modified),rawToolOutput:y.raw_tool_output,toolName:y.tool_name,createdAt:y.created_at,tokenCount:y.token_count,discoveryTokens:y.discovery_tokens??0,importance:y.importance??3,revisionOf:y.revision_of??null,deletedAt:y.deleted_at??null,supersededBy:y.superseded_by??null,supersededAt:y.superseded_at??null}}}var qn=[{version:1,name:"create-schema",up:`
|
|
120
121
|
-- Sessions table
|
|
121
122
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
122
123
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -410,24 +411,24 @@ ${E}`}return M}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
410
411
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
411
412
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
412
413
|
END;
|
|
413
|
-
`}];function
|
|
414
|
+
`}];function hS(y,S){if(y.migrate(qn),S?.hasVectorExtension&&S?.embeddingDimension&&S.embeddingDimension>0)wn(y,S.embeddingDimension)}function wn(y,S){if(y.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let n=y.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(n&&Number(n.value)!==S){console.warn(`[open-mem] vec0 table exists with dimension ${n.value}, but config specifies ${S}. Drop observation_embeddings to re-create with new dimension.`);return}}else y.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
414
415
|
observation_id TEXT PRIMARY KEY,
|
|
415
|
-
embedding float[${
|
|
416
|
-
)`);
|
|
417
|
-
VALUES (?, ?, ?, 'active')`,[
|
|
416
|
+
embedding float[${S}] distance_metric=cosine
|
|
417
|
+
)`);y.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(S)])}class Ly{db;constructor(y){this.db=y}create(y,S){let u=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
|
|
418
|
+
VALUES (?, ?, ?, 'active')`,[y,S,u]),this.getById(y)}getOrCreate(y,S){let u=this.getById(y);if(u)return u;return this.create(y,S)}getById(y){let S=this.db.get("SELECT * FROM sessions WHERE id = ?",[y]);return S?this.mapRow(S):null}getRecent(y,S=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[y,S]).map((u)=>this.mapRow(u))}getAll(y){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[y]).map((S)=>this.mapRow(S))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((y)=>this.mapRow(y))}updateStatus(y,S){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[S,y])}markCompleted(y){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[y])}incrementObservationCount(y){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[y])}setSummary(y,S){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[S,y])}mapRow(y){return{id:y.id,projectPath:y.project_path,startedAt:y.started_at,endedAt:y.ended_at??null,status:y.status,observationCount:y.observation_count,summaryId:y.summary_id??null}}}import{randomUUID as ln}from"crypto";class Fy{db;constructor(y){this.db=y}create(y){let S=ln(),u=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
|
|
418
419
|
(id, session_id, summary, key_decisions, files_modified,
|
|
419
420
|
concepts, created_at, token_count,
|
|
420
421
|
request, investigated, learned, completed, next_steps)
|
|
421
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
422
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[S,y.sessionId,y.summary,JSON.stringify(y.keyDecisions),JSON.stringify(y.filesModified),JSON.stringify(y.concepts),u,y.tokenCount,y.request??"",y.investigated??"",y.learned??"",y.completed??"",y.nextSteps??""]),{...y,id:S,createdAt:u}}importSummary(y){this.db.run(`INSERT INTO session_summaries
|
|
422
423
|
(id, session_id, summary, key_decisions, files_modified,
|
|
423
424
|
concepts, created_at, token_count,
|
|
424
425
|
request, investigated, learned, completed, next_steps)
|
|
425
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
426
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[y.id,y.sessionId,y.summary,JSON.stringify(y.keyDecisions),JSON.stringify(y.filesModified),JSON.stringify(y.concepts),y.createdAt,y.tokenCount,y.request??"",y.investigated??"",y.learned??"",y.completed??"",y.nextSteps??""])}getBySessionId(y){let S=this.db.get("SELECT * FROM session_summaries WHERE session_id = ?",[y]);return S?this.mapRow(S):null}getRecent(y=10){return this.db.all("SELECT * FROM session_summaries ORDER BY created_at DESC LIMIT ?",[y]).map((S)=>this.mapRow(S))}search(y,S=10){return this.db.all(`SELECT ss.*
|
|
426
427
|
FROM session_summaries ss
|
|
427
428
|
JOIN summaries_fts fts ON ss._rowid = fts.rowid
|
|
428
429
|
WHERE summaries_fts MATCH ?
|
|
429
430
|
ORDER BY rank
|
|
430
|
-
LIMIT ?`,[
|
|
431
|
+
LIMIT ?`,[y,S]).map((u)=>this.mapRow(u))}mapRow(y){return{id:y.id,sessionId:y.session_id,summary:y.summary,keyDecisions:JSON.parse(y.key_decisions),filesModified:JSON.parse(y.files_modified),concepts:JSON.parse(y.concepts),createdAt:y.created_at,tokenCount:y.token_count,request:y.request||void 0,investigated:y.investigated||void 0,learned:y.learned||void 0,completed:y.completed||void 0,nextSteps:y.next_steps||void 0}}}import{randomUUID as Pn}from"crypto";var rn=[{version:1,name:"create-user-observations",up:`
|
|
431
432
|
CREATE TABLE IF NOT EXISTS user_observations (
|
|
432
433
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
433
434
|
id TEXT UNIQUE NOT NULL,
|
|
@@ -498,21 +499,21 @@ ${E}`}return M}guide(){return["# open-mem Workflow Guide","","## Reading Memorie
|
|
|
498
499
|
new.facts, new.concepts, new.files_read, new.files_modified
|
|
499
500
|
);
|
|
500
501
|
END;
|
|
501
|
-
`}];class
|
|
502
|
+
`}];class Dy{db;constructor(y){let S=en(y);this.db=Sy(S),this.initializeUserSchema()}initializeUserSchema(){this.db.migrate(rn)}get database(){return this.db}close(){this.db.close()}}class Gy{db;constructor(y){this.db=y}create(y){let S=Pn(),u=new Date().toISOString();return this.db.run(`INSERT INTO user_observations
|
|
502
503
|
(id, type, title, subtitle, facts, narrative,
|
|
503
504
|
concepts, files_read, files_modified, tool_name,
|
|
504
505
|
created_at, token_count, importance, source_project)
|
|
505
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
506
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[S,y.type,y.title,y.subtitle,JSON.stringify(y.facts),y.narrative,JSON.stringify(y.concepts),JSON.stringify(y.filesRead),JSON.stringify(y.filesModified),y.toolName,u,y.tokenCount,y.importance??3,y.sourceProject]),{...y,id:S,createdAt:u,importance:y.importance??3}}search(y){try{let S=`
|
|
506
507
|
SELECT o.*, rank
|
|
507
508
|
FROM user_observations o
|
|
508
509
|
JOIN user_observations_fts fts ON o._rowid = fts.rowid
|
|
509
510
|
WHERE user_observations_fts MATCH ?
|
|
510
|
-
`,
|
|
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(`
|
|
511
|
+
`,u=[y.query];if(y.sourceProject)S+=" AND o.source_project = ?",u.push(y.sourceProject);return S+=" ORDER BY rank LIMIT ?",u.push(y.limit??10),this.db.all(S,u).map((n)=>({observation:this.mapRow(n),rank:n.rank}))}catch{return[]}}getIndex(y,S){let u=`SELECT id, type, title, token_count, created_at, importance, source_project
|
|
512
|
+
FROM user_observations`,n=[];if(S)u+=" WHERE source_project = ?",n.push(S);return u+=" ORDER BY created_at DESC LIMIT ?",n.push(y??20),this.db.all(u,n).map((O)=>({id:O.id,sessionId:"",type:O.type,title:O.title,tokenCount:O.token_count,discoveryTokens:0,createdAt:O.created_at,importance:O.importance??3}))}getById(y){let S=this.db.get("SELECT * FROM user_observations WHERE id = ?",[y]);return S?this.mapRow(S):null}delete(y){return this.db.all("DELETE FROM user_observations WHERE id = ? RETURNING id",[y]).length>0}mapRow(y){return{id:y.id,type:y.type,title:y.title,subtitle:y.subtitle,facts:JSON.parse(y.facts),narrative:y.narrative,concepts:JSON.parse(y.concepts),filesRead:JSON.parse(y.files_read),filesModified:JSON.parse(y.files_modified),toolName:y.tool_name,createdAt:y.created_at,tokenCount:y.token_count,importance:y.importance??3,sourceProject:y.source_project}}}function en(y){if(y.startsWith("~/")){let S=process.env.HOME||process.env.USERPROFILE||"";if(!S)throw Error("Cannot resolve user DB path: HOME environment variable is not set");let u=`${S}${y.slice(1)}`,n=u.substring(0,u.lastIndexOf("/"));return H("fs").mkdirSync(n,{recursive:!0}),u}return y}async function jS(y,S,u,n,O){if(!y.trim())return S;let M=bn(y),f=new Set;for(let R of M){let N=u.findByName(R);for(let V of N){let J=u.traverseRelations(V.id,1);for(let _ of J){let $=u.getObservationsForEntity(_);for(let U of $)f.add(U)}}}if(f.size===0)return S;let p=new Set(S.map((R)=>R.observation.id)),E=[];for(let R of f){if(p.has(R))continue;let N=n.getById(R);if(!N)continue;if(N.supersededBy)continue;E.push({observation:N,rank:0,snippet:N.title,source:"project",rankingSource:"graph",explain:{strategy:"hybrid",matchedBy:["graph"]}})}return[...S,...E].slice(0,O)}function bn(y){let S=y.split(/\s+/).filter((n)=>n.length>=2),u=[];for(let n of S)u.push(n);for(let n=0;n<S.length-1;n++)u.push(`${S[n]} ${S[n+1]}`);return u}class Ty{strategies=new Map;register(y,S){this.strategies.set(y,S)}get(y){return this.strategies.get(y)??null}list(){return[...this.strategies.keys()]}}function ny(y){return Array.from(new Set(y))}function vS(y,S){let u=[],n=new Set;for(let O of y){if(n.has(O.observation.id))continue;if(n.add(O.observation.id),u.push(O),u.length>=S)break}return u}function tn(y,S){let u=S.toLowerCase();return y.some((n)=>n.toLowerCase()===u)}function on(y,S){let u=S.toLowerCase();return y.some((n)=>n.toLowerCase().includes(u))}function xS(y,S){let u=ny([...S.concept?[S.concept]:[],...S.concepts??[]]),n=ny([...S.file?[S.file]:[],...S.files??[]]);return y.filter((O)=>{let M=O.observation;if(S.type&&M.type!==S.type)return!1;if(S.importanceMin!==void 0&&M.importance<S.importanceMin)return!1;if(S.importanceMax!==void 0&&M.importance>S.importanceMax)return!1;if(S.createdAfter&&M.createdAt<S.createdAfter)return!1;if(S.createdBefore&&M.createdAt>S.createdBefore)return!1;if(u.length>0&&!u.some((f)=>tn(M.concepts,f)))return!1;if(n.length>0){let f=[...M.filesRead,...M.filesModified];if(!n.some((p)=>on(f,p)))return!1}return!0})}function h(y,S,u,n){let O=ny([...u.concept?[u.concept]:[],...u.concepts??[]]);if(O.length>0){let f=O.flatMap((E)=>y.observations.searchByConcept(E,n,u.projectPath)),p=vS(f.map((E)=>({observation:E,rank:0,snippet:E.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["concept-filter"]}})),n);return xS(p,u).slice(0,n)}let M=ny([...u.file?[u.file]:[],...u.files??[]]);if(M.length>0){let f=M.flatMap((E)=>y.observations.searchByFile(E,n,u.projectPath)),p=vS(f.map((E)=>({observation:E,rank:0,snippet:E.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["file-filter"]}})),n);return xS(p,u).slice(0,n)}return y.observations.search({query:S,type:u.type,limit:n,projectPath:u.projectPath,importanceMin:u.importanceMin,importanceMax:u.importanceMax,createdAfter:u.createdAfter,createdBefore:u.createdBefore,concepts:u.concepts,files:u.files})}function j(y,S){if(S.type&&y.type!==S.type)return!1;if(S.importanceMin!==void 0&&y.importance<S.importanceMin)return!1;if(S.importanceMax!==void 0&&y.importance>S.importanceMax)return!1;if(S.createdAfter&&y.createdAt<S.createdAfter)return!1;if(S.createdBefore&&y.createdAt>S.createdBefore)return!1;if(S.concepts&&S.concepts.length>0){if(!S.concepts.some((n)=>y.concepts.some((O)=>O.toLowerCase().includes(n.toLowerCase()))))return!1}if(S.files&&S.files.length>0){let u=[...y.filesRead,...y.filesModified];if(!S.files.some((O)=>u.some((M)=>M.toLowerCase().includes(O.toLowerCase()))))return!1}return!0}var kS=60;async function IS(y,S,u,n){let O=n.limit??10,M=dn(S,y,n,O);if(!u)return M;let f=await uy(u,y);if(!f)return M;let p=M.map((R)=>R.observation.id),E=an(S,f,n.projectPath,n,O,n.hasVectorExtension??!1,p);if(E.length===0)return M;return SO(M,E,O)}function dn(y,S,u,n){try{return y.search({query:S,type:u.type,limit:n,projectPath:u.projectPath,importanceMin:u.importanceMin,importanceMax:u.importanceMax,createdAfter:u.createdAfter,createdBefore:u.createdBefore,concepts:u.concepts,files:u.files})}catch{return[]}}function an(y,S,u,n,O,M,f){if(M)return sn(y,S,n,O,f);return yO(y,S,u,n,O)}function sn(y,S,u,n,O){try{let M;if(O.length>0){if(M=y.searchVecSubset(S,O,n*3),M.length===0)M=y.getVecEmbeddingMatches(S,n*3)}else M=y.getVecEmbeddingMatches(S,n*3);if(M.length===0)return[];let f=[];for(let{observationId:p,distance:E}of M){if(f.length>=n)break;let R=y.getById(p);if(!R)continue;if(!j(R,u))continue;f.push({observation:R,rank:E-1,snippet:R.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:E}})}return f}catch{return[]}}function yO(y,S,u,n,O){let M=y.getWithEmbeddings(u,O*10);if(M.length===0)return[];let f=M.map((E)=>({id:E.id,similarity:T(S,E.embedding)})).filter(({similarity:E})=>E>=0.3).sort((E,R)=>R.similarity-E.similarity),p=[];for(let{id:E,similarity:R}of f){if(p.length>=O)break;let N=y.getById(E);if(!N)continue;if(!j(N,n))continue;p.push({observation:N,rank:-R,snippet:N.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorSimilarity:R}})}return p}function SO(y,S,u){let n=new Map;for(let O=0;O<y.length;O++){let M=y[O],f=1/(kS+O+1);n.set(M.observation.id,{score:f,result:{...M,rankingSource:"fts",explain:{strategy:"hybrid",matchedBy:["fts"],ftsRank:M.rank}}})}for(let O=0;O<S.length;O++){let M=S[O],f=1/(kS+O+1),p=n.get(M.observation.id);if(p)p.score+=f,p.result={...p.result,explain:{strategy:"hybrid",matchedBy:["fts","vector"],ftsRank:p.result.explain?.ftsRank??p.result.rank,vectorDistance:M.explain?.vectorDistance,vectorSimilarity:M.explain?.vectorSimilarity}};else n.set(M.observation.id,{score:f,result:{...M,explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:M.explain?.vectorDistance,vectorSimilarity:M.explain?.vectorSimilarity}}})}return[...n.values()].sort((O,M)=>M.score-O.score).slice(0,u).map(({score:O,result:M})=>({...M,explain:{...M.explain??{strategy:"hybrid",matchedBy:[]},strategy:"hybrid",matchedBy:M.explain?.matchedBy??[],rrfScore:O,ftsRank:M.explain?.ftsRank,vectorDistance:M.explain?.vectorDistance,vectorSimilarity:M.explain?.vectorSimilarity}}))}async function qS(y,S,u,n){return IS(S,y.observations,y.embeddingModel,{type:u.type,limit:n,projectPath:u.projectPath,hasVectorExtension:y.hasVectorExtension,importanceMin:u.importanceMin,importanceMax:u.importanceMax,createdAfter:u.createdAfter,createdBefore:u.createdBefore,concepts:u.concepts,files:u.files})}async function wS(y,S,u,n){if(!y.embeddingModel)return h(y,S,u,n);let O=await uy(y.embeddingModel,S);if(!O)return h(y,S,u,n);if(y.hasVectorExtension)try{let E=y.observations.getVecEmbeddingMatches(O,n*3);if(E.length===0)return[];let R=[];for(let{observationId:N,distance:V}of E){if(R.length>=n)break;let J=y.observations.getById(N);if(!J)continue;if(!j(J,u))continue;R.push({observation:J,rank:V-1,snippet:J.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorDistance:V}})}return R}catch{return h(y,S,u,n)}let M=y.observations.getWithEmbeddings(u.projectPath,n*10);if(M.length===0)return[];let f=M.map((E)=>({id:E.id,similarity:T(O,E.embedding)})).filter(({similarity:E})=>E>=0.3).sort((E,R)=>R.similarity-E.similarity),p=[];for(let{id:E,similarity:R}of f){if(p.length>=n)break;let N=y.observations.getById(E);if(!N)continue;if(!j(N,u))continue;p.push({observation:N,rank:-R,snippet:N.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorSimilarity:R}})}return p}class hy{observations;embeddingModel;hasVectorExtension;reranker;userObservationRepo;entityRepo;strategyRegistry;constructor(y,S,u,n=null,O=null,M=null,f=null){this.observations=y;this.embeddingModel=S;this.hasVectorExtension=u;this.reranker=n;this.userObservationRepo=O;this.entityRepo=M;if(this.strategyRegistry=f??new Ty,!this.strategyRegistry.get("filter-only"))this.strategyRegistry.register("filter-only",(p,E)=>h({observations:this.observations,embeddingModel:this.embeddingModel,hasVectorExtension:this.hasVectorExtension},E.query,p,E.limit));if(!this.strategyRegistry.get("semantic"))this.strategyRegistry.register("semantic",(p,E)=>wS({observations:this.observations,embeddingModel:this.embeddingModel,hasVectorExtension:this.hasVectorExtension},E.query,p,E.limit));if(!this.strategyRegistry.get("hybrid"))this.strategyRegistry.register("hybrid",(p,E)=>qS({observations:this.observations,embeddingModel:this.embeddingModel,hasVectorExtension:this.hasVectorExtension},E.query,p,E.limit))}async search(y,S){let u=S.strategy??"hybrid",n=S.limit??10,O=this.normalizeOptions(S),M=this.strategyRegistry.get(u);if(!M)throw Error(`Unknown search strategy: ${u}`);let f=await M(O,{query:y,limit:n});if(f=f.map((p)=>({...p,source:"project"})),this.entityRepo&&y.trim())f=await jS(y,f,this.entityRepo,this.observations,n);if(this.userObservationRepo){let p=this.searchUserMemory(y,n);f=this.mergeResults(f,p,n)}if(this.reranker&&f.length>1)return this.reranker.rerank(y,f,n);return f}normalizeOptions(y){let S=y.concept?Array.from(new Set([y.concept,...y.concepts??[]])):y.concepts,u=y.file?Array.from(new Set([y.file,...y.files??[]])):y.files;return{...y,concepts:S,files:u}}searchUserMemory(y,S){if(!this.userObservationRepo)return[];try{return this.userObservationRepo.search({query:y,limit:S}).map(({observation:n,rank:O})=>({observation:uO(n),rank:O,snippet:n.title,source:"user",rankingSource:"user-memory",explain:{strategy:"filter-only",matchedBy:["user-memory"]}}))}catch{return[]}}mergeResults(y,S,u){let n=new Set(y.map((f)=>f.observation.id)),O=new Set(y.map((f)=>`${f.observation.title}::${f.observation.narrative}`)),M=S.filter((f)=>{if(n.has(f.observation.id))return!1;let p=`${f.observation.title}::${f.observation.narrative}`;if(O.has(p))return!1;return O.add(p),!0});return[...y,...M].slice(0,u)}}function uO(y){return{id:y.id,sessionId:"",type:y.type,title:y.title,subtitle:y.subtitle,facts:y.facts,narrative:y.narrative,concepts:y.concepts,filesRead:y.filesRead,filesModified:y.filesModified,rawToolOutput:"",toolName:y.toolName,createdAt:y.createdAt,tokenCount:y.tokenCount,discoveryTokens:0,importance:y.importance}}import{generateText as OO}from"ai";function lS(y,S){let u=S.map((n,O)=>` <candidate index="${O}"><title>${n.title}</title><narrative>${n.narrative}</narrative></candidate>`).join(`
|
|
512
513
|
`);return`<rerank_request>
|
|
513
|
-
<query>${
|
|
514
|
+
<query>${y}</query>
|
|
514
515
|
<candidates>
|
|
515
|
-
${
|
|
516
|
+
${u}
|
|
516
517
|
</candidates>
|
|
517
518
|
<instructions>Reorder the candidates by relevance to the query. Return indices from most to least relevant.
|
|
518
519
|
|
|
@@ -523,4 +524,4 @@ Respond with EXACTLY this XML format:
|
|
|
523
524
|
<index>0</index>
|
|
524
525
|
</reranked>
|
|
525
526
|
</instructions>
|
|
526
|
-
</rerank_request>`}var
|
|
527
|
+
</rerank_request>`}var nO={"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},PS=0;async function rS(y,S){if(!S)return;let u=nO[y]||5,n=Math.ceil(60000/u)+100,M=Date.now()-PS;if(M<n){let f=n-M;await new Promise((p)=>setTimeout(p,f))}PS=Date.now()}class eS{languageModel;maxCandidates;provider;modelName;rateLimitingEnabled;_generate=OO;constructor(y,S){this.languageModel=y,this.maxCandidates=S.rerankingMaxCandidates,this.provider=S.provider??"",this.modelName=S.model??"",this.rateLimitingEnabled=S.rateLimitingEnabled??!0}async rerank(y,S,u){if(S.length<=1)return S;let n=S.slice(0,this.maxCandidates),O=S.slice(this.maxCandidates),M=lS(y,n.map((p)=>({title:p.observation.title,narrative:p.observation.narrative}))),f=2;for(let p=0;p<=f;p++)try{if(this.provider==="google")await rS(this.modelName,this.rateLimitingEnabled);let{text:E}=await this._generate({model:this.languageModel,maxOutputTokens:512,prompt:M}),R=ty(E);if(!R)return S.slice(0,u);let N=this.applyReranking(n,R,u);for(let V of O){if(N.length>=u)break;N.push(V)}return N}catch(E){if(MO(E)&&p<f){await fO(2**p*1000);continue}return S.slice(0,u)}return S.slice(0,u)}applyReranking(y,S,u){let n=[],O=new Set;for(let M of S)if(M>=0&&M<y.length&&!O.has(M)){if(O.add(M),n.push(y[M]),n.length>=u)break}if(n.length<u){for(let M=0;M<y.length&&n.length<u;M++)if(!O.has(M))n.push(y[M])}return n}}class iS{async rerank(y,S,u){if(S.length<=1)return S.slice(0,u);let n=jy(y),O=S.map((M)=>({result:M,score:this.scoreCandidate(M,n)}));return O.sort((M,f)=>f.score-M.score),O.slice(0,u).map((M)=>M.result)}scoreCandidate(y,S){let u=y.observation,n=jy(u.title),O=jy(u.narrative),M=new Set(u.concepts.map((X)=>X.toLowerCase())),f=0,p=0,E=0;for(let X of S){if(n.has(X))f++;if(O.has(X))p++;if(M.has(X))E++}let R=S.size||1,N=f/R*0.4,V=p/R*0.3,J=E/R*0.15,$=(Date.now()-new Date(u.createdAt).getTime())/86400000,U=$<1?0.1:$<7?0.05:0,c=u.importance/5*0.05;return N+V+J+U+c}}function bS(y,S){if(!y.rerankingEnabled)return null;if(S)return new eS(S,y);return new iS}function jy(y){return new Set(y.toLowerCase().split(/[\s\-_./\\,;:!?()[\]{}'"]+/).filter((S)=>S.length>1))}function MO(y){if(typeof y!=="object"||y===null)return!1;let S=y,u=S.status;if(u===429||u===500||u===503)return!0;let n=S.error;if(typeof n==="object"&&n!==null&&n.type==="overloaded_error")return!0;return!1}function fO(y){return new Promise((S)=>setTimeout(S,y))}function tS(y){return y}function oS(y){return y}function dS(y){return y}function aS(y){if(!y)return null;return y}import{spawnSync as sS}from"child_process";import{dirname as pO,resolve as yu}from"path";function EO(y){try{let S=sS("git",["rev-parse","--git-common-dir"],{cwd:y,encoding:"utf-8",timeout:5000});if(S.status!==0||!S.stdout)return null;let u=S.stdout.trim();if(u===".git")return null;let n=sS("git",["rev-parse","--git-dir"],{cwd:y,encoding:"utf-8",timeout:5000});if(n.status!==0||!n.stdout)return null;let O=n.stdout.trim(),M=yu(y,u),f=yu(y,O);if(M===f)return null;let p=pO(M);if(p===M||p==="/")return null;return p}catch{return null}}function Su(y){return EO(y)??y}var __dirname="/Users/clopca/dev/github/open-mem/src",{values:uu}=mO({options:{project:{type:"string",short:"p"}},strict:!1}),VO=typeof uu.project==="string"?uu.project:process.cwd(),nu=Su(VO),A=q(nu);yy.enableExtensionSupport();var Z=Sy(A.dbPath);hS(Z,{hasVectorExtension:Z.hasVectorExtension,embeddingDimension:A.embeddingDimension});var JO=new Ly(Z),Ou=new Qy(Z),_O=new Fy(Z),AO=new Ky(Z),$O=new Wy(Z),v=null,vy=null;if(A.userMemoryEnabled)try{v=new Dy(A.userMemoryDbPath),vy=new Gy(v.database)}catch(y){console.error(`[open-mem-mcp] Failed to initialize user-level memory: ${y}`)}var Mu=A.provider!=="bedrock",gO=A.compressionEnabled&&(!Mu||A.apiKey)?qy({provider:A.provider,model:A.model,apiKey:A.apiKey}):null,CO=bS(A,A.rerankingEnabled&&(!Mu||A.apiKey)?ly({provider:A.provider,model:A.model,apiKey:A.apiKey},wy(A)):null),UO=new zy(Z),BO=new hy(Ou,gO,Z.hasVectorExtension,CO,vy,UO),ZO=JSON.parse(RO(NO(__dirname,"..","package.json"),"utf-8")),XO=new fy({memoryEngine:new Hy({observations:tS(Ou),sessions:oS(JO),summaries:dS(_O),searchOrchestrator:BO,projectPath:nu,config:A,userObservationRepo:aS(vy),configAuditStore:AO,maintenanceHistoryStore:$O}),version:ZO.version,protocolVersion:A.mcpProtocolVersion,supportedProtocolVersions:A.mcpSupportedProtocolVersions}),Oy=!1,fu=()=>{if(!Oy){if(Oy=!0,v)v.close();Z.close()}process.exit(0)};process.on("SIGINT",fu);process.on("SIGTERM",fu);process.on("beforeExit",()=>{if(!Oy){if(Oy=!0,v)v.close();Z.close()}});XO.start();
|