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