open-mem 0.7.1 → 0.7.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.
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- var D=import.meta.require;import{createInterface as n0}from"readline";import{parseArgs as d0}from"util";var Kf={name:"claude-code",version:"0.1",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}},Jf={name:"cursor",version:"0.1",capabilities:{nativeSessionLifecycle:!1,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}};function g(){return new Date().toISOString()}function P(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;return f}function H(f){return typeof f==="string"&&f.trim().length>0?f:null}function O(f,B){let E=P(B);if(!E)return null;let K=H(E.kind),J=H(E.sessionId);if(!K||!J)return null;if(K==="session.start"||K==="session.end"||K==="idle.flush")return{kind:K,platform:f,sessionId:J,occurredAt:H(E.occurredAt)??g(),metadata:P(E.metadata)??void 0};if(K==="chat.message"){let z=H(E.text);if(!z)return null;let A=H(E.role);return{kind:K,platform:f,sessionId:J,text:z,role:A==="assistant"||A==="system"?A:"user",occurredAt:H(E.occurredAt)??g(),metadata:P(E.metadata)??void 0}}if(K==="tool.execute"){let z=H(E.toolName),A=H(E.output);if(!z||!A)return null;return{kind:K,platform:f,sessionId:J,callId:H(E.callId)??`${f}-${Date.now()}`,toolName:z,output:A,occurredAt:H(E.occurredAt)??g(),metadata:P(E.metadata)??void 0}}return null}function nf(f){let B=f.type??f.event;if(!B)return null;if(B==="session.start")return"session.start";if(B==="session.end")return"session.end";if(B==="idle.flush")return"idle.flush";if(B==="tool.execute")return"tool.execute";if(B==="chat.message")return"chat.message";return null}class zf{descriptor=Kf;normalize(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let B=f,E=nf(B);if(!E||!B.sessionId)return null;return O("claude-code",{kind:E,sessionId:B.sessionId,callId:B.callId,toolName:B.toolName,output:B.output,role:B.role,text:B.text,occurredAt:B.occurredAt,metadata:B.metadata})}}function Af(){return new zf}function df(f){let B=f.eventName??f.event;if(!B)return null;if(B==="sessionStart")return"session.start";if(B==="sessionEnd")return"session.end";if(B==="idleFlush")return"idle.flush";if(B==="toolExecute")return"tool.execute";if(B==="chatMessage")return"chat.message";return null}class Nf{descriptor=Jf;normalize(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let B=f,E=df(B),K=B.sessionId??B.session;if(!E||!K)return null;return O("cursor",{kind:E,sessionId:K,callId:B.callId??B.invocationId,toolName:B.toolName??B.tool,output:B.output,role:B.role,text:B.text??B.message,occurredAt:B.occurredAt??B.timestamp,metadata:B.metadata??B.meta})}}function Rf(){return new Nf}function j(f,B=""){if(!f)return f;return f.replace(/<private>[\s\S]*?<\/private>/gi,B)}var $f=200,rf=/(\([\s\S]*[+*]\)\s*[+*?])|(\(\.\*\)\+)|(\(\.\+\)\+)/;function q(f,B,E="[REDACTED]"){if(!f||B.length===0)return f;let K=f;for(let J of B){if(J.length>$f){console.warn(`[open-mem] Skipping oversized redaction pattern (${J.length} chars, max ${$f})`);continue}if(rf.test(J)){console.warn("[open-mem] Skipping potentially dangerous redaction pattern (nested quantifiers detected)");continue}try{K=K.replace(new RegExp(J,"g"),E)}catch{}}return K}var sf=20,Wf=2000,Qf=60;function of(f){let B=f.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter((E)=>E.length>4);return[...new Set(B)].slice(0,5)}function uf(f){let{observations:B,sessions:E,projectPath:K,sessionId:J,text:z,agent:A,sensitivePatterns:R=[]}=f;if(A!==void 0&&A!=="user")return!1;let N=q(j(z),R);if(N.length<sf)return!1;E.getOrCreate(J,K);let W=`User request: ${N.length>Qf?`${N.slice(0,Qf)}...`:N}`,Q=N.length>Wf?`${N.slice(0,Wf)}...`:N;return B.create({sessionId:J,type:"discovery",title:W,subtitle:"",facts:[],narrative:Q,concepts:of(N),filesRead:[],filesModified:[],rawToolOutput:"",toolName:"chat.message",tokenCount:Math.ceil(Q.length/4),discoveryTokens:0,importance:3}),!0}import{existsSync as Uf}from"fs";import{mkdir as tf,readFile as ef,rename as af,unlink as f0,writeFile as B0}from"fs/promises";import{dirname as l,isAbsolute as Vf,join as T,normalize as E0,relative as Hf,resolve as w,sep as p}from"path";var h="<!-- open-mem-context -->",F="<!-- /open-mem-context -->",K0={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},Zf=new Map,J0=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function Yf(f,B,E=5){if(B.length===0)return;let K=[];for(let A of B){for(let R of A.filesModified)K.push(R);for(let R of A.filesRead)K.push(R)}let J=R0(K,f,E);if(J.size===0)return;let z=$0(B,J,f);for(let[A,R]of z)try{let N=z0(A,R,f);await A0(A,N)}catch(N){console.error(`[open-mem] Failed to update AGENTS.md in ${A}:`,N)}}function z0(f,B,E){let K=[...B].sort((N,$)=>$.createdAt.localeCompare(N.createdAt)).slice(0,10),J=Hf(E,f)||".",z=[];z.push(`## Recent Activity in \`${J}/\` (auto-generated by open-mem)`),z.push(""),z.push("| Type | Title | Date |"),z.push("|------|-------|------|");for(let N of K){let $=K0[N.type]||"\uD83D\uDCDD",W=N.createdAt.split("T")[0],Q=N.title.replace(/\|/g,"\\|");z.push(`| ${$} ${N.type} | ${Q} | ${W} |`)}let A=new Set;for(let N of K)for(let $ of N.concepts)A.add($);if(A.size>0){let N=[...A].slice(0,10).join(", ");z.push(""),z.push(`**Key concepts:** ${N}`)}let R=K.filter((N)=>N.type==="decision").map((N)=>N.title);if(R.length>0)z.push(""),z.push(`**Recent decisions:** ${R.slice(0,5).join("; ")}`);return z.join(`
4
- `)}async function A0(f,B){if(!Uf(f))return;let K=(Zf.get(f)??Promise.resolve()).then(async()=>{let J=T(f,"AGENTS.md"),z=T(f,".AGENTS.md.tmp"),A="";try{A=await ef(J,"utf-8")}catch{}let R=N0(A,B);try{await tf(l(z),{recursive:!0}),await B0(z,R,"utf-8"),await af(z,J)}catch(N){try{await f0(z)}catch{}throw N}});return Zf.set(f,K.catch(()=>{})),K}function N0(f,B){if(!f)return`${h}
3
+ var D=import.meta.require;import{createInterface as n0}from"readline";import{parseArgs as d0}from"util";var Ef={name:"claude-code",version:"0.1",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}},Jf={name:"cursor",version:"0.1",capabilities:{nativeSessionLifecycle:!1,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}};function p(){return new Date().toISOString()}function O(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;return f}function H(f){return typeof f==="string"&&f.trim().length>0?f:null}function j(f,B){let K=O(B);if(!K)return null;let E=H(K.kind),J=H(K.sessionId);if(!E||!J)return null;if(E==="session.start"||E==="session.end"||E==="idle.flush")return{kind:E,platform:f,sessionId:J,occurredAt:H(K.occurredAt)??p(),metadata:O(K.metadata)??void 0};if(E==="chat.message"){let z=H(K.text);if(!z)return null;let $=H(K.role);return{kind:E,platform:f,sessionId:J,text:z,role:$==="assistant"||$==="system"?$:"user",occurredAt:H(K.occurredAt)??p(),metadata:O(K.metadata)??void 0}}if(E==="tool.execute"){let z=H(K.toolName),$=H(K.output);if(!z||!$)return null;return{kind:E,platform:f,sessionId:J,callId:H(K.callId)??`${f}-${Date.now()}`,toolName:z,output:$,occurredAt:H(K.occurredAt)??p(),metadata:O(K.metadata)??void 0}}return null}function nf(f){let B=f.type??f.event;if(!B)return null;if(B==="session.start")return"session.start";if(B==="session.end")return"session.end";if(B==="idle.flush")return"idle.flush";if(B==="tool.execute")return"tool.execute";if(B==="chat.message")return"chat.message";return null}class zf{descriptor=Ef;normalize(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let B=f,K=nf(B);if(!K||!B.sessionId)return null;return j("claude-code",{kind:K,sessionId:B.sessionId,callId:B.callId,toolName:B.toolName,output:B.output,role:B.role,text:B.text,occurredAt:B.occurredAt,metadata:B.metadata})}}function $f(){return new zf}function df(f){let B=f.eventName??f.event;if(!B)return null;if(B==="sessionStart")return"session.start";if(B==="sessionEnd")return"session.end";if(B==="idleFlush")return"idle.flush";if(B==="toolExecute")return"tool.execute";if(B==="chatMessage")return"chat.message";return null}class Nf{descriptor=Jf;normalize(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let B=f,K=df(B),E=B.sessionId??B.session;if(!K||!E)return null;return j("cursor",{kind:K,sessionId:E,callId:B.callId??B.invocationId,toolName:B.toolName??B.tool,output:B.output,role:B.role,text:B.text??B.message,occurredAt:B.occurredAt??B.timestamp,metadata:B.metadata??B.meta})}}function Rf(){return new Nf}function q(f,B=""){if(!f)return f;return f.replace(/<private>[\s\S]*?<\/private>/gi,B)}var Wf=200,rf=/(\([\s\S]*[+*]\)\s*[+*?])|(\(\.\*\)\+)|(\(\.\+\)\+)/;function h(f,B,K="[REDACTED]"){if(!f||B.length===0)return f;let E=f;for(let J of B){if(J.length>Wf){console.warn(`[open-mem] Skipping oversized redaction pattern (${J.length} chars, max ${Wf})`);continue}if(rf.test(J)){console.warn("[open-mem] Skipping potentially dangerous redaction pattern (nested quantifiers detected)");continue}try{E=E.replace(new RegExp(J,"g"),K)}catch{}}return E}var sf=20,Qf=2000,uf=60;function of(f){let B=f.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter((K)=>K.length>4);return[...new Set(B)].slice(0,5)}function Af(f){let{observations:B,sessions:K,projectPath:E,sessionId:J,text:z,agent:$,sensitivePatterns:R=[]}=f;if($!==void 0&&$!=="user")return!1;let N=h(q(z),R);if(N.length<sf)return!1;K.getOrCreate(J,E);let Q=`User request: ${N.length>uf?`${N.slice(0,uf)}...`:N}`,u=N.length>Qf?`${N.slice(0,Qf)}...`:N;return B.create({sessionId:J,type:"discovery",title:Q,subtitle:"",facts:[],narrative:u,concepts:of(N),filesRead:[],filesModified:[],rawToolOutput:"",toolName:"chat.message",tokenCount:Math.ceil(u.length/4),discoveryTokens:0,importance:3}),!0}import{existsSync as Uf}from"fs";import{mkdir as tf,readFile as ef,rename as af,unlink as f0,writeFile as B0}from"fs/promises";import{dirname as l,isAbsolute as Vf,join as T,normalize as K0,relative as Hf,resolve as w,sep as I}from"path";var y="<!-- open-mem-context -->",M="<!-- /open-mem-context -->",E0={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},Zf=new Map,J0=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function Yf(f,B,K=5){if(B.length===0)return;let E=[];for(let $ of B){for(let R of $.filesModified)E.push(R);for(let R of $.filesRead)E.push(R)}let J=R0(E,f,K);if(J.size===0)return;let z=W0(B,J,f);for(let[$,R]of z)try{let N=z0($,R,f);await $0($,N)}catch(N){console.error(`[open-mem] Failed to update AGENTS.md in ${$}:`,N)}}function z0(f,B,K){let E=[...B].sort((N,W)=>W.createdAt.localeCompare(N.createdAt)).slice(0,10),J=Hf(K,f)||".",z=[];z.push(`## Recent Activity in \`${J}/\` (auto-generated by open-mem)`),z.push(""),z.push("| Type | Title | Date |"),z.push("|------|-------|------|");for(let N of E){let W=E0[N.type]||"\uD83D\uDCDD",Q=N.createdAt.split("T")[0],u=N.title.replace(/\|/g,"\\|");z.push(`| ${W} ${N.type} | ${u} | ${Q} |`)}let $=new Set;for(let N of E)for(let W of N.concepts)$.add(W);if($.size>0){let N=[...$].slice(0,10).join(", ");z.push(""),z.push(`**Key concepts:** ${N}`)}let R=E.filter((N)=>N.type==="decision").map((N)=>N.title);if(R.length>0)z.push(""),z.push(`**Recent decisions:** ${R.slice(0,5).join("; ")}`);return z.join(`
4
+ `)}async function $0(f,B){if(!Uf(f))return;let E=(Zf.get(f)??Promise.resolve()).then(async()=>{let J=T(f,"AGENTS.md"),z=T(f,".AGENTS.md.tmp"),$="";try{$=await ef(J,"utf-8")}catch{}let R=N0($,B);try{await tf(l(z),{recursive:!0}),await B0(z,R,"utf-8"),await af(z,J)}catch(N){try{await f0(z)}catch{}throw N}});return Zf.set(f,E.catch(()=>{})),E}function N0(f,B){if(!f)return`${y}
5
5
  ${B}
6
- ${F}
7
- `;let E=f.indexOf(h),K=f.indexOf(F);if(E!==-1&&K!==-1&&K>E){let J=f.substring(0,E),z=f.substring(K+F.length);return`${J}${h}
6
+ ${M}
7
+ `;let K=f.indexOf(y),E=f.indexOf(M);if(K!==-1&&E!==-1&&E>K){let z=f.substring(0,K),$=f.substring(E+M.length);return`${z}${y}
8
8
  ${B}
9
- ${F}${z}`}return`${f}
9
+ ${M}${$}`}let J=f;if(K!==-1&&E===-1)J=J.replace(y,"").trim();else if(K===-1&&E!==-1)J=J.replace(M,"").trim();else if(K!==-1&&E!==-1&&E<=K)J=J.replace(M,"").replace(y,"").trim();return`${J}
10
10
 
11
- ${h}
11
+ ${y}
12
12
  ${B}
13
- ${F}
14
- `}function R0(f,B,E){let K=new Set,J=w(B);for(let z of f){if(!z||!z.trim())continue;if(z.startsWith("~")||z.startsWith("http"))continue;let A=Vf(z)?z:T(B,z),R=l(A),N=w(R);if(!N.startsWith(J+p)&&N!==J)continue;if(N===J)continue;let $=Hf(J,N);if($.split(p).length>E)continue;if(E0($).split(p).some((Z)=>J0.has(Z)))continue;if(!Uf(N))continue;K.add(N)}return K}function $0(f,B,E){let K=new Map;for(let J of f){let z=[...J.filesModified,...J.filesRead],A=new Set;for(let R of z){if(!R)continue;let N=Vf(R)?R:T(E,R),$=w(l(N));if(B.has($))A.add($)}for(let R of A){let N=K.get(R)??[];N.push(J),K.set(R,N)}}return K}function Xf(f,B,E){if(f.retentionDays===0)return;try{let K=B.deleteOlderThan(f.retentionDays),J=E.deleteCompletedOlderThan(f.retentionDays);if(K>0||J>0)console.log(`[open-mem] Retention: deleted ${K} observations, ${J} pending messages`)}catch(K){console.error("[open-mem] Retention enforcement error:",K)}}async function x(f,B,E){let{queue:K,sessions:J,projectPath:z,config:A,observations:R,pendingMessages:N}=f;switch(B){case"session.created":{if(E)J.getOrCreate(E,z);try{Xf(A,R,N)}catch($){console.error("[open-mem] Retention enforcement error:",$)}break}case"session.idle":{if(K.processBatch().catch(($)=>{console.error("[open-mem] Background processing error:",$)}),E)J.updateStatus(E,"idle"),Cf(E,z,A,R).catch(($)=>{console.error("[open-mem] Folder context error:",$)});break}case"session.completed":case"session.ended":{if(E)await K.processBatch(),await K.summarizeSession(E),J.markCompleted(E),await Cf(E,z,A,R);break}}}async function Cf(f,B,E,K){if(!E.folderContextEnabled)return;try{let J=K.getBySession(f);if(J.length>0)await Yf(B,J,E.folderContextMaxDepth)}catch(J){console.error("[open-mem] Folder context update error:",J)}}function Lf(f){let{config:B,queue:E,sessions:K,projectPath:J,tool:z,sessionId:A,callId:R,toolOutput:N}=f;if(B.ignoredTools.includes(z))return!1;if(!N||N.length<B.minOutputLength)return!1;let $=q(N,B.sensitivePatterns);return $=j($,"[PRIVATE]"),K.getOrCreate(A,J),E.enqueue(A,z,$,R),!0}class v{adapter;lifecycleDeps;queue;sessions;observations;projectPath;config;constructor(f){this.adapter=f.adapter,this.queue=f.queue,this.sessions=f.sessions,this.observations=f.observations,this.projectPath=f.projectPath,this.config=f.config,this.lifecycleDeps={queue:f.queue,sessions:f.sessions,projectPath:f.projectPath,config:f.config,observations:f.observations,pendingMessages:f.pendingMessages}}platform(){return this.adapter.descriptor.name}normalize(f){return this.adapter.normalize(f)}async ingestRaw(f){let B=this.normalize(f);if(!B)return!1;return await this.ingestNormalized(B),!0}async ingestNormalized(f){switch(f.kind){case"session.start":await x(this.lifecycleDeps,"session.created",f.sessionId);return;case"session.end":await x(this.lifecycleDeps,"session.ended",f.sessionId);return;case"idle.flush":await x(this.lifecycleDeps,"session.idle",f.sessionId);return;case"tool.execute":Lf({config:this.config,queue:this.queue,sessions:this.sessions,projectPath:this.projectPath,tool:f.toolName,sessionId:f.sessionId,callId:f.callId,toolOutput:f.output});return;case"chat.message":uf({observations:this.observations,sessions:this.sessions,projectPath:this.projectPath,sessionId:f.sessionId,text:f.text,agent:f.role==="user"?"user":f.role,sensitivePatterns:this.config.sensitivePatterns});return}}}import{generateText as Y0}from"ai";var W0=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function u(f,B){let E=new RegExp(`<${B}[^>]*>([\\s\\S]*?)</${B}>`,"i"),K=f.match(E);return K?K[1].trim():""}function Y(f,B){let E=new RegExp(`<${B}[^>]*>([\\s\\S]*?)</${B}>`,"gi"),K=[];for(let J of f.matchAll(E)){let z=J[1].trim();if(z)K.push(z)}return K}function kf(f){let B=u(f,"observation");if(!B)return null;let E=u(B,"type").toLowerCase(),K=W0.has(E)?E:"discovery",J=u(B,"title")||"Untitled observation",z=u(B,"subtitle"),A=u(B,"narrative"),R=Y(u(B,"facts"),"fact"),N=Y(u(B,"concepts"),"concept"),$=Y(u(B,"files_read"),"file"),W=Y(u(B,"files_modified"),"file"),Q=u(B,"importance"),Z=Number.parseInt(Q,10),V=Number.isNaN(Z)?3:Math.max(1,Math.min(5,Z));return{type:K,title:J,subtitle:z,facts:R,narrative:A,concepts:N,filesRead:$,filesModified:W,importance:V}}function Sf(f){let B=u(f,"session_summary");if(!B)return null;let E=u(B,"summary")||"No summary available",K=Y(u(B,"key_decisions"),"decision"),J=Y(u(B,"files_modified"),"file"),z=Y(u(B,"concepts"),"concept"),A=u(B,"request")||void 0,R=u(B,"investigated")||void 0,N=u(B,"learned")||void 0,$=u(B,"completed")||void 0,W=u(B,"next_steps")||void 0;return{summary:E,keyDecisions:K,filesModified:J,concepts:z,request:A,investigated:R,learned:N,completed:$,nextSteps:W}}var Q0=new Set(["new_fact","update","duplicate"]);function Df(f){let B=u(f,"evaluation");if(!B)return null;let E=u(B,"outcome").toLowerCase().trim();if(!Q0.has(E))return null;let K=E,J=u(B,"reason");if(!J)return null;let z=u(B,"supersedes"),A={outcome:K,reason:J};if(K==="update"&&z)A.supersedesId=z;if(K==="update"&&!A.supersedesId)return null;return A}var u0=new Set(["technology","library","pattern","concept","file","person","project","other"]),Z0=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function Mf(f){let B=u(f,"extraction");if(!B)return null;let E=u(B,"entities"),K=u(B,"relations"),J=Y(E,"entity"),z=[];for(let N of J){let $=u(N,"name");if(!$)continue;let W=u(N,"type").toLowerCase(),Q=u0.has(W)?W:"other";z.push({name:$,entityType:Q})}let A=Y(K,"relation"),R=[];for(let N of A){let $=u(N,"source"),W=u(N,"target"),Q=u(N,"relationship").toLowerCase();if(!$||!W||!Q)continue;if(!Z0.has(Q))continue;R.push({sourceName:$,targetName:W,relationship:Q})}return{entities:z,relations:R}}function M(f){return Math.ceil(f.length/4)}function _f(f,B,E){let K=E?`<session_context>
15
- ${E}
13
+ ${M}
14
+ `}function R0(f,B,K){let E=new Set,J=w(B);for(let z of f){if(!z||!z.trim())continue;if(z.startsWith("~")||z.startsWith("http"))continue;let $=Vf(z)?z:T(B,z),R=l($),N=w(R);if(!N.startsWith(J+I)&&N!==J)continue;if(N===J)continue;let W=Hf(J,N);if(W.split(I).length>K)continue;if(K0(W).split(I).some((Z)=>J0.has(Z)))continue;if(!Uf(N))continue;E.add(N)}return E}function W0(f,B,K){let E=new Map;for(let J of f){let z=[...J.filesModified,...J.filesRead],$=new Set;for(let R of z){if(!R)continue;let N=Vf(R)?R:T(K,R),W=w(l(N));if(B.has(W))$.add(W)}for(let R of $){let N=E.get(R)??[];N.push(J),E.set(R,N)}}return E}function Xf(f,B,K){if(f.retentionDays===0)return;try{let E=B.deleteOlderThan(f.retentionDays),J=K.deleteCompletedOlderThan(f.retentionDays);if(E>0||J>0)console.log(`[open-mem] Retention: deleted ${E} observations, ${J} pending messages`)}catch(E){console.error("[open-mem] Retention enforcement error:",E)}}async function g(f,B,K){let{queue:E,sessions:J,projectPath:z,config:$,observations:R,pendingMessages:N}=f;switch(B){case"session.created":{if(K)J.getOrCreate(K,z);try{Xf($,R,N)}catch(W){console.error("[open-mem] Retention enforcement error:",W)}break}case"session.idle":{if(E.processBatch().catch((W)=>{console.error("[open-mem] Background processing error:",W)}),K)J.updateStatus(K,"idle"),Cf(K,z,$,R).catch((W)=>{console.error("[open-mem] Folder context error:",W)});break}case"session.completed":case"session.ended":{if(K)await E.processBatch(),await E.summarizeSession(K),J.markCompleted(K),await Cf(K,z,$,R);break}}}async function Cf(f,B,K,E){if(!K.folderContextEnabled)return;try{let J=E.getBySession(f);if(J.length>0)await Yf(B,J,K.folderContextMaxDepth)}catch(J){console.error("[open-mem] Folder context update error:",J)}}function Lf(f){let{config:B,queue:K,sessions:E,projectPath:J,tool:z,sessionId:$,callId:R,toolOutput:N}=f;if(B.ignoredTools.includes(z))return!1;if(!N||N.length<B.minOutputLength)return!1;let W=h(N,B.sensitivePatterns);return W=q(W,"[PRIVATE]"),E.getOrCreate($,J),K.enqueue($,z,W,R),!0}class v{adapter;lifecycleDeps;queue;sessions;observations;projectPath;config;constructor(f){this.adapter=f.adapter,this.queue=f.queue,this.sessions=f.sessions,this.observations=f.observations,this.projectPath=f.projectPath,this.config=f.config,this.lifecycleDeps={queue:f.queue,sessions:f.sessions,projectPath:f.projectPath,config:f.config,observations:f.observations,pendingMessages:f.pendingMessages}}platform(){return this.adapter.descriptor.name}normalize(f){return this.adapter.normalize(f)}async ingestRaw(f){let B=this.normalize(f);if(!B)return!1;return await this.ingestNormalized(B),!0}async ingestNormalized(f){switch(f.kind){case"session.start":await g(this.lifecycleDeps,"session.created",f.sessionId);return;case"session.end":await g(this.lifecycleDeps,"session.ended",f.sessionId);return;case"idle.flush":await g(this.lifecycleDeps,"session.idle",f.sessionId);return;case"tool.execute":Lf({config:this.config,queue:this.queue,sessions:this.sessions,projectPath:this.projectPath,tool:f.toolName,sessionId:f.sessionId,callId:f.callId,toolOutput:f.output});return;case"chat.message":Af({observations:this.observations,sessions:this.sessions,projectPath:this.projectPath,sessionId:f.sessionId,text:f.text,agent:f.role==="user"?"user":f.role,sensitivePatterns:this.config.sensitivePatterns});return}}}import{generateText as Y0}from"ai";var Q0=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function A(f,B){let K=new RegExp(`<${B}[^>]*>([\\s\\S]*?)</${B}>`,"i"),E=f.match(K);return E?E[1].trim():""}function Y(f,B){let K=new RegExp(`<${B}[^>]*>([\\s\\S]*?)</${B}>`,"gi"),E=[];for(let J of f.matchAll(K)){let z=J[1].trim();if(z)E.push(z)}return E}function kf(f){let B=A(f,"observation");if(!B)return null;let K=A(B,"type").toLowerCase(),E=Q0.has(K)?K:"discovery",J=A(B,"title")||"Untitled observation",z=A(B,"subtitle"),$=A(B,"narrative"),R=Y(A(B,"facts"),"fact"),N=Y(A(B,"concepts"),"concept"),W=Y(A(B,"files_read"),"file"),Q=Y(A(B,"files_modified"),"file"),u=A(B,"importance"),Z=Number.parseInt(u,10),V=Number.isNaN(Z)?3:Math.max(1,Math.min(5,Z));return{type:E,title:J,subtitle:z,facts:R,narrative:$,concepts:N,filesRead:W,filesModified:Q,importance:V}}function Sf(f){let B=A(f,"session_summary");if(!B)return null;let K=A(B,"summary")||"No summary available",E=Y(A(B,"key_decisions"),"decision"),J=Y(A(B,"files_modified"),"file"),z=Y(A(B,"concepts"),"concept"),$=A(B,"request")||void 0,R=A(B,"investigated")||void 0,N=A(B,"learned")||void 0,W=A(B,"completed")||void 0,Q=A(B,"next_steps")||void 0;return{summary:K,keyDecisions:E,filesModified:J,concepts:z,request:$,investigated:R,learned:N,completed:W,nextSteps:Q}}var u0=new Set(["new_fact","update","duplicate"]);function Df(f){let B=A(f,"evaluation");if(!B)return null;let K=A(B,"outcome").toLowerCase().trim();if(!u0.has(K))return null;let E=K,J=A(B,"reason");if(!J)return null;let z=A(B,"supersedes"),$={outcome:E,reason:J};if(E==="update"&&z)$.supersedesId=z;if(E==="update"&&!$.supersedesId)return null;return $}var A0=new Set(["technology","library","pattern","concept","file","person","project","other"]),Z0=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function Mf(f){let B=A(f,"extraction");if(!B)return null;let K=A(B,"entities"),E=A(B,"relations"),J=Y(K,"entity"),z=[];for(let N of J){let W=A(N,"name");if(!W)continue;let Q=A(N,"type").toLowerCase(),u=A0.has(Q)?Q:"other";z.push({name:W,entityType:u})}let $=Y(E,"relation"),R=[];for(let N of $){let W=A(N,"source"),Q=A(N,"target"),u=A(N,"relationship").toLowerCase();if(!W||!Q||!u)continue;if(!Z0.has(u))continue;R.push({sourceName:W,targetName:Q,relationship:u})}return{entities:z,relations:R}}function m(f){return Math.ceil(f.length/4)}function mf(f,B,K){let E=K?`<session_context>
15
+ ${K}
16
16
  </session_context>
17
17
 
18
18
  `:"";return`<task>
@@ -25,7 +25,7 @@ Analyze the following tool output and extract a structured observation.
25
25
  ${B}
26
26
  </tool_output>
27
27
 
28
- ${K}<instructions>
28
+ ${E}<instructions>
29
29
  Extract a structured observation from the tool output. Determine the most appropriate type and provide a concise but informative summary.
30
30
 
31
31
  When extracting concepts, prefer established vocabulary where appropriate:
@@ -60,9 +60,9 @@ Respond with EXACTLY this XML format:
60
60
  <file>path/to/file/modified</file>
61
61
  </files_modified>
62
62
  </observation>
63
- </instructions>`}function mf(f,B){let E=f.map((K,J)=>` <obs index="${J+1}" type="${K.type}">
64
- <title>${K.title}</title>
65
- <narrative>${K.narrative}</narrative>
63
+ </instructions>`}function _f(f,B){let K=f.map((E,J)=>` <obs index="${J+1}" type="${E.type}">
64
+ <title>${E.title}</title>
65
+ <narrative>${E.narrative}</narrative>
66
66
  </obs>`).join(`
67
67
  `);return`<task>
68
68
  Summarize the following coding session based on its observations.
@@ -71,7 +71,7 @@ Summarize the following coding session based on its observations.
71
71
  <session_id>${B}</session_id>
72
72
 
73
73
  <observations>
74
- ${E}
74
+ ${K}
75
75
  </observations>
76
76
 
77
77
  <instructions>
@@ -95,11 +95,11 @@ Respond with EXACTLY this XML format:
95
95
  <concept>key-concept</concept>
96
96
  </concepts>
97
97
  </session_summary>
98
- </instructions>`}function Gf(f,B){let E=B.map((K)=>` <candidate id="${K.id}">
99
- <title>${K.title}</title>
100
- <narrative>${K.narrative}</narrative>
101
- <concepts>${K.concepts.join(", ")}</concepts>
102
- <type>${K.type}</type>
98
+ </instructions>`}function Ff(f,B){let K=B.map((E)=>` <candidate id="${E.id}">
99
+ <title>${E.title}</title>
100
+ <narrative>${E.narrative}</narrative>
101
+ <concepts>${E.concepts.join(", ")}</concepts>
102
+ <type>${E.type}</type>
103
103
  </candidate>`).join(`
104
104
  `);return`<conflict_evaluation>
105
105
  <new_observation>
@@ -109,7 +109,7 @@ Respond with EXACTLY this XML format:
109
109
  <type>${f.type}</type>
110
110
  </new_observation>
111
111
  <existing_candidates>
112
- ${E}
112
+ ${K}
113
113
  </existing_candidates>
114
114
  <instructions>
115
115
  Evaluate whether the new observation represents:
@@ -124,7 +124,7 @@ Respond with EXACTLY this XML format:
124
124
  <reason>Brief explanation</reason>
125
125
  </evaluation>
126
126
  </instructions>
127
- </conflict_evaluation>`}function Ff(f){let B=[...f.filesRead,...f.filesModified];return`<entity_extraction>
127
+ </conflict_evaluation>`}function Gf(f){let B=[...f.filesRead,...f.filesModified];return`<entity_extraction>
128
128
  <observation>
129
129
  <title>${f.title}</title>
130
130
  <type>${f.type}</type>
@@ -153,32 +153,32 @@ Respond with EXACTLY this XML format:
153
153
  </relations>
154
154
  </extraction>
155
155
  </instructions>
156
- </entity_extraction>`}var U0={"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 V0(f){if(f.includes("."))return f;return U0[f]||`us.anthropic.${f}-v1:0`}function C(f){switch(f.provider){case"anthropic":{let{createAnthropic:B}=D("@ai-sdk/anthropic");return B({apiKey:f.apiKey})(f.model)}case"bedrock":{let{createAmazonBedrock:B}=D("@ai-sdk/amazon-bedrock");return B()(V0(f.model))}case"openai":{let{createOpenAI:B}=D("@ai-sdk/openai");return B({apiKey:f.apiKey})(f.model)}case"google":{let{createGoogleGenerativeAI:B}=D("@ai-sdk/google");return B({apiKey:f.apiKey})(f.model)}default:throw Error(`Unknown provider: ${f.provider}. Supported: anthropic, bedrock, openai, google`)}}function yf(f){try{switch(f.provider){case"google":{let{createGoogleGenerativeAI:B}=D("@ai-sdk/google");return B({apiKey:f.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:B}=D("@ai-sdk/openai");return B({apiKey:f.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:B}=D("@ai-sdk/amazon-bedrock");return B().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;default:return null}}catch{return null}}var H0={"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},Pf=0;async function L(f,B){if(!B)return;let E=H0[f]||5,K=Math.ceil(60000/E)+100,z=Date.now()-Pf;if(z<K){let A=K-z;await new Promise((R)=>setTimeout(R,A))}Pf=Date.now()}class y{model;config;_generate=Y0;constructor(f){this.config=f,this.model=null;let B=f.provider!=="bedrock";if(f.compressionEnabled&&(!B||f.apiKey))try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}static MAX_INPUT_LENGTH=50000;async compress(f,B,E){if(!this.config.compressionEnabled||!this.model)return null;if(B.length<this.config.minOutputLength)return null;let K=M(B),J=B.length>y.MAX_INPUT_LENGTH?`${B.substring(0,y.MAX_INPUT_LENGTH)}
156
+ </entity_extraction>`}var U0={"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 V0(f){if(f.includes("."))return f;return U0[f]||`us.anthropic.${f}-v1:0`}function C(f){switch(f.provider){case"anthropic":{let{createAnthropic:B}=D("@ai-sdk/anthropic");return B({apiKey:f.apiKey})(f.model)}case"bedrock":{let{createAmazonBedrock:B}=D("@ai-sdk/amazon-bedrock");return B()(V0(f.model))}case"openai":{let{createOpenAI:B}=D("@ai-sdk/openai");return B({apiKey:f.apiKey})(f.model)}case"google":{let{createGoogleGenerativeAI:B}=D("@ai-sdk/google");return B({apiKey:f.apiKey})(f.model)}default:throw Error(`Unknown provider: ${f.provider}. Supported: anthropic, bedrock, openai, google`)}}function yf(f){try{switch(f.provider){case"google":{let{createGoogleGenerativeAI:B}=D("@ai-sdk/google");return B({apiKey:f.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:B}=D("@ai-sdk/openai");return B({apiKey:f.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:B}=D("@ai-sdk/amazon-bedrock");return B().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;default:return null}}catch{return null}}var H0={"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},Pf=0;async function L(f,B){if(!B)return;let K=H0[f]||5,E=Math.ceil(60000/K)+100,z=Date.now()-Pf;if(z<E){let $=E-z;await new Promise((R)=>setTimeout(R,$))}Pf=Date.now()}class P{model;config;_generate=Y0;constructor(f){this.config=f,this.model=null;let B=f.provider!=="bedrock";if(f.compressionEnabled&&(!B||f.apiKey))try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}static MAX_INPUT_LENGTH=50000;async compress(f,B,K){if(!this.config.compressionEnabled||!this.model)return null;if(B.length<this.config.minOutputLength)return null;let E=m(B),J=B.length>P.MAX_INPUT_LENGTH?`${B.substring(0,P.MAX_INPUT_LENGTH)}
157
157
 
158
- [... truncated ...]`:B,z=_f(f,J,E),A=2;for(let R=0;R<=A;R++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:N}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:z}),$=kf(N);if($)$.discoveryTokens=K;return $}catch(N){if(k0(N)&&R<A){let $=2**R*1000;await Of($);continue}return null}return null}async compressBatch(f){let B=new Map;for(let E=0;E<f.length;E++){let K=f[E],J=await this.compress(K.toolName,K.toolOutput,K.sessionContext);if(B.set(K.callId,J),E<f.length-1)await Of(200)}return B}createFallbackObservation(f,B){let E=L0(B),K=X0[f]??"discovery";return{type:K,title:`${f} execution`,subtitle:B.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${f} was executed. Output length: ${B.length} chars.`,concepts:[],filesRead:K==="discovery"?E:[],filesModified:K==="change"?E:[],discoveryTokens:M(B),importance:2}}async isAvailable(){if(!this.model)return!1;try{return await this._generate({model:this.model,maxOutputTokens:10,prompt:"ping"}),!0}catch{return!1}}}var X0={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},C0=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function L0(f){let B=[];for(let E of f.matchAll(C0))B.push(E[1]);return[...new Set(B)]}function k0(f){if(typeof f!=="object"||f===null)return!1;let B=f,E=B.status;if(E===429||E===500||E===503)return!0;let K=B.error;if(typeof K==="object"&&K!==null&&K.type==="overloaded_error")return!0;return!1}function Of(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as S0}from"ai";class c{model;config;_generate=S0;constructor(f){if(this.config=f,this.model=null,f.provider==="bedrock"||f.apiKey)try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async evaluate(f,B){if(!this.model||B.length===0)return null;let E=Gf(f,B),K=2;for(let J=0;J<=K;J++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:z}=await this._generate({model:this.model,maxOutputTokens:512,prompt:E});return Df(z)}catch(z){if(D0(z)&&J<K){let A=2**J*1000;await M0(A);continue}return null}return null}}function D0(f){if(typeof f!=="object"||f===null)return!1;let B=f,E=B.status;if(E===429||E===500||E===503)return!0;let K=B.error;if(typeof K==="object"&&K!==null&&K.type==="overloaded_error")return!0;return!1}function M0(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as _0}from"ai";class b{model;config;_generate=_0;constructor(f){if(this.config=f,this.model=null,f.provider==="bedrock"||f.apiKey)try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async extract(f){if(!this.model)return null;let B=Ff(f),E=2;for(let K=0;K<=E;K++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:J}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:B});return Mf(J)}catch(J){if(m0(J)&&K<E){let z=2**K*1000;await G0(z);continue}return null}return null}}function m0(f){if(typeof f!=="object"||f===null)return!1;let B=f,E=B.status;if(E===429||E===500||E===503)return!0;let K=B.error;if(typeof K==="object"&&K!==null&&K.type==="overloaded_error")return!0;return!1}function G0(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as F0}from"ai";class n{model;config;_generate=F0;constructor(f){this.config=f,this.model=null;let B=f.provider!=="bedrock";if(f.compressionEnabled&&(!B||f.apiKey))try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async summarize(f,B){if(B.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(B);let E=mf(B.map((K)=>({type:K.type,title:K.title,narrative:K.narrative})),f);try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:K}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:E}),J=Sf(K);if(!J)return this.createFallbackSummary(B);return J}catch{return this.createFallbackSummary(B)}}createFallbackSummary(f){let B=new Set,E=new Set,K=[];for(let R of f){for(let N of R.filesModified)B.add(N);for(let N of R.concepts)E.add(N);if(R.type==="decision")K.push(R.title)}let J=new Map;for(let R of f)J.set(R.type,(J.get(R.type)??0)+1);let z=Array.from(J.entries()).map(([R,N])=>`${N} ${R}${N>1?"s":""}`).join(", "),A=Array.from(E).slice(0,5).join(", ");return{summary:`Session with ${f.length} observations: ${z}. Files modified: ${B.size}. Key concepts: ${A}.`,keyDecisions:K.slice(0,5),filesModified:Array.from(B),concepts:Array.from(E)}}shouldSummarize(f){return f>=2}}import{existsSync as y0,readFileSync as P0}from"fs";var O0={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1};function j0(){let f={};if(process.env.OPEN_MEM_DB_PATH)f.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)f.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)f.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)f.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")f.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")f.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)f.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((B)=>B.trim());if(process.env.OPEN_MEM_BATCH_SIZE)f.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)f.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)f.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")f.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)f.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((B)=>B.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)f.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)f.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")f.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")f.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")f.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)f.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_DAEMON==="true")f.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")f.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)f.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")f.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")f.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")f.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)f.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)f.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)f.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((B)=>B.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)f.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")f.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let B=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(B))f.conflictSimilarityBandLow=B}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let B=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(B))f.conflictSimilarityBandHigh=B}if(process.env.OPEN_MEM_USER_MEMORY==="true")f.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)f.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)f.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")f.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)f.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")f.entityExtractionEnabled=!0;return f}function q0(f){let B=`${f}/.open-mem/config.json`;if(!y0(B))return{};try{let E=P0(B,"utf-8"),K=JSON.parse(E);if(!K||typeof K!=="object"||Array.isArray(K))return{};return K}catch{return{}}}function h0(f){switch(f){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function jf(f,B){let E=q0(f),K=j0(),J={...O0,...E,...K,...B};if(!J.dbPath.startsWith("/"))J.dbPath=`${f}/${J.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!B?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)J.provider="google";else if(process.env.ANTHROPIC_API_KEY)J.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)J.provider="bedrock"}if(!J.apiKey)switch(J.provider){case"google":J.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":J.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":J.apiKey=process.env.OPENAI_API_KEY;break;case"bedrock":break}if(J.embeddingDimension===void 0)J.embeddingDimension=h0(J.provider);return J}import{Database as qf}from"bun:sqlite";import{existsSync as d,mkdirSync as T0,unlinkSync as hf}from"fs";import*as Tf from"sqlite-vec";class I{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let f=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let B of f)try{if(d(B))return qf.setCustomSQLite(B),!0}catch{return!1}return!1}constructor(f){this.dbPath=f,this.db=this.open(f),this.configure()}open(f){let B=f.lastIndexOf("/");if(B>0){let E=f.substring(0,B);T0(E,{recursive:!0})}return new qf(f,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(f){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",f.message);try{this.db.close()}catch{}this.deleteSidecarFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after removing WAL/SHM files");return}catch(B){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",B.message);try{this.db.close()}catch{}this.deleteDatabaseFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after full database recreation");return}catch(E){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",E.message),f}}}}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{Tf.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let f of["-wal","-shm"]){let B=this.dbPath+f;try{if(d(B))hf(B)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(d(this.dbPath))hf(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
158
+ [... truncated ...]`:B,z=mf(f,J,K),$=2;for(let R=0;R<=$;R++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:N}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:z}),W=kf(N);if(W)W.discoveryTokens=E;return W}catch(N){if(k0(N)&&R<$){let W=2**R*1000;await Of(W);continue}return null}return null}async compressBatch(f){let B=new Map;for(let K=0;K<f.length;K++){let E=f[K],J=await this.compress(E.toolName,E.toolOutput,E.sessionContext);if(B.set(E.callId,J),K<f.length-1)await Of(200)}return B}createFallbackObservation(f,B){let K=L0(B),E=X0[f]??"discovery";return{type:E,title:`${f} execution`,subtitle:B.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${f} was executed. Output length: ${B.length} chars.`,concepts:[],filesRead:E==="discovery"?K:[],filesModified:E==="change"?K:[],discoveryTokens:m(B),importance:2}}async isAvailable(){if(!this.model)return!1;try{return await this._generate({model:this.model,maxOutputTokens:10,prompt:"ping"}),!0}catch{return!1}}}var X0={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},C0=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function L0(f){let B=[];for(let K of f.matchAll(C0))B.push(K[1]);return[...new Set(B)]}function k0(f){if(typeof f!=="object"||f===null)return!1;let B=f,K=B.status;if(K===429||K===500||K===503)return!0;let E=B.error;if(typeof E==="object"&&E!==null&&E.type==="overloaded_error")return!0;return!1}function Of(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as S0}from"ai";class c{model;config;_generate=S0;constructor(f){if(this.config=f,this.model=null,f.provider==="bedrock"||f.apiKey)try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async evaluate(f,B){if(!this.model||B.length===0)return null;let K=Ff(f,B),E=2;for(let J=0;J<=E;J++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:z}=await this._generate({model:this.model,maxOutputTokens:512,prompt:K});return Df(z)}catch(z){if(D0(z)&&J<E){let $=2**J*1000;await M0($);continue}return null}return null}}function D0(f){if(typeof f!=="object"||f===null)return!1;let B=f,K=B.status;if(K===429||K===500||K===503)return!0;let E=B.error;if(typeof E==="object"&&E!==null&&E.type==="overloaded_error")return!0;return!1}function M0(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as m0}from"ai";class b{model;config;_generate=m0;constructor(f){if(this.config=f,this.model=null,f.provider==="bedrock"||f.apiKey)try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async extract(f){if(!this.model)return null;let B=Gf(f),K=2;for(let E=0;E<=K;E++)try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:J}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:B});return Mf(J)}catch(J){if(_0(J)&&E<K){let z=2**E*1000;await F0(z);continue}return null}return null}}function _0(f){if(typeof f!=="object"||f===null)return!1;let B=f,K=B.status;if(K===429||K===500||K===503)return!0;let E=B.error;if(typeof E==="object"&&E!==null&&E.type==="overloaded_error")return!0;return!1}function F0(f){return new Promise((B)=>setTimeout(B,f))}import{generateText as G0}from"ai";class n{model;config;_generate=G0;constructor(f){this.config=f,this.model=null;let B=f.provider!=="bedrock";if(f.compressionEnabled&&(!B||f.apiKey))try{this.model=C({provider:f.provider,model:f.model,apiKey:f.apiKey})}catch{}}async summarize(f,B){if(B.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(B);let K=_f(B.map((E)=>({type:E.type,title:E.title,narrative:E.narrative})),f);try{if(this.config.provider==="google")await L(this.config.model,this.config.rateLimitingEnabled);let{text:E}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:K}),J=Sf(E);if(!J)return this.createFallbackSummary(B);return J}catch{return this.createFallbackSummary(B)}}createFallbackSummary(f){let B=new Set,K=new Set,E=[];for(let R of f){for(let N of R.filesModified)B.add(N);for(let N of R.concepts)K.add(N);if(R.type==="decision")E.push(R.title)}let J=new Map;for(let R of f)J.set(R.type,(J.get(R.type)??0)+1);let z=Array.from(J.entries()).map(([R,N])=>`${N} ${R}${N>1?"s":""}`).join(", "),$=Array.from(K).slice(0,5).join(", ");return{summary:`Session with ${f.length} observations: ${z}. Files modified: ${B.size}. Key concepts: ${$}.`,keyDecisions:E.slice(0,5),filesModified:Array.from(B),concepts:Array.from(K)}}shouldSummarize(f){return f>=2}}import{existsSync as y0,readFileSync as P0}from"fs";var O0={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1};function j0(){let f={};if(process.env.OPEN_MEM_DB_PATH)f.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)f.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)f.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)f.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")f.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")f.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)f.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((B)=>B.trim());if(process.env.OPEN_MEM_BATCH_SIZE)f.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)f.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)f.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")f.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)f.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((B)=>B.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)f.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)f.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")f.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")f.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")f.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)f.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_DAEMON==="true")f.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")f.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)f.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")f.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")f.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")f.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)f.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)f.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)f.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((B)=>B.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)f.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")f.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let B=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(B))f.conflictSimilarityBandLow=B}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let B=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(B))f.conflictSimilarityBandHigh=B}if(process.env.OPEN_MEM_USER_MEMORY==="true")f.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)f.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)f.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")f.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)f.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")f.entityExtractionEnabled=!0;return f}function q0(f){let B=`${f}/.open-mem/config.json`;if(!y0(B))return{};try{let K=P0(B,"utf-8"),E=JSON.parse(K);if(!E||typeof E!=="object"||Array.isArray(E))return{};return E}catch{return{}}}function h0(f){switch(f){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function jf(f,B){let K=q0(f),E=j0(),J={...O0,...K,...E,...B};if(!J.dbPath.startsWith("/"))J.dbPath=`${f}/${J.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!B?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)J.provider="google";else if(process.env.ANTHROPIC_API_KEY)J.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)J.provider="bedrock"}if(!J.apiKey)switch(J.provider){case"google":J.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":J.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":J.apiKey=process.env.OPENAI_API_KEY;break;case"bedrock":break}if(J.embeddingDimension===void 0)J.embeddingDimension=h0(J.provider);return J}import{Database as qf}from"bun:sqlite";import{existsSync as d,mkdirSync as T0,unlinkSync as hf}from"fs";import*as Tf from"sqlite-vec";class x{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let f=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let B of f)try{if(d(B))return qf.setCustomSQLite(B),!0}catch{return!1}return!1}constructor(f){this.dbPath=f,this.db=this.open(f),this.configure()}open(f){let B=f.lastIndexOf("/");if(B>0){let K=f.substring(0,B);T0(K,{recursive:!0})}return new qf(f,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(f){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",f.message);try{this.db.close()}catch{}this.deleteSidecarFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after removing WAL/SHM files");return}catch(B){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",B.message);try{this.db.close()}catch{}this.deleteDatabaseFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after full database recreation");return}catch(K){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",K.message),f}}}}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{Tf.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let f of["-wal","-shm"]){let B=this.dbPath+f;try{if(d(B))hf(B)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(d(this.dbPath))hf(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
159
159
  CREATE TABLE IF NOT EXISTS _migrations (
160
160
  version INTEGER PRIMARY KEY,
161
161
  name TEXT NOT NULL,
162
162
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
163
163
  )
164
- `)}migrate(f){this.ensureMigrationTable();let B=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),E=new Set(B.map((J)=>J.version)),K=f.filter((J)=>!E.has(J.version)).sort((J,z)=>J.version-z.version);for(let J of K)this.db.transaction(()=>{this.db.exec(J.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:J.version,$name:J.name})})()}run(f,B){let E=this.db.query(f);if(B)E.run(...B);else E.run()}get(f,B){let E=this.db.query(f);return B?E.get(...B):E.get()}all(f,B){let E=this.db.query(f);return B?E.all(...B):E.all()}exec(f){this.db.exec(f)}transaction(f){return this.db.transaction(f)()}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function xf(f){return new I(f)}import{randomUUID as If}from"crypto";class r{db;constructor(f){this.db=f}upsertEntity(f,B){let E=If(),K=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
164
+ `)}migrate(f){this.ensureMigrationTable();let B=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),K=new Set(B.map((J)=>J.version)),E=f.filter((J)=>!K.has(J.version)).sort((J,z)=>J.version-z.version);for(let J of E)this.db.transaction(()=>{this.db.exec(J.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:J.version,$name:J.name})})()}run(f,B){let K=this.db.query(f);if(B)K.run(...B);else K.run()}get(f,B){let K=this.db.query(f);return B?K.get(...B):K.get()}all(f,B){let K=this.db.query(f);return B?K.all(...B):K.all()}exec(f){this.db.exec(f)}transaction(f){return this.db.transaction(f)()}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function gf(f){return new x(f)}import{randomUUID as xf}from"crypto";class r{db;constructor(f){this.db=f}upsertEntity(f,B){let K=xf(),E=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
165
165
  VALUES (?, ?, ?, ?, ?, 1)
166
166
  ON CONFLICT(name, entity_type) DO UPDATE SET
167
167
  mention_count = mention_count + 1,
168
- last_seen_at = ?`,[E,f,B,K,K,K]);let J=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[f,B]);if(!J)throw Error(`Failed to upsert entity: ${f} (${B})`);return this.mapEntityRow(J)}createRelation(f,B,E,K){let J=If(),z=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
168
+ last_seen_at = ?`,[K,f,B,E,E,E]);let J=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[f,B]);if(!J)throw Error(`Failed to upsert entity: ${f} (${B})`);return this.mapEntityRow(J)}createRelation(f,B,K,E){let J=xf(),z=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
169
169
  (id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
170
- VALUES (?, ?, ?, ?, ?, ?)`,[J,f,B,E,K,z])}catch{return null}let A=this.db.get(`SELECT * FROM entity_relations
171
- WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[f,B,E]);return A?this.mapRelationRow(A):null}linkObservation(f,B){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[f,B])}findByName(f){try{return this.db.all(`SELECT e.*
170
+ VALUES (?, ?, ?, ?, ?, ?)`,[J,f,B,K,E,z])}catch{return null}let $=this.db.get(`SELECT * FROM entity_relations
171
+ WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[f,B,K]);return $?this.mapRelationRow($):null}linkObservation(f,B){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[f,B])}findByName(f){try{return this.db.all(`SELECT e.*
172
172
  FROM entities e
173
173
  JOIN entities_fts fts ON e._rowid = fts.rowid
174
174
  WHERE entities_fts MATCH ?
175
- ORDER BY rank`,[f]).map((E)=>this.mapEntityRow(E))}catch{return[]}}getRelationsFor(f){return this.db.all(`SELECT * FROM entity_relations
176
- WHERE source_entity_id = ? OR target_entity_id = ?`,[f,f]).map((E)=>this.mapRelationRow(E))}traverseRelations(f,B=1){let E=Math.min(B,2),K=100,J=new Set,z=[{id:f,currentDepth:0}];J.add(f);while(z.length>0){if(J.size>=100)break;let A=z.shift();if(!A)continue;if(A.currentDepth>=E)continue;let R=this.getRelationsFor(A.id);for(let N of R){let $=N.sourceEntityId===A.id?N.targetEntityId:N.sourceEntityId;if(!J.has($))J.add($),z.push({id:$,currentDepth:A.currentDepth+1})}}return J}getObservationsForEntity(f){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[f]).map((E)=>E.observation_id)}getById(f){let B=this.db.get("SELECT * FROM entities WHERE id = ?",[f]);return B?this.mapEntityRow(B):null}mapEntityRow(f){return{id:f.id,name:f.name,entityType:f.entity_type,firstSeenAt:f.first_seen_at,lastSeenAt:f.last_seen_at,mentionCount:f.mention_count}}mapRelationRow(f){return{id:f.id,sourceEntityId:f.source_entity_id,targetEntityId:f.target_entity_id,relationship:f.relationship,observationId:f.observation_id,createdAt:f.created_at}}}import{randomUUID as I0}from"crypto";import{embed as x0}from"ai";async function i(f,B){try{let{embedding:E}=await x0({model:f,value:B});return E}catch{return null}}function gf(f,B){if(f.length!==B.length||f.length===0)return 0;let E=0,K=0,J=0;for(let A=0;A<f.length;A++)E+=f[A]*B[A],K+=f[A]*f[A],J+=B[A]*B[A];let z=Math.sqrt(K)*Math.sqrt(J);if(z===0)return 0;return E/z}function s(f){let B=[f.title,f.narrative];if(f.concepts.length>0)B.push(f.concepts.join(", "));return B.join(`
177
- `)}function g0(f){return f.replace(/[%_\\]/g,"\\$&")}class o{db;constructor(f){this.db=f}create(f){let B=I0(),E=new Date().toISOString(),K=f.discoveryTokens??0,J=f.importance??3,z=f.scope??"project";return this.db.run(`INSERT INTO observations
175
+ ORDER BY rank`,[f]).map((K)=>this.mapEntityRow(K))}catch{return[]}}getRelationsFor(f){return this.db.all(`SELECT * FROM entity_relations
176
+ WHERE source_entity_id = ? OR target_entity_id = ?`,[f,f]).map((K)=>this.mapRelationRow(K))}traverseRelations(f,B=1){let K=Math.min(B,2),E=100,J=new Set,z=[{id:f,currentDepth:0}];J.add(f);while(z.length>0){if(J.size>=100)break;let $=z.shift();if(!$)continue;if($.currentDepth>=K)continue;let R=this.getRelationsFor($.id);for(let N of R){let W=N.sourceEntityId===$.id?N.targetEntityId:N.sourceEntityId;if(!J.has(W))J.add(W),z.push({id:W,currentDepth:$.currentDepth+1})}}return J}getObservationsForEntity(f){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[f]).map((K)=>K.observation_id)}getById(f){let B=this.db.get("SELECT * FROM entities WHERE id = ?",[f]);return B?this.mapEntityRow(B):null}mapEntityRow(f){return{id:f.id,name:f.name,entityType:f.entity_type,firstSeenAt:f.first_seen_at,lastSeenAt:f.last_seen_at,mentionCount:f.mention_count}}mapRelationRow(f){return{id:f.id,sourceEntityId:f.source_entity_id,targetEntityId:f.target_entity_id,relationship:f.relationship,observationId:f.observation_id,createdAt:f.created_at}}}import{randomUUID as x0}from"crypto";import{embed as g0}from"ai";async function i(f,B){try{let{embedding:K}=await g0({model:f,value:B});return K}catch{return null}}function pf(f,B){if(f.length!==B.length||f.length===0)return 0;let K=0,E=0,J=0;for(let $=0;$<f.length;$++)K+=f[$]*B[$],E+=f[$]*f[$],J+=B[$]*B[$];let z=Math.sqrt(E)*Math.sqrt(J);if(z===0)return 0;return K/z}function s(f){let B=[f.title,f.narrative];if(f.concepts.length>0)B.push(f.concepts.join(", "));return B.join(`
177
+ `)}function p0(f){return f.replace(/[%_\\]/g,"\\$&")}class o{db;constructor(f){this.db=f}create(f){let B=x0(),K=new Date().toISOString(),E=f.discoveryTokens??0,J=f.importance??3,z=f.scope??"project";return this.db.run(`INSERT INTO observations
178
178
  (id, session_id, scope, type, title, subtitle, facts, narrative,
179
179
  concepts, files_read, files_modified, raw_tool_output,
180
180
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
181
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[B,f.sessionId,z,f.type,f.title,f.subtitle,JSON.stringify(f.facts),f.narrative,JSON.stringify(f.concepts),JSON.stringify(f.filesRead),JSON.stringify(f.filesModified),f.rawToolOutput,f.toolName,E,f.tokenCount,K,J,null,null]),{...f,id:B,scope:z,createdAt:E,discoveryTokens:K,importance:J,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(f){this.db.run(`INSERT INTO observations
181
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[B,f.sessionId,z,f.type,f.title,f.subtitle,JSON.stringify(f.facts),f.narrative,JSON.stringify(f.concepts),JSON.stringify(f.filesRead),JSON.stringify(f.filesModified),f.rawToolOutput,f.toolName,K,f.tokenCount,E,J,null,null]),{...f,id:B,scope:z,createdAt:K,discoveryTokens:E,importance:J,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(f){this.db.run(`INSERT INTO observations
182
182
  (id, session_id, scope, type, title, subtitle, facts, narrative,
183
183
  concepts, files_read, files_modified, raw_tool_output,
184
184
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
@@ -187,50 +187,50 @@ Respond with EXACTLY this XML format:
187
187
  JOIN sessions s ON o.session_id = s.id
188
188
  WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
189
189
  ORDER BY o.created_at DESC
190
- LIMIT ?`,[f,B]).map((E)=>({id:E.id,sessionId:E.session_id,type:E.type,title:E.title,tokenCount:E.token_count,discoveryTokens:E.discovery_tokens??0,createdAt:E.created_at,importance:E.importance??3}))}listByProject(f,B={}){let{limit:E=50,offset:K=0,type:J,state:z,sessionId:A}=B,R=`SELECT o.*
190
+ LIMIT ?`,[f,B]).map((K)=>({id:K.id,sessionId:K.session_id,type:K.type,title:K.title,tokenCount:K.token_count,discoveryTokens:K.discovery_tokens??0,createdAt:K.created_at,importance:K.importance??3}))}listByProject(f,B={}){let{limit:K=50,offset:E=0,type:J,state:z,sessionId:$}=B,R=`SELECT o.*
191
191
  FROM observations o
192
192
  JOIN sessions s ON o.session_id = s.id
193
- WHERE s.project_path = ?`,N=[f];if(A)R+=" AND o.session_id = ?",N.push(A);if(J)R+=" AND o.type = ?",N.push(J);if(z==="current")R+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(z==="superseded")R+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(z==="tombstoned")R+=" AND o.deleted_at IS NOT NULL";else R+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return R+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",N.push(E,K),this.db.all(R,N).map(($)=>this.mapRow($))}search(f){let B=!!f.projectPath,E=`
193
+ WHERE s.project_path = ?`,N=[f];if($)R+=" AND o.session_id = ?",N.push($);if(J)R+=" AND o.type = ?",N.push(J);if(z==="current")R+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(z==="superseded")R+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(z==="tombstoned")R+=" AND o.deleted_at IS NOT NULL";else R+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return R+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",N.push(K,E),this.db.all(R,N).map((W)=>this.mapRow(W))}search(f){let B=!!f.projectPath,K=`
194
194
  SELECT o.*, rank
195
195
  FROM observations o
196
196
  JOIN observations_fts fts ON o._rowid = fts.rowid
197
197
  ${B?"JOIN sessions s ON o.session_id = s.id":""}
198
198
  WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
199
- `,K=[f.query];if(B&&f.projectPath)E+=" AND s.project_path = ?",K.push(f.projectPath);if(f.sessionId)E+=" AND o.session_id = ?",K.push(f.sessionId);if(f.type)E+=" AND o.type = ?",K.push(f.type);if(f.importanceMin!==void 0)E+=" AND o.importance >= ?",K.push(f.importanceMin);if(f.importanceMax!==void 0)E+=" AND o.importance <= ?",K.push(f.importanceMax);if(f.createdAfter)E+=" AND o.created_at >= ?",K.push(f.createdAfter);if(f.createdBefore)E+=" AND o.created_at <= ?",K.push(f.createdBefore);if(f.concepts&&f.concepts.length>0){let J=f.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");E+=` AND (${J.join(" OR ")})`;for(let z of f.concepts)K.push(z)}if(f.files&&f.files.length>0){let J=f.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
200
- OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);E+=` AND (${J.join(" OR ")})`;for(let z of f.files){let A=`%${g0(z)}%`;K.push(A,A)}}return E+=" ORDER BY rank LIMIT ? OFFSET ?",K.push(f.limit??10),K.push(f.offset??0),this.db.all(E,K).map((J)=>({observation:this.mapRow(J),rank:J.rank,snippet:J.title}))}searchByConcept(f,B=10,E){let K=!!E,J=`SELECT o.*
199
+ `,E=[f.query];if(B&&f.projectPath)K+=" AND s.project_path = ?",E.push(f.projectPath);if(f.sessionId)K+=" AND o.session_id = ?",E.push(f.sessionId);if(f.type)K+=" AND o.type = ?",E.push(f.type);if(f.importanceMin!==void 0)K+=" AND o.importance >= ?",E.push(f.importanceMin);if(f.importanceMax!==void 0)K+=" AND o.importance <= ?",E.push(f.importanceMax);if(f.createdAfter)K+=" AND o.created_at >= ?",E.push(f.createdAfter);if(f.createdBefore)K+=" AND o.created_at <= ?",E.push(f.createdBefore);if(f.concepts&&f.concepts.length>0){let J=f.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");K+=` AND (${J.join(" OR ")})`;for(let z of f.concepts)E.push(z)}if(f.files&&f.files.length>0){let J=f.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
200
+ OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);K+=` AND (${J.join(" OR ")})`;for(let z of f.files){let $=`%${p0(z)}%`;E.push($,$)}}return K+=" ORDER BY rank LIMIT ? OFFSET ?",E.push(f.limit??10),E.push(f.offset??0),this.db.all(K,E).map((J)=>({observation:this.mapRow(J),rank:J.rank,snippet:J.title}))}searchByConcept(f,B=10,K){let E=!!K,J=`SELECT o.*
201
201
  FROM observations o
202
202
  JOIN observations_fts fts ON o._rowid = fts.rowid
203
- ${K?"JOIN sessions s ON o.session_id = s.id":""}
203
+ ${E?"JOIN sessions s ON o.session_id = s.id":""}
204
204
  WHERE observations_fts MATCH ?
205
205
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
206
- ${K?"AND s.project_path = ?":""}
206
+ ${E?"AND s.project_path = ?":""}
207
207
  ORDER BY rank
208
- LIMIT ?`,z=[`concepts:${f}`];if(K&&E)z.push(E);return z.push(B),this.db.all(J,z).map((A)=>this.mapRow(A))}searchByFile(f,B=10,E){let K=!!E,J=`SELECT o.*
208
+ LIMIT ?`,z=[`concepts:${f}`];if(E&&K)z.push(K);return z.push(B),this.db.all(J,z).map(($)=>this.mapRow($))}searchByFile(f,B=10,K){let E=!!K,J=`SELECT o.*
209
209
  FROM observations o
210
210
  JOIN observations_fts fts ON o._rowid = fts.rowid
211
- ${K?"JOIN sessions s ON o.session_id = s.id":""}
211
+ ${E?"JOIN sessions s ON o.session_id = s.id":""}
212
212
  WHERE observations_fts MATCH ?
213
213
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
214
- ${K?"AND s.project_path = ?":""}
214
+ ${E?"AND s.project_path = ?":""}
215
215
  ORDER BY rank
216
- LIMIT ?`,z=[`files_read:"${f.replace(/"/g,'""')}" OR files_modified:"${f.replace(/"/g,'""')}"`];if(K&&E)z.push(E);return z.push(B),this.db.all(J,z).map((A)=>this.mapRow(A))}setEmbedding(f,B){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(B),f])}getWithEmbeddings(f,B){return this.db.all(`SELECT o.id, o.embedding, o.title
216
+ LIMIT ?`,z=[`files_read:"${f.replace(/"/g,'""')}" OR files_modified:"${f.replace(/"/g,'""')}"`];if(E&&K)z.push(K);return z.push(B),this.db.all(J,z).map(($)=>this.mapRow($))}setEmbedding(f,B){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(B),f])}getWithEmbeddings(f,B){return this.db.all(`SELECT o.id, o.embedding, o.title
217
217
  FROM observations o
218
218
  JOIN sessions s ON o.session_id = s.id
219
219
  WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
220
220
  ORDER BY o.created_at DESC
221
- LIMIT ?`,[f,B]).map((E)=>{try{return{id:E.id,embedding:JSON.parse(E.embedding),title:E.title}}catch{return null}}).filter((E)=>E!==null)}findSimilar(f,B,E,K){let J=this.db.all(`SELECT id, embedding FROM observations
221
+ LIMIT ?`,[f,B]).map((K)=>{try{return{id:K.id,embedding:JSON.parse(K.embedding),title:K.title}}catch{return null}}).filter((K)=>K!==null)}findSimilar(f,B,K,E){let J=this.db.all(`SELECT id, embedding FROM observations
222
222
  WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
223
223
  ORDER BY created_at DESC
224
- LIMIT 200`,[B]),z=[];for(let A of J)try{let R=JSON.parse(A.embedding);if(!Array.isArray(R)||R.length!==f.length)continue;let N=gf(f,R);if(N>=E)z.push({id:A.id,similarity:N})}catch{}return z.sort((A,R)=>R.similarity-A.similarity).slice(0,K)}insertVecEmbedding(f,B){let E=new Float32Array(B);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[f]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[f,E]),this.db.run("COMMIT")}catch(K){throw this.db.run("ROLLBACK"),K}}migrateExistingEmbeddings(f){let B=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),E=0,K=0;for(let J of B)try{let z=JSON.parse(J.embedding);if(!Array.isArray(z)||z.length!==f){K++;continue}this.insertVecEmbedding(J.id,z),E++}catch{K++}return{migrated:E,skipped:K}}getVecEmbeddingMatches(f,B){try{let E=new Float32Array(f);return this.db.all(`SELECT observation_id, distance
224
+ LIMIT 200`,[B]),z=[];for(let $ of J)try{let R=JSON.parse($.embedding);if(!Array.isArray(R)||R.length!==f.length)continue;let N=pf(f,R);if(N>=K)z.push({id:$.id,similarity:N})}catch{}return z.sort(($,R)=>R.similarity-$.similarity).slice(0,E)}insertVecEmbedding(f,B){let K=new Float32Array(B);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[f]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[f,K]),this.db.run("COMMIT")}catch(E){throw this.db.run("ROLLBACK"),E}}migrateExistingEmbeddings(f){let B=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),K=0,E=0;for(let J of B)try{let z=JSON.parse(J.embedding);if(!Array.isArray(z)||z.length!==f){E++;continue}this.insertVecEmbedding(J.id,z),K++}catch{E++}return{migrated:K,skipped:E}}getVecEmbeddingMatches(f,B){try{let K=new Float32Array(f);return this.db.all(`SELECT observation_id, distance
225
225
  FROM observation_embeddings
226
- WHERE embedding MATCH ? AND k = ?`,[E,B]).map((K)=>({observationId:K.observation_id,distance:K.distance}))}catch{return[]}}searchVecSubset(f,B,E){if(B.length===0)return[];try{let K=new Float32Array(f),J=Math.max(E*5,B.length),z=this.db.all(`SELECT observation_id, distance
226
+ WHERE embedding MATCH ? AND k = ?`,[K,B]).map((E)=>({observationId:E.observation_id,distance:E.distance}))}catch{return[]}}searchVecSubset(f,B,K){if(B.length===0)return[];try{let E=new Float32Array(f),J=Math.max(K*5,B.length),z=this.db.all(`SELECT observation_id, distance
227
227
  FROM observation_embeddings
228
- WHERE embedding MATCH ? AND k = ?`,[K,J]),A=new Set(B);return z.filter((R)=>A.has(R.observation_id)).slice(0,E).map((R)=>({observationId:R.observation_id,distance:R.distance}))}catch{return[]}}update(f,B){let E=this.getById(f);if(!E)return null;if(Object.keys(B).length===0)return E;let K=this.create({sessionId:E.sessionId,scope:E.scope??"project",type:B.type??E.type,title:B.title??E.title,subtitle:B.subtitle??E.subtitle,facts:B.facts??E.facts,narrative:B.narrative??E.narrative,concepts:B.concepts??E.concepts,filesRead:B.filesRead??E.filesRead,filesModified:B.filesModified??E.filesModified,rawToolOutput:E.rawToolOutput,toolName:"memory.revise",tokenCount:E.tokenCount,discoveryTokens:E.discoveryTokens,importance:B.importance??E.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[f,K.id]),this.supersede(f,K.id),this.getById(K.id)}supersede(f,B){let E=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[B,E,f])}delete(f){if(this.db.all("SELECT id FROM observations WHERE id = ?",[f]).length===0)return!1;let E=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[E,f]),this.deleteEmbeddingsForObservations([f]),!0}getLineage(f){let B=this.getByIdIncludingArchived(f);if(!B)return[];let E=new Set([B.id]),K=[B];while(K[0].revisionOf){let J=this.getByIdIncludingArchived(K[0].revisionOf);if(!J||E.has(J.id))break;K.unshift(J),E.add(J.id)}while(K[K.length-1].supersededBy){let J=K[K.length-1].supersededBy;if(!J)break;let z=this.getByIdIncludingArchived(J);if(!z||E.has(z.id))break;K.push(z),E.add(z.id)}return K}deleteOlderThan(f){return this.db.all(`DELETE FROM observations
228
+ WHERE embedding MATCH ? AND k = ?`,[E,J]),$=new Set(B);return z.filter((R)=>$.has(R.observation_id)).slice(0,K).map((R)=>({observationId:R.observation_id,distance:R.distance}))}catch{return[]}}update(f,B){let K=this.getById(f);if(!K)return null;if(Object.keys(B).length===0)return K;let E=this.create({sessionId:K.sessionId,scope:K.scope??"project",type:B.type??K.type,title:B.title??K.title,subtitle:B.subtitle??K.subtitle,facts:B.facts??K.facts,narrative:B.narrative??K.narrative,concepts:B.concepts??K.concepts,filesRead:B.filesRead??K.filesRead,filesModified:B.filesModified??K.filesModified,rawToolOutput:K.rawToolOutput,toolName:"memory.revise",tokenCount:K.tokenCount,discoveryTokens:K.discoveryTokens,importance:B.importance??K.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[f,E.id]),this.supersede(f,E.id),this.getById(E.id)}supersede(f,B){let K=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[B,K,f])}delete(f){if(this.db.all("SELECT id FROM observations WHERE id = ?",[f]).length===0)return!1;let K=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[K,f]),this.deleteEmbeddingsForObservations([f]),!0}getLineage(f){let B=this.getByIdIncludingArchived(f);if(!B)return[];let K=new Set([B.id]),E=[B];while(E[0].revisionOf){let J=this.getByIdIncludingArchived(E[0].revisionOf);if(!J||K.has(J.id))break;E.unshift(J),K.add(J.id)}while(E[E.length-1].supersededBy){let J=E[E.length-1].supersededBy;if(!J)break;let z=this.getByIdIncludingArchived(J);if(!z||K.has(z.id))break;E.push(z),K.add(z.id)}return E}deleteOlderThan(f){return this.db.all(`DELETE FROM observations
229
229
  WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
230
230
  AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
231
- RETURNING id`,[f]).length}deleteEmbeddingsForObservations(f){if(f.length===0)return;let B=f.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${B})`,f)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${B})`,f)}mapRow(f){return{id:f.id,sessionId:f.session_id,scope:f.scope??"project",type:f.type,title:f.title,subtitle:f.subtitle,facts:JSON.parse(f.facts),narrative:f.narrative,concepts:JSON.parse(f.concepts),filesRead:JSON.parse(f.files_read),filesModified:JSON.parse(f.files_modified),rawToolOutput:f.raw_tool_output,toolName:f.tool_name,createdAt:f.created_at,tokenCount:f.token_count,discoveryTokens:f.discovery_tokens??0,importance:f.importance??3,revisionOf:f.revision_of??null,deletedAt:f.deleted_at??null,supersededBy:f.superseded_by??null,supersededAt:f.superseded_at??null}}}import{randomUUID as p0}from"crypto";class t{db;constructor(f){this.db=f}create(f){let B=p0(),E=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
231
+ RETURNING id`,[f]).length}deleteEmbeddingsForObservations(f){if(f.length===0)return;let B=f.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${B})`,f)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${B})`,f)}mapRow(f){return{id:f.id,sessionId:f.session_id,scope:f.scope??"project",type:f.type,title:f.title,subtitle:f.subtitle,facts:JSON.parse(f.facts),narrative:f.narrative,concepts:JSON.parse(f.concepts),filesRead:JSON.parse(f.files_read),filesModified:JSON.parse(f.files_modified),rawToolOutput:f.raw_tool_output,toolName:f.tool_name,createdAt:f.created_at,tokenCount:f.token_count,discoveryTokens:f.discovery_tokens??0,importance:f.importance??3,revisionOf:f.revision_of??null,deletedAt:f.deleted_at??null,supersededBy:f.superseded_by??null,supersededAt:f.superseded_at??null}}}import{randomUUID as I0}from"crypto";class t{db;constructor(f){this.db=f}create(f){let B=I0(),K=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
232
232
  (id, session_id, tool_name, tool_output, call_id, created_at)
233
- VALUES (?, ?, ?, ?, ?, ?)`,[B,f.sessionId,f.toolName,f.toolOutput,f.callId,E]),{...f,id:B,createdAt:E,status:"pending",retryCount:0,error:null}}getPending(f=10){return this.db.all("SELECT * FROM pending_messages WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?",[f]).map((B)=>this.mapRow(B))}getByStatus(f){return this.db.all("SELECT * FROM pending_messages WHERE status = ? ORDER BY created_at ASC",[f]).map((B)=>this.mapRow(B))}markProcessing(f){this.db.run("UPDATE pending_messages SET status = 'processing' WHERE id = ?",[f])}markCompleted(f){this.db.run("UPDATE pending_messages SET status = 'completed' WHERE id = ?",[f])}markFailed(f,B){this.db.run("UPDATE pending_messages SET status = 'failed', error = ?, retry_count = retry_count + 1 WHERE id = ?",[B,f])}resetStale(f=5){return this.db.all(`UPDATE pending_messages SET status = 'pending'
233
+ VALUES (?, ?, ?, ?, ?, ?)`,[B,f.sessionId,f.toolName,f.toolOutput,f.callId,K]),{...f,id:B,createdAt:K,status:"pending",retryCount:0,error:null}}getPending(f=10){return this.db.all("SELECT * FROM pending_messages WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?",[f]).map((B)=>this.mapRow(B))}getByStatus(f){return this.db.all("SELECT * FROM pending_messages WHERE status = ? ORDER BY created_at ASC",[f]).map((B)=>this.mapRow(B))}markProcessing(f){this.db.run("UPDATE pending_messages SET status = 'processing' WHERE id = ?",[f])}markCompleted(f){this.db.run("UPDATE pending_messages SET status = 'completed' WHERE id = ?",[f])}markFailed(f,B){this.db.run("UPDATE pending_messages SET status = 'failed', error = ?, retry_count = retry_count + 1 WHERE id = ?",[B,f])}resetStale(f=5){return this.db.all(`UPDATE pending_messages SET status = 'pending'
234
234
  WHERE status = 'processing'
235
235
  AND created_at < datetime('now', ? || ' minutes')
236
236
  RETURNING id`,[`-${f}`]).length}deleteCompletedOlderThan(f){return this.db.all(`DELETE FROM pending_messages
@@ -530,15 +530,15 @@ Respond with EXACTLY this XML format:
530
530
  INSERT INTO entities_fts(rowid, name, entity_type)
531
531
  VALUES (new._rowid, new.name, new.entity_type);
532
532
  END;
533
- `}];function pf(f,B){if(f.migrate(w0),B?.hasVectorExtension&&B?.embeddingDimension&&B.embeddingDimension>0)l0(f,B.embeddingDimension)}function l0(f,B){if(f.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let K=f.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(K&&Number(K.value)!==B){console.warn(`[open-mem] vec0 table exists with dimension ${K.value}, but config specifies ${B}. Drop observation_embeddings to re-create with new dimension.`);return}}else f.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
533
+ `}];function If(f,B){if(f.migrate(w0),B?.hasVectorExtension&&B?.embeddingDimension&&B.embeddingDimension>0)l0(f,B.embeddingDimension)}function l0(f,B){if(f.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let E=f.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(E&&Number(E.value)!==B){console.warn(`[open-mem] vec0 table exists with dimension ${E.value}, but config specifies ${B}. Drop observation_embeddings to re-create with new dimension.`);return}}else f.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
534
534
  observation_id TEXT PRIMARY KEY,
535
535
  embedding float[${B}] distance_metric=cosine
536
- )`);f.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(B)])}class e{db;constructor(f){this.db=f}create(f,B){let E=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
537
- VALUES (?, ?, ?, 'active')`,[f,B,E]),this.getById(f)}getOrCreate(f,B){let E=this.getById(f);if(E)return E;return this.create(f,B)}getById(f){let B=this.db.get("SELECT * FROM sessions WHERE id = ?",[f]);return B?this.mapRow(B):null}getRecent(f,B=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[f,B]).map((E)=>this.mapRow(E))}getAll(f){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[f]).map((B)=>this.mapRow(B))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((f)=>this.mapRow(f))}updateStatus(f,B){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[B,f])}markCompleted(f){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[f])}incrementObservationCount(f){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[f])}setSummary(f,B){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[B,f])}mapRow(f){return{id:f.id,projectPath:f.project_path,startedAt:f.started_at,endedAt:f.ended_at??null,status:f.status,observationCount:f.observation_count,summaryId:f.summary_id??null}}}import{randomUUID as v0}from"crypto";class a{db;constructor(f){this.db=f}create(f){let B=v0(),E=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
536
+ )`);f.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(B)])}class e{db;constructor(f){this.db=f}create(f,B){let K=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
537
+ VALUES (?, ?, ?, 'active')`,[f,B,K]),this.getById(f)}getOrCreate(f,B){let K=this.getById(f);if(K)return K;return this.create(f,B)}getById(f){let B=this.db.get("SELECT * FROM sessions WHERE id = ?",[f]);return B?this.mapRow(B):null}getRecent(f,B=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[f,B]).map((K)=>this.mapRow(K))}getAll(f){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[f]).map((B)=>this.mapRow(B))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((f)=>this.mapRow(f))}updateStatus(f,B){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[B,f])}markCompleted(f){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[f])}incrementObservationCount(f){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[f])}setSummary(f,B){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[B,f])}mapRow(f){return{id:f.id,projectPath:f.project_path,startedAt:f.started_at,endedAt:f.ended_at??null,status:f.status,observationCount:f.observation_count,summaryId:f.summary_id??null}}}import{randomUUID as v0}from"crypto";class a{db;constructor(f){this.db=f}create(f){let B=v0(),K=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
538
538
  (id, session_id, summary, key_decisions, files_modified,
539
539
  concepts, created_at, token_count,
540
540
  request, investigated, learned, completed, next_steps)
541
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[B,f.sessionId,f.summary,JSON.stringify(f.keyDecisions),JSON.stringify(f.filesModified),JSON.stringify(f.concepts),E,f.tokenCount,f.request??"",f.investigated??"",f.learned??"",f.completed??"",f.nextSteps??""]),{...f,id:B,createdAt:E}}importSummary(f){this.db.run(`INSERT INTO session_summaries
541
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[B,f.sessionId,f.summary,JSON.stringify(f.keyDecisions),JSON.stringify(f.filesModified),JSON.stringify(f.concepts),K,f.tokenCount,f.request??"",f.investigated??"",f.learned??"",f.completed??"",f.nextSteps??""]),{...f,id:B,createdAt:K}}importSummary(f){this.db.run(`INSERT INTO session_summaries
542
542
  (id, session_id, summary, key_decisions, files_modified,
543
543
  concepts, created_at, token_count,
544
544
  request, investigated, learned, completed, next_steps)
@@ -547,5 +547,5 @@ Respond with EXACTLY this XML format:
547
547
  JOIN summaries_fts fts ON ss._rowid = fts.rowid
548
548
  WHERE summaries_fts MATCH ?
549
549
  ORDER BY rank
550
- LIMIT ?`,[f,B]).map((E)=>this.mapRow(E))}mapRow(f){return{id:f.id,sessionId:f.session_id,summary:f.summary,keyDecisions:JSON.parse(f.key_decisions),filesModified:JSON.parse(f.files_modified),concepts:JSON.parse(f.concepts),createdAt:f.created_at,tokenCount:f.token_count,request:f.request||void 0,investigated:f.investigated||void 0,learned:f.learned||void 0,completed:f.completed||void 0,nextSteps:f.next_steps||void 0}}}class ff{config;compressor;summarizer;pendingRepo;observationRepo;sessionRepo;summaryRepo;embeddingModel;conflictEvaluator;entityExtractor;entityRepo;observer;processing=!1;timer=null;mode="in-process";onEnqueue=null;constructor(f,B,E,K,J,z,A,R=null,N=null,$=null,W=null,Q=null){this.config=f;this.compressor=B;this.summarizer=E;this.pendingRepo=K;this.observationRepo=J;this.sessionRepo=z;this.summaryRepo=A;this.embeddingModel=R;this.conflictEvaluator=N;this.entityExtractor=$;this.entityRepo=W;this.observer=Q}setMode(f){if(this.mode=f,f==="enqueue-only")this.stop()}getMode(){return this.mode}setOnEnqueue(f){this.onEnqueue=f}enqueue(f,B,E,K){if(this.pendingRepo.create({sessionId:f,toolName:B,toolOutput:E,callId:K}),this.observer?.onEnqueue?.({sessionId:f,toolName:B,createdAt:new Date().toISOString()}),this.mode==="enqueue-only")this.onEnqueue?.()}async processBatch(){if(this.mode==="enqueue-only")return 0;if(this.processing)return 0;this.processing=!0;let f=0,B=0,E=Date.now();try{this.pendingRepo.resetStale(5);let K=this.pendingRepo.getPending(this.config.batchSize);if(this.observer?.onBatchStart?.({pending:K.length,mode:this.mode,startedAt:new Date(E).toISOString()}),K.length===0)return 0;for(let J of K)try{this.pendingRepo.markProcessing(J.id);let A=await this.compressor.compress(J.toolName,J.toolOutput)??this.compressor.createFallbackObservation(J.toolName,J.toolOutput),R=!1,N=null;if(this.embeddingModel)try{let W=s({title:A.title,narrative:A.narrative,concepts:A.concepts}),Q=await i(this.embeddingModel,W);if(Q){let Z=this.config.conflictResolutionEnabled&&this.conflictEvaluator,V=this.config.conflictSimilarityBandLow??0.7,k=this.config.conflictSimilarityBandHigh??0.92;if(Z){let X=this.observationRepo.findSimilar(Q,A.type,V,5),_=X.find((m)=>m.similarity>k);if(_)console.log(`[open-mem] Dedup: skipping duplicate of ${_.id} (similarity: ${_.similarity.toFixed(3)})`),R=!0;else{let m=X.filter((S)=>S.similarity>=V&&S.similarity<=k);if(m.length>0)try{let S=m.map((U)=>{let G=this.observationRepo.getById(U.id);return G?{id:G.id,title:G.title,narrative:G.narrative,concepts:G.concepts,type:G.type}:null}).filter((U)=>U!==null);if(S.length>0&&this.conflictEvaluator){let U=await this.conflictEvaluator.evaluate({title:A.title,narrative:A.narrative,concepts:A.concepts,type:A.type},S);if(U&&U.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${U.reason})`),R=!0;else if(U&&U.outcome==="update"&&U.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${U.supersedesId} (${U.reason})`),N=U.supersedesId}}catch{}}}else{let X=this.observationRepo.findSimilar(Q,A.type,0.92,1);if(X.length>0)console.log(`[open-mem] Dedup: skipping duplicate of ${X[0].id} (similarity: ${X[0].similarity.toFixed(3)})`),R=!0}}}catch{}if(R){this.pendingRepo.markCompleted(J.id);continue}let $=this.observationRepo.create({sessionId:J.sessionId,type:A.type,title:A.title,subtitle:A.subtitle,facts:A.facts,narrative:A.narrative,concepts:A.concepts,filesRead:A.filesRead,filesModified:A.filesModified,rawToolOutput:J.toolOutput,toolName:J.toolName,tokenCount:M(`${A.title} ${A.narrative} ${A.facts.join(" ")}`),discoveryTokens:A.discoveryTokens??M(J.toolOutput),importance:A.importance??3});if(this.embeddingModel)try{let W=s({title:$.title,narrative:$.narrative,concepts:$.concepts}),Q=await i(this.embeddingModel,W);if(Q)this.observationRepo.setEmbedding($.id,Q)}catch{}if(N)try{this.observationRepo.supersede(N,$.id),console.log(`[open-mem] Superseded observation ${N} with ${$.id}`)}catch(W){console.error(`[open-mem] Failed to supersede ${N}:`,W)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let W=await this.entityExtractor.extract({title:$.title,narrative:$.narrative,concepts:$.concepts,facts:$.facts,filesRead:$.filesRead,filesModified:$.filesModified,type:$.type});if(W){let Q=new Map;for(let Z of W.entities){let V=this.entityRepo.upsertEntity(Z.name,Z.entityType);Q.set(Z.name,V.id),this.entityRepo.linkObservation(V.id,$.id)}for(let Z of W.relations){let V=Q.get(Z.sourceName),k=Q.get(Z.targetName);if(V&&k)this.entityRepo.createRelation(V,k,Z.relationship,$.id)}}}catch{}this.sessionRepo.incrementObservationCount(J.sessionId),this.pendingRepo.markCompleted(J.id),f++}catch(z){this.pendingRepo.markFailed(J.id,String(z)),B++,this.observer?.onItemFailed?.({pendingId:J.id,error:String(z),failedAt:new Date().toISOString()})}return f}finally{this.observer?.onBatchEnd?.({processed:f,failed:B,durationMs:Date.now()-E,finishedAt:new Date().toISOString()}),this.processing=!1}}async summarizeSession(f){let B=this.observationRepo.getBySession(f);if(!this.summarizer.shouldSummarize(B.length))return;if(this.summaryRepo.getBySessionId(f))return;let K=await this.summarizer.summarize(f,B);if(!K)return;let J=this.summaryRepo.create({sessionId:f,summary:K.summary,keyDecisions:K.keyDecisions,filesModified:K.filesModified,concepts:K.concepts,tokenCount:M(K.summary)});this.sessionRepo.setSummary(f,J.id)}start(){if(this.mode==="enqueue-only")return;if(this.timer)return;this.timer=setInterval(async()=>{try{await this.processBatch()}catch{}},this.config.batchIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get isProcessing(){return this.processing}getStats(){return{pending:this.pendingRepo.getPending(1000).length,processing:this.processing}}}import{spawnSync as wf}from"child_process";import{dirname as c0,resolve as lf}from"path";function b0(f){try{let B=wf("git",["rev-parse","--git-common-dir"],{cwd:f,encoding:"utf-8",timeout:5000});if(B.status!==0||!B.stdout)return null;let E=B.stdout.trim();if(E===".git")return null;let K=wf("git",["rev-parse","--git-dir"],{cwd:f,encoding:"utf-8",timeout:5000});if(K.status!==0||!K.stdout)return null;let J=K.stdout.trim(),z=lf(f,E),A=lf(f,J);if(z===A)return null;let R=c0(z);if(R===z||R==="/")return null;return R}catch{return null}}function vf(f){return b0(f)??f}function Bf(f){process.stdout.write(`${JSON.stringify(f)}
551
- `)}function r0(){let{values:f}=d0({options:{project:{type:"string",short:"p"},"http-port":{type:"string"}},strict:!1}),B=typeof f.project==="string"?f.project:process.cwd(),E=f["http-port"],K=typeof E==="string"&&Number.parseInt(E,10)>0?Number.parseInt(E,10):void 0;return{projectDir:B,httpPort:K}}function i0(f,B){if(f==="claude-code"&&!B.platformClaudeCodeEnabled)throw Error("Claude Code adapter is disabled. Set OPEN_MEM_PLATFORM_CLAUDE_CODE=true.");if(f==="cursor"&&!B.platformCursorEnabled)throw Error("Cursor adapter is disabled. Set OPEN_MEM_PLATFORM_CURSOR=true.")}function s0(f,B){let E=vf(B),K=jf(E);i0(f,K),I.enableExtensionSupport();let J=xf(K.dbPath);pf(J,{hasVectorExtension:J.hasVectorExtension,embeddingDimension:K.embeddingDimension});let z=new e(J),A=new o(J),R=new a(J),N=new t(J),$=new y(K),W=new n(K),Q=K.provider!=="bedrock",Z=K.compressionEnabled&&(!Q||K.apiKey)?yf({provider:K.provider,model:K.model,apiKey:K.apiKey}):null,V=K.conflictResolutionEnabled&&(!Q||K.apiKey)?new c({provider:K.provider,apiKey:K.apiKey,model:K.model,rateLimitingEnabled:K.rateLimitingEnabled}):null,k=K.entityExtractionEnabled&&(!Q||K.apiKey)?new b({provider:K.provider,apiKey:K.apiKey,model:K.model,rateLimitingEnabled:K.rateLimitingEnabled}):null,X=new r(J),_=new ff(K,$,W,N,A,z,R,Z,V,k,X),m=f==="claude-code"?Af():Rf(),S=new v({adapter:m,queue:_,sessions:z,observations:A,pendingMessages:N,projectPath:E,config:K});return{db:J,queue:_,runtime:S,platform:f,projectPath:E}}function cf(f,B){let E=f.queue.getStats();return{id:B,ok:!0,code:"OK",status:{platform:f.platform,projectPath:f.projectPath,queue:{mode:f.queue.getMode(),running:f.queue.isRunning,processing:E.processing,pending:E.pending}}}}function Ef(f){if(!f||typeof f!=="object"||Array.isArray(f))return{command:"event",payload:f};let B=f,E=typeof B.command==="string"&&(B.command==="event"||B.command==="flush"||B.command==="health"||B.command==="shutdown")?B.command:void 0,K=typeof B.id==="string"||typeof B.id==="number"?B.id:void 0;if(!E)return{command:"event",payload:f,id:K};return{id:K,command:E,payload:"payload"in B?B.payload:void 0}}async function bf(f){let B=r0(),E=s0(f,B.projectDir);E.queue.start();let K=!1,J=async()=>{if(K)return;K=!0;try{await E.queue.processBatch()}catch{}E.queue.stop(),E.db.close(),process.exit(0)},z=async(N)=>{let $=N.command??"event";if($==="health")return cf(E,N.id);if($==="flush"){let Q=await E.queue.processBatch();return{id:N.id,ok:!0,code:"OK",processed:Q}}if($==="shutdown")return{id:N.id,ok:!0,code:"OK",message:"shutting down"};if(!await E.runtime.ingestRaw(N.payload))return{id:N.id,ok:!1,code:"UNSUPPORTED_EVENT",message:"Payload did not match adapter event schema"};return{id:N.id,ok:!0,code:"OK",ingested:!0}};if(B.httpPort)Bun.serve({port:B.httpPort,hostname:"127.0.0.1",idleTimeout:0,fetch:async(N)=>{if(N.method==="GET"&&new URL(N.url).pathname==="/v1/health")return Response.json(cf(E));if(N.method==="POST"&&new URL(N.url).pathname==="/v1/events"){let $;try{$=await N.json()}catch{return Response.json({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"},{status:400})}try{let W=await z(Ef($));if((Ef($).command??"event")==="shutdown")setTimeout(()=>{J()},0);return Response.json(W,{status:W.ok?200:422})}catch(W){return Response.json({ok:!1,code:"INGESTION_FAILED",message:String(W)},{status:500})}}return Response.json({ok:!1,code:"NOT_FOUND"},{status:404})}});process.on("SIGINT",()=>{J()}),process.on("SIGTERM",()=>{J()});let A=Promise.resolve(),R=n0({input:process.stdin,terminal:!1});R.on("line",(N)=>{let $=N.trim();if(!$)return;A=A.then(async()=>{let W;try{W=JSON.parse($)}catch{Bf({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"});return}try{let Q=Ef(W),Z=await z(Q);if(Bf(Z),(Q.command??"event")==="shutdown")await J()}catch(Q){Bf({ok:!1,code:"INGESTION_FAILED",message:String(Q)})}})}),R.on("close",()=>{A.finally(()=>J())})}bf("claude-code");
550
+ LIMIT ?`,[f,B]).map((K)=>this.mapRow(K))}mapRow(f){return{id:f.id,sessionId:f.session_id,summary:f.summary,keyDecisions:JSON.parse(f.key_decisions),filesModified:JSON.parse(f.files_modified),concepts:JSON.parse(f.concepts),createdAt:f.created_at,tokenCount:f.token_count,request:f.request||void 0,investigated:f.investigated||void 0,learned:f.learned||void 0,completed:f.completed||void 0,nextSteps:f.next_steps||void 0}}}class ff{config;compressor;summarizer;pendingRepo;observationRepo;sessionRepo;summaryRepo;embeddingModel;conflictEvaluator;entityExtractor;entityRepo;observer;processing=!1;timer=null;mode="in-process";onEnqueue=null;constructor(f,B,K,E,J,z,$,R=null,N=null,W=null,Q=null,u=null){this.config=f;this.compressor=B;this.summarizer=K;this.pendingRepo=E;this.observationRepo=J;this.sessionRepo=z;this.summaryRepo=$;this.embeddingModel=R;this.conflictEvaluator=N;this.entityExtractor=W;this.entityRepo=Q;this.observer=u}setMode(f){if(this.mode=f,f==="enqueue-only")this.stop()}getMode(){return this.mode}setOnEnqueue(f){this.onEnqueue=f}enqueue(f,B,K,E){if(this.pendingRepo.create({sessionId:f,toolName:B,toolOutput:K,callId:E}),this.observer?.onEnqueue?.({sessionId:f,toolName:B,createdAt:new Date().toISOString()}),this.mode==="enqueue-only")this.onEnqueue?.()}async processBatch(){if(this.mode==="enqueue-only")return 0;if(this.processing)return 0;this.processing=!0;let f=0,B=0,K=Date.now();try{this.pendingRepo.resetStale(5);let E=this.pendingRepo.getPending(this.config.batchSize);if(this.observer?.onBatchStart?.({pending:E.length,mode:this.mode,startedAt:new Date(K).toISOString()}),E.length===0)return 0;for(let J of E)try{this.pendingRepo.markProcessing(J.id);let $=await this.compressor.compress(J.toolName,J.toolOutput)??this.compressor.createFallbackObservation(J.toolName,J.toolOutput),R=!1,N=null;if(this.embeddingModel)try{let Q=s({title:$.title,narrative:$.narrative,concepts:$.concepts}),u=await i(this.embeddingModel,Q);if(u){let Z=this.config.conflictResolutionEnabled&&this.conflictEvaluator,V=this.config.conflictSimilarityBandLow??0.7,k=this.config.conflictSimilarityBandHigh??0.92;if(Z){let X=this.observationRepo.findSimilar(u,$.type,V,5),_=X.find((F)=>F.similarity>k);if(_)console.log(`[open-mem] Dedup: skipping duplicate of ${_.id} (similarity: ${_.similarity.toFixed(3)})`),R=!0;else{let F=X.filter((S)=>S.similarity>=V&&S.similarity<=k);if(F.length>0)try{let S=F.map((U)=>{let G=this.observationRepo.getById(U.id);return G?{id:G.id,title:G.title,narrative:G.narrative,concepts:G.concepts,type:G.type}:null}).filter((U)=>U!==null);if(S.length>0&&this.conflictEvaluator){let U=await this.conflictEvaluator.evaluate({title:$.title,narrative:$.narrative,concepts:$.concepts,type:$.type},S);if(U&&U.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${U.reason})`),R=!0;else if(U&&U.outcome==="update"&&U.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${U.supersedesId} (${U.reason})`),N=U.supersedesId}}catch{}}}else{let X=this.observationRepo.findSimilar(u,$.type,0.92,1);if(X.length>0)console.log(`[open-mem] Dedup: skipping duplicate of ${X[0].id} (similarity: ${X[0].similarity.toFixed(3)})`),R=!0}}}catch{}if(R){this.pendingRepo.markCompleted(J.id);continue}let W=this.observationRepo.create({sessionId:J.sessionId,type:$.type,title:$.title,subtitle:$.subtitle,facts:$.facts,narrative:$.narrative,concepts:$.concepts,filesRead:$.filesRead,filesModified:$.filesModified,rawToolOutput:J.toolOutput,toolName:J.toolName,tokenCount:m(`${$.title} ${$.narrative} ${$.facts.join(" ")}`),discoveryTokens:$.discoveryTokens??m(J.toolOutput),importance:$.importance??3});if(this.embeddingModel)try{let Q=s({title:W.title,narrative:W.narrative,concepts:W.concepts}),u=await i(this.embeddingModel,Q);if(u)this.observationRepo.setEmbedding(W.id,u)}catch{}if(N)try{this.observationRepo.supersede(N,W.id),console.log(`[open-mem] Superseded observation ${N} with ${W.id}`)}catch(Q){console.error(`[open-mem] Failed to supersede ${N}:`,Q)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let Q=await this.entityExtractor.extract({title:W.title,narrative:W.narrative,concepts:W.concepts,facts:W.facts,filesRead:W.filesRead,filesModified:W.filesModified,type:W.type});if(Q){let u=new Map;for(let Z of Q.entities){let V=this.entityRepo.upsertEntity(Z.name,Z.entityType);u.set(Z.name,V.id),this.entityRepo.linkObservation(V.id,W.id)}for(let Z of Q.relations){let V=u.get(Z.sourceName),k=u.get(Z.targetName);if(V&&k)this.entityRepo.createRelation(V,k,Z.relationship,W.id)}}}catch{}this.sessionRepo.incrementObservationCount(J.sessionId),this.pendingRepo.markCompleted(J.id),f++}catch(z){this.pendingRepo.markFailed(J.id,String(z)),B++,this.observer?.onItemFailed?.({pendingId:J.id,error:String(z),failedAt:new Date().toISOString()})}return f}finally{this.observer?.onBatchEnd?.({processed:f,failed:B,durationMs:Date.now()-K,finishedAt:new Date().toISOString()}),this.processing=!1}}async summarizeSession(f){let B=this.observationRepo.getBySession(f);if(!this.summarizer.shouldSummarize(B.length))return;if(this.summaryRepo.getBySessionId(f))return;let E=await this.summarizer.summarize(f,B);if(!E)return;let J=this.summaryRepo.create({sessionId:f,summary:E.summary,keyDecisions:E.keyDecisions,filesModified:E.filesModified,concepts:E.concepts,tokenCount:m(E.summary)});this.sessionRepo.setSummary(f,J.id)}start(){if(this.mode==="enqueue-only")return;if(this.timer)return;this.timer=setInterval(async()=>{try{await this.processBatch()}catch{}},this.config.batchIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get isProcessing(){return this.processing}getStats(){return{pending:this.pendingRepo.getPending(1000).length,processing:this.processing}}}import{spawnSync as wf}from"child_process";import{dirname as c0,resolve as lf}from"path";function b0(f){try{let B=wf("git",["rev-parse","--git-common-dir"],{cwd:f,encoding:"utf-8",timeout:5000});if(B.status!==0||!B.stdout)return null;let K=B.stdout.trim();if(K===".git")return null;let E=wf("git",["rev-parse","--git-dir"],{cwd:f,encoding:"utf-8",timeout:5000});if(E.status!==0||!E.stdout)return null;let J=E.stdout.trim(),z=lf(f,K),$=lf(f,J);if(z===$)return null;let R=c0(z);if(R===z||R==="/")return null;return R}catch{return null}}function vf(f){return b0(f)??f}function Bf(f){process.stdout.write(`${JSON.stringify(f)}
551
+ `)}function r0(){let{values:f}=d0({options:{project:{type:"string",short:"p"},"http-port":{type:"string"}},strict:!1}),B=typeof f.project==="string"?f.project:process.cwd(),K=f["http-port"],E=typeof K==="string"&&Number.parseInt(K,10)>0?Number.parseInt(K,10):void 0;return{projectDir:B,httpPort:E}}function i0(f,B){if(f==="claude-code"&&!B.platformClaudeCodeEnabled)throw Error("Claude Code adapter is disabled. Set OPEN_MEM_PLATFORM_CLAUDE_CODE=true.");if(f==="cursor"&&!B.platformCursorEnabled)throw Error("Cursor adapter is disabled. Set OPEN_MEM_PLATFORM_CURSOR=true.")}function s0(f,B){let K=vf(B),E=jf(K);i0(f,E),x.enableExtensionSupport();let J=gf(E.dbPath);If(J,{hasVectorExtension:J.hasVectorExtension,embeddingDimension:E.embeddingDimension});let z=new e(J),$=new o(J),R=new a(J),N=new t(J),W=new P(E),Q=new n(E),u=E.provider!=="bedrock",Z=E.compressionEnabled&&(!u||E.apiKey)?yf({provider:E.provider,model:E.model,apiKey:E.apiKey}):null,V=E.conflictResolutionEnabled&&(!u||E.apiKey)?new c({provider:E.provider,apiKey:E.apiKey,model:E.model,rateLimitingEnabled:E.rateLimitingEnabled}):null,k=E.entityExtractionEnabled&&(!u||E.apiKey)?new b({provider:E.provider,apiKey:E.apiKey,model:E.model,rateLimitingEnabled:E.rateLimitingEnabled}):null,X=new r(J),_=new ff(E,W,Q,N,$,z,R,Z,V,k,X),F=f==="claude-code"?$f():Rf(),S=new v({adapter:F,queue:_,sessions:z,observations:$,pendingMessages:N,projectPath:K,config:E});return{db:J,queue:_,runtime:S,platform:f,projectPath:K}}function cf(f,B){let K=f.queue.getStats();return{id:B,ok:!0,code:"OK",status:{platform:f.platform,projectPath:f.projectPath,queue:{mode:f.queue.getMode(),running:f.queue.isRunning,processing:K.processing,pending:K.pending}}}}function Kf(f){if(!f||typeof f!=="object"||Array.isArray(f))return{command:"event",payload:f};let B=f,K=typeof B.command==="string"&&(B.command==="event"||B.command==="flush"||B.command==="health"||B.command==="shutdown")?B.command:void 0,E=typeof B.id==="string"||typeof B.id==="number"?B.id:void 0;if(!K)return{command:"event",payload:f,id:E};return{id:E,command:K,payload:"payload"in B?B.payload:void 0}}async function bf(f){let B=r0(),K=s0(f,B.projectDir);K.queue.start();let E=!1,J=async()=>{if(E)return;E=!0;try{await K.queue.processBatch()}catch{}K.queue.stop(),K.db.close(),process.exit(0)},z=async(N)=>{let W=N.command??"event";if(W==="health")return cf(K,N.id);if(W==="flush"){let u=await K.queue.processBatch();return{id:N.id,ok:!0,code:"OK",processed:u}}if(W==="shutdown")return{id:N.id,ok:!0,code:"OK",message:"shutting down"};if(!await K.runtime.ingestRaw(N.payload))return{id:N.id,ok:!1,code:"UNSUPPORTED_EVENT",message:"Payload did not match adapter event schema"};return{id:N.id,ok:!0,code:"OK",ingested:!0}};if(B.httpPort)Bun.serve({port:B.httpPort,hostname:"127.0.0.1",idleTimeout:0,fetch:async(N)=>{if(N.method==="GET"&&new URL(N.url).pathname==="/v1/health")return Response.json(cf(K));if(N.method==="POST"&&new URL(N.url).pathname==="/v1/events"){let W;try{W=await N.json()}catch{return Response.json({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"},{status:400})}try{let Q=await z(Kf(W));if((Kf(W).command??"event")==="shutdown")setTimeout(()=>{J()},0);return Response.json(Q,{status:Q.ok?200:422})}catch(Q){return Response.json({ok:!1,code:"INGESTION_FAILED",message:String(Q)},{status:500})}}return Response.json({ok:!1,code:"NOT_FOUND"},{status:404})}});process.on("SIGINT",()=>{J()}),process.on("SIGTERM",()=>{J()});let $=Promise.resolve(),R=n0({input:process.stdin,terminal:!1});R.on("line",(N)=>{let W=N.trim();if(!W)return;$=$.then(async()=>{let Q;try{Q=JSON.parse(W)}catch{Bf({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"});return}try{let u=Kf(Q),Z=await z(u);if(Bf(Z),(u.command??"event")==="shutdown")await J()}catch(u){Bf({ok:!1,code:"INGESTION_FAILED",message:String(u)})}})}),R.on("close",()=>{$.finally(()=>J())})}bf("claude-code");