open-mem 0.14.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +58 -1
- package/dist/claude-code.js +88 -87
- package/dist/cursor.js +88 -87
- package/dist/daemon/manager.d.ts +33 -5
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/pid.d.ts +23 -0
- package/dist/daemon/pid.d.ts.map +1 -1
- package/dist/daemon.js +35 -34
- package/dist/db/advisory-lock.d.ts +40 -0
- package/dist/db/advisory-lock.d.ts.map +1 -0
- package/dist/db/database.d.ts +37 -4
- package/dist/db/database.d.ts.map +1 -1
- package/dist/doctor.js +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +99 -98
- package/dist/maintenance.js +48 -45
- package/dist/mcp.js +72 -71
- package/dist/platform-worker.d.ts.map +1 -1
- package/dist/runtime/queue-runtime.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/cursor.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
4
|
-
`);await
|
|
5
|
-
`)}async function
|
|
6
|
-
${
|
|
7
|
-
${
|
|
8
|
-
`;let
|
|
9
|
-
${
|
|
10
|
-
${
|
|
11
|
-
|
|
12
|
-
${
|
|
13
|
-
${
|
|
14
|
-
${
|
|
15
|
-
`}function
|
|
3
|
+
var E=import.meta.require;import{createInterface as jJ}from"readline";import{parseArgs as qJ}from"util";var h1=new Set(["127.0.0.1","::1","localhost"]);function g1($){return $.trim().toLowerCase()}function m1($){return h1.has(g1($))}function T$($,J){if(m1($))return;throw Error(`[open-mem] ${J} must bind to loopback only (127.0.0.1, ::1, localhost). Received "${$}".`)}var j$={name:"claude-code",version:"0.1",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}},q$={name:"cursor",version:"0.1",capabilities:{nativeSessionLifecycle:!1,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}};function $$(){return new Date().toISOString()}function l($){if(!$||typeof $!=="object"||Array.isArray($))return null;return $}function C($){return typeof $==="string"&&$.trim().length>0?$:null}function d($,J){let V=l(J);if(!V)return null;let Z=C(V.kind),X=C(V.sessionId);if(!Z||!X)return null;if(Z==="session.start"||Z==="session.end"||Z==="idle.flush")return{kind:Z,platform:$,sessionId:X,occurredAt:C(V.occurredAt)??$$(),metadata:l(V.metadata)??void 0};if(Z==="chat.message"){let H=C(V.text);if(!H)return null;let K=C(V.role);return{kind:Z,platform:$,sessionId:X,text:H,role:K==="assistant"||K==="system"?K:"user",occurredAt:C(V.occurredAt)??$$(),metadata:l(V.metadata)??void 0}}if(Z==="tool.execute"){let H=C(V.toolName),K=C(V.output);if(!H||!K)return null;return{kind:Z,platform:$,sessionId:X,callId:C(V.callId)??`${$}-${Date.now()}`,toolName:H,output:K,occurredAt:C(V.occurredAt)??$$(),metadata:l(V.metadata)??void 0}}return null}function b1($){let J=$.type??$.event;if(!J)return null;if(J==="session.start")return"session.start";if(J==="session.end")return"session.end";if(J==="idle.flush")return"idle.flush";if(J==="tool.execute")return"tool.execute";if(J==="chat.message")return"chat.message";return null}class x${descriptor=j$;normalize($){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,V=b1(J);if(!V||!J.sessionId)return null;return d("claude-code",{kind:V,sessionId:J.sessionId,callId:J.callId,toolName:J.toolName,output:J.output,role:J.role,text:J.text,occurredAt:J.occurredAt,metadata:J.metadata})}}function f$(){return new x$}function p1($){let J=$.eventName??$.event;if(!J)return null;if(J==="sessionStart")return"session.start";if(J==="sessionEnd")return"session.end";if(J==="idleFlush")return"idle.flush";if(J==="toolExecute")return"tool.execute";if(J==="chatMessage")return"chat.message";return null}class I${descriptor=q$;normalize($){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,V=p1(J),Z=J.sessionId??J.session;if(!V||!Z)return null;return d("cursor",{kind:V,sessionId:Z,callId:J.callId??J.invocationId,toolName:J.toolName??J.tool,output:J.output,role:J.role,text:J.text??J.message,occurredAt:J.occurredAt??J.timestamp,metadata:J.metadata??J.meta})}}function u$(){return new I$}function n($,J=""){if(!$)return $;return $.replace(/<private>[\s\S]*?<\/private>/gi,J)}var w$=200,c1=/(\([\s\S]*[+*]\)\s*[+*?])|(\(\.\*\)\+)|(\(\.\+\)\+)/;function i($,J,V="[REDACTED]"){if(!$||J.length===0)return $;let Z=$;for(let X of J){if(X.length>w$){console.warn(`[open-mem] Skipping oversized redaction pattern (${X.length} chars, max ${w$})`);continue}if(c1.test(X)){console.warn("[open-mem] Skipping potentially dangerous redaction pattern (nested quantifiers detected)");continue}try{Z=Z.replace(new RegExp(X,"g"),V)}catch{}}return Z}var l1=20,P$=2000,v$=60;function d1($){let J=$.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter((V)=>V.length>4);return[...new Set(J)].slice(0,5)}function h$($){let{observations:J,sessions:V,projectPath:Z,sessionId:X,text:H,agent:K,sensitivePatterns:z=[]}=$;if(K!==void 0&&K!=="user")return!1;let B=i(n(H),z);if(B.length<l1)return!1;V.getOrCreate(X,Z);let Q=`User request: ${B.length>v$?`${B.slice(0,v$)}...`:B}`,U=B.length>P$?`${B.slice(0,P$)}...`:B;return J.create({sessionId:X,type:"discovery",title:Q,subtitle:"",facts:[],narrative:U,concepts:d1(B),filesRead:[],filesModified:[],rawToolOutput:"",toolName:"chat.message",tokenCount:Math.ceil(U.length/4),discoveryTokens:0,importance:3}),!0}import{existsSync as V0}from"fs";import{readFile as Z0,writeFile as X0}from"fs/promises";import{join as H0}from"path";import{existsSync as m$}from"fs";import{mkdir as n1,readFile as i1,rename as r1,unlink as s1,writeFile as o1}from"fs/promises";import{dirname as r,isAbsolute as Z$,join as h,normalize as t1,relative as X$,resolve as w,sep as J$}from"path";var u="<!-- open-mem-context -->",q="<!-- /open-mem-context -->",b$={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},g$=new Map,a1=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function p$($,J,V){if(J.length===0)return;if(V.mode==="single")return e1($,J,V);let{maxDepth:Z,filename:X}=V,H=[];for(let B of J){for(let Y of B.filesModified)H.push(Y);for(let Y of B.filesRead)H.push(Y)}let K=l$(H,$,Z);if(K.size===0)return;let z=d$(J,K,$);for(let[B,Y]of z)try{let Q=$0(B,Y,$);await c$(B,Q,X)}catch(Q){console.error(`[open-mem] Failed to update AGENTS.md in ${B}:`,Q)}}async function e1($,J,V){let{maxDepth:Z,filename:X}=V,H=J.filter(V$);if(H.length===0)return;let K=[];for(let W of H){for(let M of W.filesModified)K.push(M);for(let M of W.filesRead)K.push(M)}let z=l$(K,$,Z),B=d$(H,z,$),Y=H.filter((W)=>{return[...W.filesModified,...W.filesRead].some((D)=>{if(!D)return!1;let L=Z$(D)?D:h($,D);return w(r(L))===w($)})});if(Y.length>0)B.set(w($),Y);if(B.size===0)return;let Q=[];Q.push("## Project Activity (auto-generated by open-mem)"),Q.push("");let U=[...B.entries()].map(([W,M])=>({relPath:X$($,W)||".",observations:M})).sort((W,M)=>W.relPath.localeCompare(M.relPath));for(let{relPath:W,observations:M}of U){let D=M.filter(V$).sort((G,F)=>F.createdAt.localeCompare(G.createdAt)).slice(0,10);if(D.length===0)continue;Q.push(`### ${W}/`),Q.push("| ID | Type | Title | Date |"),Q.push("|----|------|-------|------|");for(let G of D){let F=b$[G.type]||"\uD83D\uDCDD",R=G.createdAt.split("T")[0],e=G.title.replace(/\|/g,"\\|");Q.push(`| ${G.id} | ${F} ${G.type} | ${e} | ${R} |`)}let L=new Set;for(let G of D)for(let F of G.concepts)L.add(F);if(L.size>0){let G=[...L].slice(0,10).join(", ");Q.push(""),Q.push(`**Key concepts:** ${G}`)}let _=D.filter((G)=>G.type==="decision").map((G)=>G.title);if(_.length>0)Q.push(""),Q.push(`**Recent decisions:** ${_.slice(0,5).join("; ")}`);Q.push("")}Q.push("\uD83D\uDCA1 *Use `mem-find` to search full details. Use `mem-create` to save important decisions.*");let A=Q.join(`
|
|
4
|
+
`);await c$($,A,X)}function V$($){return!/^\w[\w-]*\s+execution$/i.test($.title)}function $0($,J,V){let Z=[...J].filter(V$).sort((Y,Q)=>Q.createdAt.localeCompare(Y.createdAt)).slice(0,10),X=X$(V,$)||".",H=[];H.push(`## Recent Activity in \`${X}/\` (auto-generated by open-mem)`),H.push(""),H.push("| ID | Type | Title | Date |"),H.push("|----|------|-------|------|");for(let Y of Z){let Q=b$[Y.type]||"\uD83D\uDCDD",U=Y.createdAt.split("T")[0],A=Y.title.replace(/\|/g,"\\|");H.push(`| ${Y.id} | ${Q} ${Y.type} | ${A} | ${U} |`)}let K=new Set;for(let Y of Z)for(let Q of Y.concepts)K.add(Q);if(K.size>0){let Y=[...K].slice(0,10).join(", ");H.push(""),H.push(`**Key concepts:** ${Y}`)}let z=Z.filter((Y)=>Y.type==="decision").map((Y)=>Y.title);if(z.length>0)H.push(""),H.push(`**Recent decisions:** ${z.slice(0,5).join("; ")}`);let B=Z.filter((Y)=>Y.type==="decision"&&Y.narrative).slice(0,3);if(B.length>0){H.push(""),H.push("**Decision details:**");for(let Y of B){let Q=Y.narrative.split(/[.!?]\s/)[0],U=Q.length>120?`${Q.slice(0,117)}...`:Q;H.push(`- \u2696\uFE0F ${Y.title}: ${U}`)}}return H.push(""),H.push("\uD83D\uDCA1 *Use `mem-find` to search full details across all sessions. Use `mem-create` to save important decisions.*"),H.join(`
|
|
5
|
+
`)}async function c$($,J,V){if(!m$($))return;let X=(g$.get($)??Promise.resolve()).then(async()=>{let H=h($,V),K=h($,`.${V}.tmp`),z="";try{z=await i1(H,"utf-8")}catch{}let B=J0(z,J);try{await n1(r(K),{recursive:!0}),await o1(K,B,"utf-8"),await r1(K,H)}catch(Y){try{await s1(K)}catch{}throw Y}});return g$.set($,X.catch(()=>{})),X}function J0($,J){if(!$)return`${u}
|
|
6
|
+
${J}
|
|
7
|
+
${q}
|
|
8
|
+
`;let V=$.indexOf(u),Z=$.indexOf(q);if(V!==-1&&Z!==-1&&Z>V){let H=$.substring(0,V),K=$.substring(Z+q.length);return`${H}${u}
|
|
9
|
+
${J}
|
|
10
|
+
${q}${K}`}let X=$;if(V!==-1&&Z===-1)X=X.replace(u,"").trim();else if(V===-1&&Z!==-1)X=X.replace(q,"").trim();else if(V!==-1&&Z!==-1&&Z<=V)X=X.replace(q,"").replace(u,"").trim();return`${X}
|
|
11
|
+
|
|
12
|
+
${u}
|
|
13
|
+
${J}
|
|
14
|
+
${q}
|
|
15
|
+
`}function l$($,J,V){let Z=new Set,X=w(J);for(let H of $){if(!H||!H.trim())continue;if(H.startsWith("~")||H.startsWith("http"))continue;let K=Z$(H)?H:h(J,H),z=r(K),B=w(z);if(!B.startsWith(X+J$)&&B!==X)continue;if(B===X)continue;let Y=X$(X,B);if(Y.split(J$).length>V)continue;if(t1(Y).split(J$).some((A)=>a1.has(A)))continue;if(!m$(B))continue;Z.add(B)}return Z}function d$($,J,V){let Z=new Map;for(let X of $){let H=[...X.filesModified,...X.filesRead],K=new Set;for(let z of H){if(!z)continue;let B=Z$(z)?z:h(V,z),Y=w(r(B));if(J.has(Y))K.add(Y)}for(let z of K){let B=Z.get(z)??[];B.push(X),Z.set(z,B)}}return Z}function n$($,J,V){if($.retentionDays===0)return;try{let Z=J.deleteOlderThan($.retentionDays),X=V.deleteCompletedOlderThan($.retentionDays);if(Z>0||X>0)console.log(`[open-mem] Retention: deleted ${Z} observations, ${X} pending messages`)}catch(Z){console.error("[open-mem] Retention enforcement error:",Z)}}async function s($,J,V){let{queue:Z,sessions:X,projectPath:H,config:K,observations:z,pendingMessages:B}=$;switch(J){case"session.created":{if(V)X.getOrCreate(V,H);try{n$(K,z,B)}catch(Y){console.error("[open-mem] Retention enforcement error:",Y)}try{await K0(H)}catch(Y){console.error("[open-mem] Gitignore entry error:",Y)}break}case"session.idle":{if(Z.processBatch().catch((Y)=>{console.error("[open-mem] Background processing error:",Y)}),V)X.updateStatus(V,"idle"),i$(V,H,K,z).catch((Y)=>{console.error("[open-mem] Folder context error:",Y)});break}case"session.completed":case"session.ended":{if(V)await Z.processBatch(),await Z.summarizeSession(V),X.markCompleted(V),await i$(V,H,K,z);break}}}async function i$($,J,V,Z){if(!V.folderContextEnabled)return;try{let X=Z.getBySession($);if(X.length>0)await p$(J,X,{mode:V.folderContextMode,filename:V.folderContextFilename,maxDepth:V.folderContextMaxDepth})}catch(X){console.error("[open-mem] Folder context update error:",X)}}async function K0($){let J=H0($,".gitignore");if(!V0(J))return;let V=await Z0(J,"utf-8");if(V.includes("AGENTS.md"))return;let Z=`
|
|
16
16
|
# open-mem: Auto-generated folder context files.
|
|
17
17
|
# Uncomment to exclude from version control (recommended for large projects):
|
|
18
18
|
# **/AGENTS.md
|
|
19
|
-
`;await
|
|
20
|
-
`)?
|
|
21
|
-
${
|
|
22
|
-
${
|
|
19
|
+
`;await X0(J,V.endsWith(`
|
|
20
|
+
`)?V+Z:`${V}
|
|
21
|
+
${Z}`,"utf-8")}function r$($){let{config:J,queue:V,sessions:Z,projectPath:X,tool:H,sessionId:K,callId:z,toolOutput:B}=$;if(J.ignoredTools.includes(H))return!1;if(!B||B.length<J.minOutputLength)return!1;let Y=i(B,J.sensitivePatterns);return Y=n(Y,"[PRIVATE]"),Z.getOrCreate(K,X),V.enqueue(K,H,Y,z),!0}class H${adapter;lifecycleDeps;queue;sessions;observations;projectPath;config;constructor($){this.adapter=$.adapter,this.queue=$.queue,this.sessions=$.sessions,this.observations=$.observations,this.projectPath=$.projectPath,this.config=$.config,this.lifecycleDeps={queue:$.queue,sessions:$.sessions,projectPath:$.projectPath,config:$.config,observations:$.observations,pendingMessages:$.pendingMessages}}platform(){return this.adapter.descriptor.name}normalize($){return this.adapter.normalize($)}async ingestRaw($){let J=this.normalize($);if(!J)return!1;return await this.ingestNormalized(J),!0}async ingestNormalized($){switch($.kind){case"session.start":await s(this.lifecycleDeps,"session.created",$.sessionId);return;case"session.end":await s(this.lifecycleDeps,"session.ended",$.sessionId);return;case"idle.flush":await s(this.lifecycleDeps,"session.idle",$.sessionId);return;case"tool.execute":r$({config:this.config,queue:this.queue,sessions:this.sessions,projectPath:this.projectPath,tool:$.toolName,sessionId:$.sessionId,callId:$.callId,toolOutput:$.output});return;case"chat.message":h$({observations:this.observations,sessions:this.sessions,projectPath:this.projectPath,sessionId:$.sessionId,text:$.text,agent:$.role==="user"?"user":$.role,sensitivePatterns:this.config.sensitivePatterns});return}}}import{generateText as F0}from"ai";function S($){if(typeof $!=="object"||$===null)return!1;let J=$,V=J.status;if(V===429||V===500||V===503)return!0;let Z=J.error;if(typeof Z==="object"&&Z!==null&&Z.type==="overloaded_error")return!0;return!1}function g($){if($&&typeof $==="object"){let J=$.status;if(typeof J==="number")return J===400||J===401||J===403}return!1}function x($){return new Promise((J)=>setTimeout(J,$))}var Y0=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function N($,J){let V=new RegExp(`<${J}[^>]*>([\\s\\S]*?)</${J}>`,"i"),Z=$.match(V);return Z?Z[1].trim():""}function O($,J){let V=new RegExp(`<${J}[^>]*>([\\s\\S]*?)</${J}>`,"gi"),Z=[];for(let X of $.matchAll(V)){let H=X[1].trim();if(H)Z.push(H)}return Z}function s$($){let J=N($,"observation");if(!J)return null;let V=N(J,"type").toLowerCase(),Z=Y0.has(V)?V:"discovery",X=N(J,"title")||"Untitled observation",H=N(J,"subtitle"),K=N(J,"narrative"),z=O(N(J,"facts"),"fact"),B=O(N(J,"concepts"),"concept"),Y=O(N(J,"files_read"),"file"),Q=O(N(J,"files_modified"),"file"),U=N(J,"importance"),A=Number.parseInt(U,10),W=Number.isNaN(A)?3:Math.max(1,Math.min(5,A));return{type:Z,title:X,subtitle:H,facts:z,narrative:K,concepts:B,filesRead:Y,filesModified:Q,importance:W}}function o$($){let J=N($,"session_summary");if(!J)return null;let V=N(J,"summary")||"No summary available",Z=O(N(J,"key_decisions"),"decision"),X=O(N(J,"files_modified"),"file"),H=O(N(J,"concepts"),"concept"),K=N(J,"request")||void 0,z=N(J,"investigated")||void 0,B=N(J,"learned")||void 0,Y=N(J,"completed")||void 0,Q=N(J,"next_steps")||void 0;return{summary:V,keyDecisions:Z,filesModified:X,concepts:H,request:K,investigated:z,learned:B,completed:Y,nextSteps:Q}}var z0=new Set(["new_fact","update","duplicate"]);function t$($){let J=N($,"evaluation");if(!J)return null;let V=N(J,"outcome").toLowerCase().trim();if(!z0.has(V))return null;let Z=V,X=N(J,"reason");if(!X)return null;let H=N(J,"supersedes"),K={outcome:Z,reason:X};if(Z==="update"&&H)K.supersedesId=H;if(Z==="update"&&!K.supersedesId)return null;return K}var B0=new Set(["technology","library","pattern","concept","file","person","project","other"]),Q0=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function a$($){let J=N($,"extraction");if(!J)return null;let V=N(J,"entities"),Z=N(J,"relations"),X=O(V,"entity"),H=[];for(let B of X){let Y=N(B,"name");if(!Y)continue;let Q=N(B,"type").toLowerCase(),U=B0.has(Q)?Q:"other";H.push({name:Y,entityType:U})}let K=O(Z,"relation"),z=[];for(let B of K){let Y=N(B,"source"),Q=N(B,"target"),U=N(B,"relationship").toLowerCase();if(!Y||!Q||!U)continue;if(!Q0.has(U))continue;z.push({sourceName:Y,targetName:Q,relationship:U})}return{entities:H,relations:z}}function f($){return Math.ceil($.length/4)}function e$($,J,V,Z){let X=V?`<session_context>
|
|
22
|
+
${V}
|
|
23
23
|
</session_context>
|
|
24
24
|
|
|
25
|
-
`:"",
|
|
25
|
+
`:"",H=Z?Z.observationTypes.join("|"):"decision|bugfix|feature|refactor|discovery|change",z=(Z?Z.conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"]).map((B)=>{let Q={"how-it-works":"Technical mechanisms and behaviors","why-it-exists":"Rationale and motivations","what-changed":"Modifications and their effects","problem-solution":"Issues encountered and how they were resolved",gotcha:"Surprising behaviors, edge cases, or pitfalls",pattern:"Recurring design patterns or approaches","trade-off":"Deliberate compromises between competing concerns",hypothesis:"Proposed explanations or predictions",finding:"Key results or discoveries",methodology:"Research methods and approaches",evidence:"Supporting data or observations",limitation:"Known constraints or boundaries",implication:"Consequences or downstream effects",comparison:"Similarities and differences between approaches"}[B];return Q?`- ${B}: ${Q}`:`- ${B}`}).join(`
|
|
26
26
|
`);return`<task>
|
|
27
27
|
Analyze the following tool output and extract a structured observation.
|
|
28
28
|
</task>
|
|
29
29
|
|
|
30
|
-
<tool_name>${
|
|
30
|
+
<tool_name>${$}</tool_name>
|
|
31
31
|
|
|
32
32
|
<tool_output>
|
|
33
|
-
${
|
|
33
|
+
${J}
|
|
34
34
|
</tool_output>
|
|
35
35
|
|
|
36
|
-
${
|
|
36
|
+
${X}<instructions>
|
|
37
37
|
Extract a structured observation from the tool output. Determine the most appropriate type and provide a concise but informative summary.
|
|
38
38
|
|
|
39
39
|
When extracting concepts, prefer established vocabulary where appropriate:
|
|
40
|
-
${
|
|
40
|
+
${z}
|
|
41
41
|
You may also use any domain-specific concepts relevant to the observation.
|
|
42
42
|
|
|
43
43
|
Respond with EXACTLY this XML format:
|
|
44
44
|
<observation>
|
|
45
|
-
<type>${
|
|
45
|
+
<type>${H}</type>
|
|
46
46
|
<title>Brief descriptive title (max 80 chars)</title>
|
|
47
47
|
<subtitle>One-line elaboration</subtitle>
|
|
48
48
|
<importance>1-5 (1=trivial/routine, 2=low, 3=normal, 4=significant, 5=critical decision or discovery)</importance>
|
|
@@ -62,18 +62,18 @@ Respond with EXACTLY this XML format:
|
|
|
62
62
|
<file>path/to/file/modified</file>
|
|
63
63
|
</files_modified>
|
|
64
64
|
</observation>
|
|
65
|
-
</instructions>`}function
|
|
66
|
-
<title>${
|
|
67
|
-
<narrative>${
|
|
65
|
+
</instructions>`}function $1($,J){let V=$.map((Z,X)=>` <obs index="${X+1}" type="${Z.type}">
|
|
66
|
+
<title>${Z.title}</title>
|
|
67
|
+
<narrative>${Z.narrative}</narrative>
|
|
68
68
|
</obs>`).join(`
|
|
69
69
|
`);return`<task>
|
|
70
70
|
Summarize the following coding session based on its observations.
|
|
71
71
|
</task>
|
|
72
72
|
|
|
73
|
-
<session_id>${
|
|
73
|
+
<session_id>${J}</session_id>
|
|
74
74
|
|
|
75
75
|
<observations>
|
|
76
|
-
${
|
|
76
|
+
${V}
|
|
77
77
|
</observations>
|
|
78
78
|
|
|
79
79
|
<instructions>
|
|
@@ -97,21 +97,21 @@ Respond with EXACTLY this XML format:
|
|
|
97
97
|
<concept>key-concept</concept>
|
|
98
98
|
</concepts>
|
|
99
99
|
</session_summary>
|
|
100
|
-
</instructions>`}function
|
|
101
|
-
<title>${
|
|
102
|
-
<narrative>${
|
|
103
|
-
<concepts>${
|
|
104
|
-
<type>${
|
|
100
|
+
</instructions>`}function J1($,J){let V=J.map((Z)=>` <candidate id="${Z.id}">
|
|
101
|
+
<title>${Z.title}</title>
|
|
102
|
+
<narrative>${Z.narrative}</narrative>
|
|
103
|
+
<concepts>${Z.concepts.join(", ")}</concepts>
|
|
104
|
+
<type>${Z.type}</type>
|
|
105
105
|
</candidate>`).join(`
|
|
106
106
|
`);return`<conflict_evaluation>
|
|
107
107
|
<new_observation>
|
|
108
|
-
<title>${
|
|
109
|
-
<narrative>${
|
|
110
|
-
<concepts>${
|
|
111
|
-
<type>${
|
|
108
|
+
<title>${$.title}</title>
|
|
109
|
+
<narrative>${$.narrative}</narrative>
|
|
110
|
+
<concepts>${$.concepts.join(", ")}</concepts>
|
|
111
|
+
<type>${$.type}</type>
|
|
112
112
|
</new_observation>
|
|
113
113
|
<existing_candidates>
|
|
114
|
-
${
|
|
114
|
+
${V}
|
|
115
115
|
</existing_candidates>
|
|
116
116
|
<instructions>
|
|
117
117
|
Evaluate whether the new observation represents:
|
|
@@ -126,22 +126,22 @@ Respond with EXACTLY this XML format:
|
|
|
126
126
|
<reason>Brief explanation</reason>
|
|
127
127
|
</evaluation>
|
|
128
128
|
</instructions>
|
|
129
|
-
</conflict_evaluation>`}function
|
|
129
|
+
</conflict_evaluation>`}function V1($,J){let V=[...$.filesRead,...$.filesModified],Z=J?J.entityTypes.join(", "):"technology, library, pattern, concept, file, person, project, other",X=J?J.relationshipTypes.join(", "):"uses, depends_on, implements, extends, related_to, replaces, configures";return`<entity_extraction>
|
|
130
130
|
<observation>
|
|
131
|
-
<title>${
|
|
132
|
-
<type>${
|
|
133
|
-
<narrative>${
|
|
134
|
-
<facts>${
|
|
131
|
+
<title>${$.title}</title>
|
|
132
|
+
<type>${$.type}</type>
|
|
133
|
+
<narrative>${$.narrative}</narrative>
|
|
134
|
+
<facts>${$.facts.join(`
|
|
135
135
|
`)}</facts>
|
|
136
|
-
<files>${
|
|
136
|
+
<files>${V.join(`
|
|
137
137
|
`)}</files>
|
|
138
|
-
<concepts>${
|
|
138
|
+
<concepts>${$.concepts.join(", ")}</concepts>
|
|
139
139
|
</observation>
|
|
140
140
|
<instructions>
|
|
141
141
|
Extract entities and relationships from this observation.
|
|
142
142
|
|
|
143
|
-
Entity types: ${
|
|
144
|
-
Relationship types: ${
|
|
143
|
+
Entity types: ${Z}
|
|
144
|
+
Relationship types: ${X}
|
|
145
145
|
|
|
146
146
|
Extract entities that are clearly mentioned or strongly implied. For example, "React hooks" implies a relationship between React and hooks. Do not extract speculative relationships.
|
|
147
147
|
Respond with EXACTLY this XML format:
|
|
@@ -155,102 +155,103 @@ Respond with EXACTLY this XML format:
|
|
|
155
155
|
</relations>
|
|
156
156
|
</extraction>
|
|
157
157
|
</instructions>
|
|
158
|
-
</entity_extraction>`}class
|
|
158
|
+
</entity_extraction>`}class K${shouldFailover($){let{error:J,attemptIndex:V,totalProviders:Z}=$;if(g(J))return!1;if(V>=Z-1)return!1;return S(J)}onFailover($){let J=$.error?.status??"unknown";if(!$.nextProvider)return;console.error(`[open-mem] Provider ${$.provider} failed (${J}), falling over to ${$.nextProvider}`)}}class Y${specificationVersion;provider;modelId;supportedUrls;providers;policy;constructor($,J=new K$){if($.length===0)throw Error("At least one provider required");let V=$[0].model;this.specificationVersion=V.specificationVersion,this.provider=V.provider,this.modelId=V.modelId,this.supportedUrls=V.supportedUrls,this.providers=$,this.policy=J}async doGenerate($){let J;for(let V=0;V<this.providers.length;V++){let Z=this.providers[V];try{return this.policy.onAttempt?.({error:null,provider:Z.name,nextProvider:this.providers[V+1]?.name,attemptIndex:V,totalProviders:this.providers.length}),await Z.model.doGenerate($)}catch(X){if(J=X,g(X))throw X;let H=this.providers[V+1]?.name,K={error:X,provider:Z.name,nextProvider:H,attemptIndex:V,totalProviders:this.providers.length};if(this.policy.shouldFailover(K)){this.policy.onFailover(K);continue}throw this.policy.onFinalFailure?.(K),X}}throw J}async doStream($){let J;for(let V=0;V<this.providers.length;V++){let Z=this.providers[V];try{return this.policy.onAttempt?.({error:null,provider:Z.name,nextProvider:this.providers[V+1]?.name,attemptIndex:V,totalProviders:this.providers.length}),await Z.model.doStream($)}catch(X){if(J=X,g(X))throw X;let H=this.providers[V+1]?.name,K={error:X,provider:Z.name,nextProvider:H,attemptIndex:V,totalProviders:this.providers.length};if(this.policy.shouldFailover(K)){this.policy.onFailover(K);continue}throw this.policy.onFinalFailure?.(K),X}}throw J}}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 W0($){if($.includes("."))return $;return U0[$]||`us.anthropic.${$}-v1:0`}function Z1($){switch($.provider){case"anthropic":{let{createAnthropic:J}=E("@ai-sdk/anthropic");return J({apiKey:$.apiKey})($.model)}case"bedrock":{let{createAmazonBedrock:J}=E("@ai-sdk/amazon-bedrock");return J()(W0($.model))}case"openai":{let{createOpenAI:J}=E("@ai-sdk/openai");return J({apiKey:$.apiKey})($.model)}case"google":{let{createGoogleGenerativeAI:J}=E("@ai-sdk/google");return J({apiKey:$.apiKey})($.model)}case"openrouter":{let{createOpenRouter:J}=E("@openrouter/ai-sdk-provider");return J({apiKey:$.apiKey})($.model)}default:throw Error(`Unknown provider: ${$.provider}. Supported: anthropic, bedrock, openai, google, openrouter`)}}function X1($){try{switch($.provider){case"google":{let{createGoogleGenerativeAI:J}=E("@ai-sdk/google");return J({apiKey:$.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:J}=E("@ai-sdk/openai");return J({apiKey:$.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:J}=E("@ai-sdk/amazon-bedrock");return J().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;case"openrouter":return null;default:return null}}catch{return null}}var A0={google:"gemini-2.5-flash-lite",anthropic:"claude-sonnet-4-20250514",openai:"gpt-4o-mini",bedrock:"us.anthropic.claude-3-5-haiku-20241022-v1:0",openrouter:"google/gemini-2.5-flash-lite"};function N0($){switch($){case"google":return process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;case"anthropic":return process.env.ANTHROPIC_API_KEY;case"openai":return process.env.OPENAI_API_KEY;case"openrouter":return process.env.OPENROUTER_API_KEY;case"bedrock":return;default:return}}function k($){if(!$.fallbackProviders||$.fallbackProviders.length===0)return[];return $.fallbackProviders.map((J)=>({provider:J,model:A0[J]??"gemini-2.5-flash-lite",apiKey:N0(J)}))}function T($,J=[],V){let Z=Z1($);if(J.length===0)return Z;let X=[{name:$.provider,model:Z},...J.map((H)=>({name:H.provider,model:Z1(H)}))];return new Y$(X,V)}var G0={"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},H1=0;async function j($,J){if(!J)return;let V=G0[$]||5,Z=Math.ceil(60000/V)+100,H=Date.now()-H1;if(H<Z){let K=Z-H;await new Promise((z)=>setTimeout(z,K))}H1=Date.now()}class m{model;config;_generate=F0;constructor($){this.config=$,this.model=null;let J=$.provider!=="bedrock";if($.compressionEnabled&&(!J||$.apiKey))try{this.model=T({provider:$.provider,model:$.model,apiKey:$.apiKey},k($))}catch{}}static MAX_INPUT_LENGTH=50000;async compress($,J,V){if(!this.config.compressionEnabled||!this.model)return null;if(J.length<this.config.minOutputLength)return null;let Z=f(J),X=J.length>m.MAX_INPUT_LENGTH?`${J.substring(0,m.MAX_INPUT_LENGTH)}
|
|
159
159
|
|
|
160
|
-
[... truncated ...]`:y,J=nu(u,A,B),K=2;for(let V=0;V<=K;V++)try{if(this.config.provider==="google")await F(this.config.model,this.config.rateLimitingEnabled);let{text:R}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:J}),z=hu(R);if(z)z.discoveryTokens=$;return z}catch(R){if(m(R)&&V<K){let z=2**V*1000;await O(z);continue}return null}return null}async compressBatch(u){let y=new Map;for(let B=0;B<u.length;B++){let $=u[B],A=await this.compress($.toolName,$.toolOutput,$.sessionContext);if(y.set($.callId,A),B<u.length-1)await O(200)}return y}createFallbackObservation(u,y){let B=by(y),$=vy[u]??"discovery";return{type:$,title:`${u} execution`,subtitle:y.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${u} was executed. Output length: ${y.length} chars.`,concepts:[],filesRead:$==="discovery"?B:[],filesModified:$==="change"?B:[],discoveryTokens:P(y),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 vy={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},ly=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function by(u){let y=[];for(let B of u.matchAll(ly))y.push(B[1]);return[...new Set(y)]}import{generateText as ry}from"ai";class yu{model;config;_generate=ry;constructor(u){if(this.config=u,this.model=null,u.provider==="bedrock"||u.apiKey)try{this.model=C({provider:u.provider,model:u.model,apiKey:u.apiKey},_(u))}catch{}}async evaluate(u,y){if(!this.model||y.length===0)return null;let B=cu(u,y),$=2;for(let A=0;A<=$;A++)try{if(this.config.provider==="google")await F(this.config.model,this.config.rateLimitingEnabled);let{text:J}=await this._generate({model:this.model,maxOutputTokens:512,prompt:B});return wu(J)}catch(J){if(m(J)&&A<$){let K=2**A*1000;await O(K);continue}return null}return null}}import{generateText as dy}from"ai";class Bu{model;config;_generate=dy;constructor(u){if(this.config=u,this.model=null,u.provider==="bedrock"||u.apiKey)try{this.model=C({provider:u.provider,model:u.model,apiKey:u.apiKey},_(u))}catch{}}async extract(u){if(!this.model)return null;let y=vu(u),B=2;for(let $=0;$<=B;$++)try{if(this.config.provider==="google")await F(this.config.model,this.config.rateLimitingEnabled);let{text:A}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:y});return Iu(A)}catch(A){if(m(A)&&$<B){let J=2**$*1000;await O(J);continue}return null}return null}}import{generateText as iy}from"ai";class $u{model;config;_generate=iy;constructor(u){this.config=u,this.model=null;let y=u.provider!=="bedrock";if(u.compressionEnabled&&(!y||u.apiKey))try{this.model=C({provider:u.provider,model:u.model,apiKey:u.apiKey},_(u))}catch{}}async summarize(u,y){if(y.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(y);let B=gu(y.map(($)=>({type:$.type,title:$.title,narrative:$.narrative})),u);try{if(this.config.provider==="google")await F(this.config.model,this.config.rateLimitingEnabled);let{text:$}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:B}),A=xu($);if(!A)return this.createFallbackSummary(y);return A}catch{return this.createFallbackSummary(y)}}createFallbackSummary(u){let y=new Set,B=new Set,$=[];for(let V of u){for(let R of V.filesModified)y.add(R);for(let R of V.concepts)B.add(R);if(V.type==="decision")$.push(V.title)}let A=new Map;for(let V of u)A.set(V.type,(A.get(V.type)??0)+1);let J=Array.from(A.entries()).map(([V,R])=>`${R} ${V}${R>1?"s":""}`).join(", "),K=Array.from(B).slice(0,5).join(", ");return{summary:`Session with ${u.length} observations: ${J}. Files modified: ${y.size}. Key concepts: ${K}.`,keyDecisions:$.slice(0,5),filesModified:Array.from(y),concepts:Array.from(B)}}shouldSummarize(u){return u>=2}}import{existsSync as J0,readFileSync as K0}from"fs";import{join as y0}from"path";import{existsSync as sy,readdirSync as ty,readFileSync as oy}from"fs";import{join as ey}from"path";var q={id:"code",name:"Code",description:"Default coding workflow mode",observationTypes:["decision","bugfix","feature","refactor","discovery","change"],conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"],entityTypes:["technology","library","pattern","concept","file","person","project","other"],relationshipTypes:["uses","depends_on","implements","extends","related_to","replaces","configures"]};function T(u){return{...u,observationTypes:[...u.observationTypes],conceptVocabulary:[...u.conceptVocabulary],entityTypes:[...u.entityTypes],relationshipTypes:[...u.relationshipTypes],promptOverrides:u.promptOverrides?{...u.promptOverrides}:void 0}}function ay(u){if(!u||typeof u!=="object")return!1;let y=u,B=(A)=>Array.isArray(A)&&A.every((J)=>typeof J==="string"),$=(A)=>typeof A==="object"&&A!==null&&!Array.isArray(A)&&Object.values(A).every((J)=>typeof J==="string");return typeof y.id==="string"&&(y.extends===void 0||typeof y.extends==="string")&&(y.locale===void 0||typeof y.locale==="string")&&(y.name===void 0||typeof y.name==="string")&&(y.description===void 0||typeof y.description==="string")&&(y.observationTypes===void 0||B(y.observationTypes))&&(y.conceptVocabulary===void 0||B(y.conceptVocabulary))&&(y.entityTypes===void 0||B(y.entityTypes))&&(y.relationshipTypes===void 0||B(y.relationshipTypes))&&(y.promptOverrides===void 0||$(y.promptOverrides))}function u0(u){return typeof u.name==="string"&&typeof u.description==="string"&&Array.isArray(u.observationTypes)&&Array.isArray(u.conceptVocabulary)&&Array.isArray(u.entityTypes)&&Array.isArray(u.relationshipTypes)}function du(u,y){return{...u,...y,id:y.id,name:y.name??u.name,description:y.description??u.description,observationTypes:y.observationTypes??u.observationTypes,conceptVocabulary:y.conceptVocabulary??u.conceptVocabulary,entityTypes:y.entityTypes??u.entityTypes,relationshipTypes:y.relationshipTypes??u.relationshipTypes,promptOverrides:{...u.promptOverrides??{},...y.promptOverrides??{}}}}class Au{modesDir;constructor(u){this.modesDir=u}loadAllRaw(){let u=new Map;if(!sy(this.modesDir))return u;for(let y of ty(this.modesDir)){if(!y.endsWith(".json"))continue;let B=ey(this.modesDir,y);try{let $=oy(B,"utf-8"),A=JSON.parse($);if(!ay(A))continue;if(u.has(A.id))console.warn(`[open-mem] Duplicate mode id "${A.id}" in ${B}; overriding previous definition.`);u.set(A.id,A)}catch{}}return u}resolveById(u,y){let B=new Set,$=!1,A=(K)=>{if(B.has(K))return $=!0,T(q);B.add(K);let V=y.get(K);if(!V)return T(q);if(!V.extends){if(!u0(V))return T(q);return du(T(q),V)}let R=A(V.extends);if($)return T(q);return du(R,V)},J=A(u);return $?T(q):T(J)}}var B0=y0(import.meta.dir,"."),$0=new Au(B0),b=null;function A0(){if(b)return b;return b=$0.loadAllRaw(),b}function iu(){return[...A0().keys()].sort()}var z0={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"dispersed",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0,mode:"code"};function R0(){let u={};if(process.env.OPEN_MEM_DB_PATH)u.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)u.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)u.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)u.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")u.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")u.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)u.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((y)=>y.trim());if(process.env.OPEN_MEM_BATCH_SIZE)u.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)u.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)u.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")u.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)u.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((y)=>y.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)u.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)u.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")u.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")u.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")u.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)u.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")u.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")u.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)u.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")u.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")u.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)u.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")u.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")u.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")u.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)u.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)u.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((y)=>y.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)u.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")u.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let y=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(y))u.conflictSimilarityBandLow=y}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let y=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(y))u.conflictSimilarityBandHigh=y}if(process.env.OPEN_MEM_USER_MEMORY==="true")u.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)u.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)u.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")u.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)u.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")u.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)u.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((y)=>y.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)u.mode=process.env.OPEN_MEM_MODE;return u}function V0(u){let y=`${u}/.open-mem/config.json`;if(!J0(y))return{};try{let B=K0(y,"utf-8"),$=JSON.parse(B);if(!$||typeof $!=="object"||Array.isArray($))return{};return $}catch{return{}}}function N0(u){switch(u){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function su(u,y){let B=V0(u),$=R0(),A={...z0,...B,...$,...y};if(!A.dbPath.startsWith("/"))A.dbPath=`${u}/${A.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!y?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)A.provider="google";else if(process.env.ANTHROPIC_API_KEY)A.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)A.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)A.provider="openrouter"}if(!A.apiKey)switch(A.provider){case"google":A.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":A.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":A.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":A.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(A.provider==="openrouter"&&A.model==="gemini-2.5-flash-lite")A.model="google/gemini-2.5-flash-lite";if(A.embeddingDimension===void 0)A.embeddingDimension=N0(A.provider);if(A.mode&&!iu().includes(A.mode))A.mode="code";return A}import{Database as tu}from"bun:sqlite";import{existsSync as Ju,mkdirSync as E0,unlinkSync as ou}from"fs";import*as eu from"sqlite-vec";class r{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let u=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let y of u)try{if(Ju(y))return tu.setCustomSQLite(y),!0}catch{return!1}return!1}constructor(u){this.dbPath=u,this.db=this.open(u),this.configure()}open(u){let y=u.lastIndexOf("/");if(y>0){let B=u.substring(0,y);E0(B,{recursive:!0})}return new tu(u,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(u){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",u.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(y){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",y.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(B){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",B.message),u}}}}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{eu.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let u of["-wal","-shm"]){let y=this.dbPath+u;try{if(Ju(y))ou(y)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(Ju(this.dbPath))ou(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
|
|
160
|
+
[... truncated ...]`:J,H=e$($,X,V),K=2;for(let z=0;z<=K;z++)try{if(this.config.provider==="google")await j(this.config.model,this.config.rateLimitingEnabled);let{text:B}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:H}),Y=s$(B);if(Y)Y.discoveryTokens=Z;return Y}catch(B){if(S(B)&&z<K){let Y=2**z*1000;await x(Y);continue}return null}return null}async compressBatch($){let J=new Map;for(let V=0;V<$.length;V++){let Z=$[V],X=await this.compress(Z.toolName,Z.toolOutput,Z.sessionContext);if(J.set(Z.callId,X),V<$.length-1)await x(200)}return J}createFallbackObservation($,J){let V=L0(J),Z=M0[$]??"discovery";return{type:Z,title:`${$} execution`,subtitle:J.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${$} was executed. Output length: ${J.length} chars.`,concepts:[],filesRead:Z==="discovery"?V:[],filesModified:Z==="change"?V:[],discoveryTokens:f(J),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 M0={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},D0=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function L0($){let J=[];for(let V of $.matchAll(D0))J.push(V[1]);return[...new Set(J)]}import{generateText as _0}from"ai";class z${model;config;_generate=_0;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=T({provider:$.provider,model:$.model,apiKey:$.apiKey},k($))}catch{}}async evaluate($,J){if(!this.model||J.length===0)return null;let V=J1($,J),Z=2;for(let X=0;X<=Z;X++)try{if(this.config.provider==="google")await j(this.config.model,this.config.rateLimitingEnabled);let{text:H}=await this._generate({model:this.model,maxOutputTokens:512,prompt:V});return t$(H)}catch(H){if(S(H)&&X<Z){let K=2**X*1000;await x(K);continue}return null}return null}}import{generateText as R0}from"ai";class B${model;config;_generate=R0;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=T({provider:$.provider,model:$.model,apiKey:$.apiKey},k($))}catch{}}async extract($){if(!this.model)return null;let J=V1($),V=2;for(let Z=0;Z<=V;Z++)try{if(this.config.provider==="google")await j(this.config.model,this.config.rateLimitingEnabled);let{text:X}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:J});return a$(X)}catch(X){if(S(X)&&Z<V){let H=2**Z*1000;await x(H);continue}return null}return null}}import{generateText as C0}from"ai";class Q${model;config;_generate=C0;constructor($){this.config=$,this.model=null;let J=$.provider!=="bedrock";if($.compressionEnabled&&(!J||$.apiKey))try{this.model=T({provider:$.provider,model:$.model,apiKey:$.apiKey},k($))}catch{}}async summarize($,J){if(J.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(J);let V=$1(J.map((Z)=>({type:Z.type,title:Z.title,narrative:Z.narrative})),$);try{if(this.config.provider==="google")await j(this.config.model,this.config.rateLimitingEnabled);let{text:Z}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:V}),X=o$(Z);if(!X)return this.createFallbackSummary(J);return X}catch{return this.createFallbackSummary(J)}}createFallbackSummary($){let J=new Set,V=new Set,Z=[];for(let z of $){for(let B of z.filesModified)J.add(B);for(let B of z.concepts)V.add(B);if(z.type==="decision")Z.push(z.title)}let X=new Map;for(let z of $)X.set(z.type,(X.get(z.type)??0)+1);let H=Array.from(X.entries()).map(([z,B])=>`${B} ${z}${B>1?"s":""}`).join(", "),K=Array.from(V).slice(0,5).join(", ");return{summary:`Session with ${$.length} observations: ${H}. Files modified: ${J.size}. Key concepts: ${K}.`,keyDecisions:Z.slice(0,5),filesModified:Array.from(J),concepts:Array.from(V)}}shouldSummarize($){return $>=2}}import{existsSync as I0,readFileSync as u0}from"fs";import{join as j0}from"path";import{existsSync as y0,readdirSync as O0,readFileSync as E0}from"fs";import{join as S0}from"path";var P={id:"code",name:"Code",description:"Default coding workflow mode",observationTypes:["decision","bugfix","feature","refactor","discovery","change"],conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"],entityTypes:["technology","library","pattern","concept","file","person","project","other"],relationshipTypes:["uses","depends_on","implements","extends","related_to","replaces","configures"]};function I($){return{...$,observationTypes:[...$.observationTypes],conceptVocabulary:[...$.conceptVocabulary],entityTypes:[...$.entityTypes],relationshipTypes:[...$.relationshipTypes],promptOverrides:$.promptOverrides?{...$.promptOverrides}:void 0}}function k0($){if(!$||typeof $!=="object")return!1;let J=$,V=(X)=>Array.isArray(X)&&X.every((H)=>typeof H==="string"),Z=(X)=>typeof X==="object"&&X!==null&&!Array.isArray(X)&&Object.values(X).every((H)=>typeof H==="string");return typeof J.id==="string"&&(J.extends===void 0||typeof J.extends==="string")&&(J.locale===void 0||typeof J.locale==="string")&&(J.name===void 0||typeof J.name==="string")&&(J.description===void 0||typeof J.description==="string")&&(J.observationTypes===void 0||V(J.observationTypes))&&(J.conceptVocabulary===void 0||V(J.conceptVocabulary))&&(J.entityTypes===void 0||V(J.entityTypes))&&(J.relationshipTypes===void 0||V(J.relationshipTypes))&&(J.promptOverrides===void 0||Z(J.promptOverrides))}function T0($){return typeof $.name==="string"&&typeof $.description==="string"&&Array.isArray($.observationTypes)&&Array.isArray($.conceptVocabulary)&&Array.isArray($.entityTypes)&&Array.isArray($.relationshipTypes)}function K1($,J){return{...$,...J,id:J.id,name:J.name??$.name,description:J.description??$.description,observationTypes:J.observationTypes??$.observationTypes,conceptVocabulary:J.conceptVocabulary??$.conceptVocabulary,entityTypes:J.entityTypes??$.entityTypes,relationshipTypes:J.relationshipTypes??$.relationshipTypes,promptOverrides:{...$.promptOverrides??{},...J.promptOverrides??{}}}}class U${modesDir;constructor($){this.modesDir=$}loadAllRaw(){let $=new Map;if(!y0(this.modesDir))return $;for(let J of O0(this.modesDir)){if(!J.endsWith(".json"))continue;let V=S0(this.modesDir,J);try{let Z=E0(V,"utf-8"),X=JSON.parse(Z);if(!k0(X))continue;if($.has(X.id))console.warn(`[open-mem] Duplicate mode id "${X.id}" in ${V}; overriding previous definition.`);$.set(X.id,X)}catch{}}return $}resolveById($,J){let V=new Set,Z=!1,X=(K)=>{if(V.has(K))return Z=!0,I(P);V.add(K);let z=J.get(K);if(!z)return I(P);if(!z.extends){if(!T0(z))return I(P);return K1(I(P),z)}let B=X(z.extends);if(Z)return I(P);return K1(B,z)},H=X($);return Z?I(P):I(H)}}var q0=j0(import.meta.dir,"."),x0=new U$(q0),o=null;function f0(){if(o)return o;return o=x0.loadAllRaw(),o}function Y1(){return[...f0().keys()].sort()}var w0={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"single",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0,mode:"code"};function P0(){let $={};if(process.env.OPEN_MEM_DB_PATH)$.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)$.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)$.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)$.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")$.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")$.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)$.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((J)=>J.trim());if(process.env.OPEN_MEM_BATCH_SIZE)$.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)$.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)$.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")$.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)$.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((J)=>J.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)$.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)$.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")$.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")$.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")$.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)$.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")$.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")$.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)$.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")$.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")$.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)$.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")$.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")$.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")$.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)$.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)$.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((J)=>J.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)$.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")$.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let J=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(J))$.conflictSimilarityBandLow=J}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let J=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(J))$.conflictSimilarityBandHigh=J}if(process.env.OPEN_MEM_USER_MEMORY==="true")$.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)$.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)$.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")$.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)$.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")$.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)$.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((J)=>J.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)$.mode=process.env.OPEN_MEM_MODE;return $}function v0($){let J=`${$}/.open-mem/config.json`;if(!I0(J))return{};try{let V=u0(J,"utf-8"),Z=JSON.parse(V);if(!Z||typeof Z!=="object"||Array.isArray(Z))return{};return Z}catch{return{}}}function h0($){switch($){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function z1($,J){let V=v0($),Z=P0(),X={...w0,...V,...Z,...J};if(!X.dbPath.startsWith("/"))X.dbPath=`${$}/${X.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!J?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)X.provider="google";else if(process.env.ANTHROPIC_API_KEY)X.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)X.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)X.provider="openrouter"}if(!X.apiKey)switch(X.provider){case"google":X.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":X.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":X.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":X.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(X.provider==="openrouter"&&X.model==="gemini-2.5-flash-lite")X.model="google/gemini-2.5-flash-lite";if(X.embeddingDimension===void 0)X.embeddingDimension=h0(X.provider);if(X.mode&&!Y1().includes(X.mode))X.mode="code";return X}import{existsSync as i0}from"fs";import{existsSync as g0}from"fs";import{homedir as m0}from"os";import{join as B1}from"path";function b0(){let $=[],J=process.env.BUN_INSTALL;if(J)$.push(B1(J,"bin","bun"));let V=m0();return $.push(B1(V,".bun","bin","bun")),$.push("/usr/local/bin/bun"),$.push("/opt/homebrew/bin/bun"),$.push("/home/linuxbrew/.linuxbrew/bin/bun"),$}function p0(){let $=Bun.which("bun");if($)return $;for(let J of b0())if(g0(J))return console.debug(`[open-mem] Resolved bun path via candidate scan: ${J}`),J;return"bun"}var W$=null;function Q1(){if(W$===null)W$=p0();return W$}import{existsSync as c0,mkdirSync as l0,readFileSync as d0,unlinkSync as U1,writeFileSync as n0}from"fs";function W1($){let J=$.lastIndexOf("/");if(J>0){let V=$.substring(0,J);l0(V,{recursive:!0})}n0($,String(process.pid),"utf-8")}function b($){if(!c0($))return null;let J=d0($,"utf-8").trim(),V=Number.parseInt(J,10);if(Number.isNaN(V))return null;return V}function p($){try{return process.kill($,0),!0}catch(J){if(J instanceof Error&&"code"in J&&J.code==="EPERM")return!0;return!1}}function A1($,J){let V=b($);if(V===null)return{state:"missing",pid:null,stalePid:null,stalePidRemoved:!1};if(p(V))return{state:"alive",pid:V,stalePid:null,stalePidRemoved:!1};if(!J)return{state:"dead",pid:null,stalePid:V,stalePidRemoved:!1};let Z=A$($,V);return{state:"dead",pid:null,stalePid:V,stalePidRemoved:Z}}function N1($){try{U1($)}catch{}}function A$($,J){let V=b($);if(V===null||V!==J)return!1;try{return U1($),!0}catch{return!1}}function G1($){let J=$.lastIndexOf("/");if(J>=0)return`${$.substring(0,J)}/worker.pid`;return"worker.pid"}function F1($,J){let V=$.lastIndexOf("/");return`${V>=0?$.substring(0,V):"."}/platform-worker-${J}.pid`}var r0=100,s0=2000;class N${pidPath;projectPath;daemonScript;subprocess=null;constructor($){this.pidPath=G1($.dbPath),this.projectPath=$.projectPath,this.daemonScript=$.daemonScript}start(){if(this.isRunning())return!1;this.subprocess=Bun.spawn([Q1(),"run",this.daemonScript,"--project",this.projectPath],{detached:!0,stdio:["ignore","ignore","ignore"],ipc(J){}}),this.subprocess.unref();let $=Date.now()+s0;while(Date.now()<$)if(Bun.sleepSync(r0),i0(this.pidPath)){let J=b(this.pidPath);if(J!==null&&p(J))return!0}return!1}signal($){let J=()=>{try{return this.getStatus()}catch{return null}};try{if(this.subprocess)return this.subprocess.send($),{ok:!0,state:"delivered",via:"ipc",pid:J()?.pid??null,message:$};if($!=="PROCESS_NOW")return{ok:!1,state:"unsupported-signal",via:"none",pid:null,message:$};let V=this.getStatus();if(V.state==="missing")return{ok:!1,state:"no-daemon",via:"none",pid:null,message:$};if(V.state==="dead")return{ok:!1,state:"daemon-dead",via:"none",pid:V.stalePid,message:$};if(V.pid!==null)return process.kill(V.pid,"SIGUSR1"),{ok:!0,state:"delivered",via:"os-signal",pid:V.pid,message:$};return{ok:!1,state:"delivery-failed",via:"none",pid:null,message:$,error:"Daemon was reported running but did not expose a PID"}}catch(V){return{ok:!1,state:"delivery-failed",via:"none",pid:J()?.pid??null,message:$,error:String(V)}}}stop(){let $=b(this.pidPath);if($!==null)try{process.kill($,"SIGTERM")}catch{}this.subprocess=null,N1(this.pidPath)}isRunning(){return this.getStatus().running}getStatus(){return o0(this.pidPath,!0)}}function o0($,J){let V=A1($,J);if(V.state==="missing")return{state:"missing",running:!1,pid:null,stalePid:null,stalePidRemoved:!1};if(V.state==="dead")return{state:"dead",running:!1,pid:null,stalePid:V.stalePid,stalePidRemoved:V.stalePidRemoved};return{state:"running",running:!0,pid:V.pid,stalePid:null,stalePidRemoved:!1}}import{Database as O1}from"bun:sqlite";import{existsSync as zJ,mkdirSync as BJ}from"fs";import*as S1 from"sqlite-vec";import{closeSync as t0,fsyncSync as a0,openSync as e0,readFileSync as $J,unlinkSync as D1,writeFileSync as JJ}from"fs";import{hostname as L1}from"os";var _1="plugin";class t extends Error{lockPath;role;waitDurationMs;owner;constructor($){super(`Timed out acquiring advisory write lock after ${$.waitDurationMs}ms (role=${$.role}, lockPath=${$.lockPath})`);this.name="AdvisoryLockTimeoutError",this.lockPath=$.lockPath,this.role=$.role,this.waitDurationMs=$.waitDurationMs,this.owner=$.owner}}var VJ=5000,ZJ=50,v=new Map;function XJ($){if($<=0)return;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,$)}function M1($,J){if(typeof $!=="number"||!Number.isFinite($)||$<=0)return J;return Math.floor($)}function R1($){try{let J=$J($,"utf8").trim();if(!J)return null;let V=JSON.parse(J);if(typeof V!=="object"||V===null||typeof V.pid!=="number"||typeof V.role!=="string"||typeof V.hostname!=="string"||typeof V.acquiredAt!=="string")return null;return{pid:V.pid,role:V.role,hostname:V.hostname,acquiredAt:V.acquiredAt,ownerId:typeof V.ownerId==="string"?V.ownerId:void 0}}catch{return null}}function HJ($,J){if(!$||!J)return!1;return $.pid===J.pid&&$.role===J.role&&$.hostname===J.hostname&&$.acquiredAt===J.acquiredAt&&$.ownerId===J.ownerId}function KJ($,J){if(!J)return!1;if(J.hostname!==L1())return!1;if(p(J.pid))return!1;let V=R1($);if(!HJ(V,J))return!1;try{return D1($),!0}catch(Z){if(Z.code==="ENOENT")return!1;throw Z}}function G$($,J){t0(J);try{D1($)}catch(V){if(V.code!=="ENOENT")throw V}}function C1($){return`${$}.write.lock`}function YJ($,J){let V=J.now??Date.now,Z=M1(J.timeoutMs,VJ),X=M1(J.retryIntervalMs,ZJ),H=v.get($);if(H){H.count+=1;let Y=!1;return{lockPath:$,role:J.role,waitDurationMs:0,reentrant:!0,release:()=>{if(Y)return;Y=!0;let Q=v.get($);if(!Q)return;if(Q.count-=1,Q.count===0)v.delete($),G$($,Q.fd)}}}let K={pid:process.pid,role:J.role,hostname:L1(),acquiredAt:new Date(V()).toISOString(),ownerId:J.ownerId},z=V(),B=null;for(;;)try{let Y=e0($,"wx");try{JJ(Y,JSON.stringify(K),"utf8"),a0(Y)}catch(U){throw G$($,Y),U}v.set($,{count:1,fd:Y});let Q=!1;return{lockPath:$,role:J.role,waitDurationMs:V()-z,reentrant:!1,release:()=>{if(Q)return;Q=!0;let U=v.get($);if(!U)return;if(U.count-=1,U.count===0)v.delete($),G$($,U.fd)}}}catch(Y){if(Y.code!=="EEXIST")throw Y;if(B=R1($),KJ($,B))continue;let U=V()-z;if(U>=Z)throw new t({lockPath:$,role:J.role,waitDurationMs:U,owner:B});XJ(Math.min(X,Z-U))}}function y1($,J,V){let Z=YJ($,J);try{return V()}finally{Z.release()}}var QJ=new Set(["SQLITE_BUSY","SQLITE_LOCKED","SQLITE_IOERR","SQLITE_IOERR_VNODE","SQLITE_IOERR_READ","SQLITE_IOERR_WRITE","SQLITE_IOERR_SHORT_READ","SQLITE_IOERR_FSYNC","SQLITE_PROTOCOL"]),UJ=3,E1=50,WJ=new Set(["INSERT","UPDATE","DELETE","REPLACE","CREATE","ALTER","DROP","VACUUM","REINDEX","ANALYZE","ATTACH","DETACH"]),AJ=new Set(["WAL_CHECKPOINT","OPTIMIZE","INCREMENTAL_VACUUM","SHRINK_MEMORY"]),NJ=/^(?:\s+|--[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)+/;function GJ($){let J=$;for(;;){let V=J.replace(NJ,"");if(V===J)return J.trimStart();J=V}}function FJ($){let J=[],V=0,Z=!1,X=!1,H=!1,K=!1,z=!1,B=!1;for(let Q=0;Q<$.length;Q+=1){let U=$[Q],A=$[Q+1];if(z){if(U===`
|
|
161
|
+
`)z=!1;continue}if(B){if(U==="*"&&A==="/")B=!1,Q+=1;continue}if(Z){if(U==="'")if(A==="'")Q+=1;else Z=!1;continue}if(X){if(U==='"')if(A==='"')Q+=1;else X=!1;continue}if(H){if(U==="`")H=!1;continue}if(K){if(U==="]")K=!1;continue}if(U==="-"&&A==="-"){z=!0,Q+=1;continue}if(U==="/"&&A==="*"){B=!0,Q+=1;continue}if(U==="'"){Z=!0;continue}if(U==='"'){X=!0;continue}if(U==="`"){H=!0;continue}if(U==="["){K=!0;continue}if(U===";"){let W=$.slice(V,Q).trim();if(W.length>0)J.push(W);V=Q+1}}let Y=$.slice(V).trim();if(Y.length>0)J.push(Y);return J}function MJ($){let J=GJ($);if(!J)return!1;let V=J.toUpperCase();if(/\bRETURNING\b/.test(V))return!0;if(V.startsWith("PRAGMA")){if(/^PRAGMA\s+(?:[A-Z0-9_]+\.)?[A-Z0-9_]+\s*=/.test(V))return!0;let X=/^PRAGMA\s+(?:[A-Z0-9_]+\.)?([A-Z0-9_]+)/.exec(V)?.[1];if(!X)return!1;return AJ.has(X)}let Z=/^[A-Z]+/.exec(V)?.[0];if(!Z)return!1;if(WJ.has(Z))return!0;if(Z==="WITH")return/\b(INSERT|UPDATE|DELETE|REPLACE)\b/.test(V);return!1}function F$($){let J=FJ($);if(J.length===0)return!1;for(let V of J)if(MJ(V))return!0;return!1}var DJ=new Set(["PASSIVE","FULL","RESTART","TRUNCATE"]);function c($){if($ instanceof Error){let J=$.code;return{code:typeof J==="string"?J:"UNKNOWN",message:$.message}}return{code:"UNKNOWN",message:String($)}}function LJ($){if($&&typeof $==="object"&&"code"in $){let J=$.code;return QJ.has(J)}return!1}class a{db;dbPath;advisoryWriteLockPath;processRole;transactionDepth=0;_hasVectorExtension=!1;static enableExtensionSupport(){let $=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let J of $)try{if(zJ(J))return O1.setCustomSQLite(J),!0}catch{return!1}return!1}constructor($,J={}){this.dbPath=$,this.processRole=J.processRole??_1,this.advisoryWriteLockPath=C1($),this.db=this.open($),this.configure()}open($){let J=$.lastIndexOf("/");if(J>0){let V=$.substring(0,J);BJ(V,{recursive:!0})}return new O1($,{create:!0})}configure(){this.runConfigureStage("applyPragmas",()=>this.applyPragmas()),this.runConfigureStage("loadExtensions",()=>this.loadExtensions())}runConfigureStage($,J){try{J()}catch(V){this.throwConfigureFailure($,V)}}throwConfigureFailure($,J){let V=c(J);try{this.db.close()}catch{}throw console.error("[open-mem] Database configure failed (non-destructive fail-safe)",{stage:$,dbPath:this.dbPath,sqliteCode:V.code,sqliteMessage:V.message,action:"startup-abort",deletionAttempted:!1}),Error(`Database startup failed during ${$} (fail-safe, non-destructive): [${V.code}] ${V.message}`)}applyPragmas(){this.db.exec("PRAGMA journal_mode = WAL"),this.db.exec("PRAGMA synchronous = NORMAL"),this.db.exec("PRAGMA foreign_keys = ON"),this.db.exec("PRAGMA busy_timeout = 5000")}loadExtensions(){try{S1.load(this.db),this._hasVectorExtension=!0}catch($){let J=c($);console.warn("[open-mem] SQLite extension load skipped",{stage:"loadExtensions",dbPath:this.dbPath,sqliteCode:J.code,sqliteMessage:J.message,action:"continue-without-extension"}),this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}ensureMigrationTable(){this.db.exec(`
|
|
161
162
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
162
163
|
version INTEGER PRIMARY KEY,
|
|
163
164
|
name TEXT NOT NULL,
|
|
164
165
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
165
166
|
)
|
|
166
|
-
`)}migrate(
|
|
167
|
+
`)}migrate($){this.withAdvisoryWriteLock(this.processRole,()=>{this.ensureMigrationTable();let J=this.withRetry("migrate.applied_versions",()=>{return this.db.query("SELECT version FROM _migrations ORDER BY version").all()}),V=new Set(J.map((X)=>X.version)),Z=$.filter((X)=>!V.has(X.version)).sort((X,H)=>X.version-H.version);for(let X of Z)this.transaction(()=>{this.exec(X.up),this.run("INSERT INTO _migrations (version, name) VALUES ($version, $name)",[{$version:X.version,$name:X.name}])})})}withRetry($,J){let V=this.transactionDepth>0?0:UJ,Z;for(let X=0;X<=V;X++)try{return J()}catch(H){if(Z=H,!LJ(H)||X===V)throw H;let K=E1*2**X+Math.random()*E1;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,K);let z=c(H);console.warn("[open-mem] Retrying after transient SQLite error",{attempt:X+1,maxRetries:V,operation:$,role:this.processRole,dbPath:this.dbPath,sqliteCode:z.code,sqliteMessage:z.message})}throw Z}run($,J){this.withAdvisoryWriteLock(this.processRole,()=>{this.withRetry("run",()=>{let V=this.db.query($);if(J)V.run(...J);else V.run()})})}get($,J){let V=()=>{let Z=this.db.query($);return J?Z.get(...J):Z.get()};if(F$($))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("get",V));return this.withRetry("get",V)}all($,J){let V=()=>{let Z=this.db.query($);return J?Z.all(...J):Z.all()};if(F$($))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("all",V));return this.withRetry("all",V)}exec($){let J=()=>this.withRetry("exec",()=>this.db.exec($));if(F$($)){this.withAdvisoryWriteLock(this.processRole,J);return}J()}transaction($){return this.withAdvisoryWriteLock(this.processRole,()=>{if(this.transactionDepth>0)return $();let J=this.db.transaction($);if(typeof J.immediate==="function"){this.transactionDepth+=1;try{return J.immediate()}finally{this.transactionDepth-=1}}this.db.exec("BEGIN IMMEDIATE"),this.transactionDepth+=1;try{let V=$();return this.db.exec("COMMIT"),V}catch(V){let Z=V;try{this.db.exec("ROLLBACK")}catch(X){if(Z instanceof Error){let H=Z;if(H.cause===void 0)H.cause=X;else H.suppressed=[...H.suppressed??[],X]}console.warn("[open-mem] Transaction rollback failed after transaction error",{dbPath:this.dbPath,originalError:c(Z),rollbackError:c(X)})}throw Z}finally{this.transactionDepth-=1}})}get writeLockPath(){return this.advisoryWriteLockPath}withAdvisoryWriteLock($,J,V){try{return y1(this.advisoryWriteLockPath,{...V,role:$},J)}catch(Z){if(Z instanceof t)console.error("[open-mem] Advisory write lock timeout",{role:$,dbPath:this.dbPath,lockPath:Z.lockPath,waitDurationMs:Z.waitDurationMs,owner:Z.owner});throw Z}}checkpointWal($="PASSIVE"){let J=typeof $==="string"?$.toUpperCase():"";if(!DJ.has(J))throw Error(`Invalid wal_checkpoint mode: ${String($)}`);return this.withAdvisoryWriteLock(this.processRole,()=>{return this.withRetry("maintenance.wal_checkpoint",()=>{let V=this.db.query(`PRAGMA wal_checkpoint(${J})`).get();if(!V)throw Error("wal_checkpoint returned no result row");return{mode:J,busy:V.busy??0,logFrames:V.log??0,checkpointedFrames:V.checkpointed??0}})})}integrityCheck($=1){let J=Number.isFinite($)?Math.max(1,Math.floor($)):1;return this.withRetry("maintenance.integrity_check",()=>{let V=this.db.query(`PRAGMA integrity_check(${J})`).all();if(V.length===0)throw Error("integrity_check returned no result rows");let Z=V.map((X)=>Object.values(X).find((H)=>typeof H==="string")).filter((X)=>typeof X==="string").map((X)=>X.trim()).filter((X)=>X.length>0);if(Z.length===0)throw Error("integrity_check returned no diagnostic messages");return{ok:Z.length===1&&Z[0].toLowerCase()==="ok",messages:Z,maxErrors:J}})}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function k1($,J){return new a($,J)}import{randomUUID as T1}from"crypto";class M${db;constructor($){this.db=$}upsertEntity($,J){let V=T1(),Z=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
|
|
167
168
|
VALUES (?, ?, ?, ?, ?, 1)
|
|
168
169
|
ON CONFLICT(name, entity_type) DO UPDATE SET
|
|
169
170
|
mention_count = mention_count + 1,
|
|
170
|
-
last_seen_at = ?`,[
|
|
171
|
+
last_seen_at = ?`,[V,$,J,Z,Z,Z]);let X=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[$,J]);if(!X)throw Error(`Failed to upsert entity: ${$} (${J})`);return this.mapEntityRow(X)}createRelation($,J,V,Z){let X=T1(),H=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
|
|
171
172
|
(id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
|
|
172
|
-
VALUES (?, ?, ?, ?, ?, ?)`,[
|
|
173
|
-
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[
|
|
173
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[X,$,J,V,Z,H])}catch{return null}let K=this.db.get(`SELECT * FROM entity_relations
|
|
174
|
+
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[$,J,V]);return K?this.mapRelationRow(K):null}linkObservation($,J){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[$,J])}findByName($){try{return this.db.all(`SELECT e.*
|
|
174
175
|
FROM entities e
|
|
175
176
|
JOIN entities_fts fts ON e._rowid = fts.rowid
|
|
176
177
|
WHERE entities_fts MATCH ?
|
|
177
|
-
ORDER BY rank`,[
|
|
178
|
-
WHERE source_entity_id = ? OR target_entity_id = ?`,[
|
|
179
|
-
`)}function
|
|
178
|
+
ORDER BY rank`,[$]).map((V)=>this.mapEntityRow(V))}catch{return[]}}getRelationsFor($){return this.db.all(`SELECT * FROM entity_relations
|
|
179
|
+
WHERE source_entity_id = ? OR target_entity_id = ?`,[$,$]).map((V)=>this.mapRelationRow(V))}traverseRelations($,J=1){let V=Math.min(J,2),Z=100,X=new Set,H=[{id:$,currentDepth:0}];X.add($);while(H.length>0){if(X.size>=100)break;let K=H.shift();if(!K)continue;if(K.currentDepth>=V)continue;let z=this.getRelationsFor(K.id);for(let B of z){let Y=B.sourceEntityId===K.id?B.targetEntityId:B.sourceEntityId;if(!X.has(Y))X.add(Y),H.push({id:Y,currentDepth:K.currentDepth+1})}}return X}getObservationsForEntity($){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[$]).map((V)=>V.observation_id)}getById($){let J=this.db.get("SELECT * FROM entities WHERE id = ?",[$]);return J?this.mapEntityRow(J):null}mapEntityRow($){return{id:$.id,name:$.name,entityType:$.entity_type,firstSeenAt:$.first_seen_at,lastSeenAt:$.last_seen_at,mentionCount:$.mention_count}}mapRelationRow($){return{id:$.id,sourceEntityId:$.source_entity_id,targetEntityId:$.target_entity_id,relationship:$.relationship,observationId:$.observation_id,createdAt:$.created_at}}}import{randomUUID as RJ}from"crypto";import{embed as _J}from"ai";async function D$($,J){try{let{embedding:V}=await _J({model:$,value:J});return V}catch{return null}}function j1($,J){if($.length!==J.length||$.length===0)return 0;let V=0,Z=0,X=0;for(let K=0;K<$.length;K++)V+=$[K]*J[K],Z+=$[K]*$[K],X+=J[K]*J[K];let H=Math.sqrt(Z)*Math.sqrt(X);if(H===0)return 0;return V/H}function L$($){let J=[$.title,$.narrative];if($.concepts.length>0)J.push($.concepts.join(", "));return J.join(`
|
|
180
|
+
`)}function CJ($){return $.replace(/[%_\\]/g,"\\$&")}class _${db;constructor($){this.db=$}create($){let J=RJ(),V=new Date().toISOString(),Z=$.discoveryTokens??0,X=$.importance??3,H=$.scope??"project";return this.db.run(`INSERT INTO observations
|
|
180
181
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
181
182
|
concepts, files_read, files_modified, raw_tool_output,
|
|
182
183
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
183
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
184
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[J,$.sessionId,H,$.type,$.title,$.subtitle,JSON.stringify($.facts),$.narrative,JSON.stringify($.concepts),JSON.stringify($.filesRead),JSON.stringify($.filesModified),$.rawToolOutput,$.toolName,V,$.tokenCount,Z,X,null,null]),{...$,id:J,scope:H,createdAt:V,discoveryTokens:Z,importance:X,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation($){this.db.run(`INSERT INTO observations
|
|
184
185
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
185
186
|
concepts, files_read, files_modified, raw_tool_output,
|
|
186
187
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
187
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
188
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[$.id,$.sessionId,$.scope??"project",$.type,$.title,$.subtitle,JSON.stringify($.facts),$.narrative,JSON.stringify($.concepts),JSON.stringify($.filesRead),JSON.stringify($.filesModified),$.rawToolOutput,$.toolName,$.createdAt,$.tokenCount,$.discoveryTokens??0,$.importance??3,$.revisionOf??null,$.deletedAt??null])}getById($){let J=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[$]);return J?this.mapRow(J):null}getByIdIncludingArchived($){let J=this.db.get("SELECT * FROM observations WHERE id = ?",[$]);return J?this.mapRow(J):null}getBySession($){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",[$]).map((J)=>this.mapRow(J))}getCount($){if($)return this.db.get("SELECT COUNT(*) as count FROM observations WHERE session_id = ?",[$])?.count??0;return this.db.get("SELECT COUNT(*) as count FROM observations")?.count??0}getIndex($,J=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
|
|
188
189
|
FROM observations o
|
|
189
190
|
JOIN sessions s ON o.session_id = s.id
|
|
190
191
|
WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
191
192
|
ORDER BY o.created_at DESC
|
|
192
|
-
LIMIT ?`,[
|
|
193
|
+
LIMIT ?`,[$,J]).map((V)=>({id:V.id,sessionId:V.session_id,type:V.type,title:V.title,tokenCount:V.token_count,discoveryTokens:V.discovery_tokens??0,createdAt:V.created_at,importance:V.importance??3}))}getAroundTimestamp($,J,V,Z){let X=J>0?this.db.all(`SELECT o.*
|
|
193
194
|
FROM observations o
|
|
194
195
|
JOIN sessions s ON o.session_id = s.id
|
|
195
196
|
WHERE s.project_path = ? AND o.created_at < ?
|
|
196
197
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
197
198
|
ORDER BY o.created_at DESC
|
|
198
|
-
LIMIT ?`,[
|
|
199
|
+
LIMIT ?`,[Z,$,J]).reverse():[],H=V>0?this.db.all(`SELECT o.*
|
|
199
200
|
FROM observations o
|
|
200
201
|
JOIN sessions s ON o.session_id = s.id
|
|
201
202
|
WHERE s.project_path = ? AND o.created_at > ?
|
|
202
203
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
203
204
|
ORDER BY o.created_at ASC
|
|
204
|
-
LIMIT ?`,[
|
|
205
|
+
LIMIT ?`,[Z,$,V]):[];return[...X,...H].map((K)=>this.mapRow(K))}listByProject($,J={}){let{limit:V=50,offset:Z=0,type:X,state:H,sessionId:K}=J,z=`SELECT o.*
|
|
205
206
|
FROM observations o
|
|
206
207
|
JOIN sessions s ON o.session_id = s.id
|
|
207
|
-
WHERE s.project_path = ?`,
|
|
208
|
+
WHERE s.project_path = ?`,B=[$];if(K)z+=" AND o.session_id = ?",B.push(K);if(X)z+=" AND o.type = ?",B.push(X);if(H==="current")z+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(H==="superseded")z+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(H==="tombstoned")z+=" AND o.deleted_at IS NOT NULL";else z+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return z+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",B.push(V,Z),this.db.all(z,B).map((Y)=>this.mapRow(Y))}search($){let J=!!$.projectPath,V=`
|
|
208
209
|
SELECT o.*, rank
|
|
209
210
|
FROM observations o
|
|
210
211
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
211
|
-
${
|
|
212
|
+
${J?"JOIN sessions s ON o.session_id = s.id":""}
|
|
212
213
|
WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
213
|
-
|
|
214
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);
|
|
214
|
+
`,Z=[$.query];if(J&&$.projectPath)V+=" AND s.project_path = ?",Z.push($.projectPath);if($.sessionId)V+=" AND o.session_id = ?",Z.push($.sessionId);if($.type)V+=" AND o.type = ?",Z.push($.type);if($.importanceMin!==void 0)V+=" AND o.importance >= ?",Z.push($.importanceMin);if($.importanceMax!==void 0)V+=" AND o.importance <= ?",Z.push($.importanceMax);if($.createdAfter)V+=" AND o.created_at >= ?",Z.push($.createdAfter);if($.createdBefore)V+=" AND o.created_at <= ?",Z.push($.createdBefore);if($.concepts&&$.concepts.length>0){let X=$.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");V+=` AND (${X.join(" OR ")})`;for(let H of $.concepts)Z.push(H)}if($.files&&$.files.length>0){let X=$.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
|
|
215
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);V+=` AND (${X.join(" OR ")})`;for(let H of $.files){let K=`%${CJ(H)}%`;Z.push(K,K)}}return V+=" ORDER BY rank LIMIT ? OFFSET ?",Z.push($.limit??10),Z.push($.offset??0),this.db.all(V,Z).map((X)=>({observation:this.mapRow(X),rank:X.rank,snippet:X.title}))}searchByConcept($,J=10,V){let Z=!!V,X=`SELECT o.*
|
|
215
216
|
FROM observations o
|
|
216
217
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
217
|
-
${
|
|
218
|
+
${Z?"JOIN sessions s ON o.session_id = s.id":""}
|
|
218
219
|
WHERE observations_fts MATCH ?
|
|
219
220
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
220
|
-
${
|
|
221
|
+
${Z?"AND s.project_path = ?":""}
|
|
221
222
|
ORDER BY rank
|
|
222
|
-
LIMIT ?`,K=[`concepts:"${
|
|
223
|
+
LIMIT ?`,K=[`concepts:"${$.replace(/"/g,'""')}"`];if(Z&&V)K.push(V);return K.push(J),this.db.all(X,K).map((z)=>this.mapRow(z))}searchByFile($,J=10,V){let Z=!!V,X=`SELECT o.*
|
|
223
224
|
FROM observations o
|
|
224
225
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
225
|
-
${
|
|
226
|
+
${Z?"JOIN sessions s ON o.session_id = s.id":""}
|
|
226
227
|
WHERE observations_fts MATCH ?
|
|
227
228
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
228
|
-
${
|
|
229
|
+
${Z?"AND s.project_path = ?":""}
|
|
229
230
|
ORDER BY rank
|
|
230
|
-
LIMIT ?`,
|
|
231
|
+
LIMIT ?`,H=[`files_read:"${$.replace(/"/g,'""')}" OR files_modified:"${$.replace(/"/g,'""')}"`];if(Z&&V)H.push(V);return H.push(J),this.db.all(X,H).map((K)=>this.mapRow(K))}setEmbedding($,J){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(J),$])}getWithEmbeddings($,J){return this.db.all(`SELECT o.id, o.embedding, o.title
|
|
231
232
|
FROM observations o
|
|
232
233
|
JOIN sessions s ON o.session_id = s.id
|
|
233
234
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
234
235
|
ORDER BY o.created_at DESC
|
|
235
|
-
LIMIT ?`,[
|
|
236
|
+
LIMIT ?`,[$,J]).map((V)=>{try{return{id:V.id,embedding:JSON.parse(V.embedding),title:V.title}}catch{return null}}).filter((V)=>V!==null)}findSimilar($,J,V,Z){let X=this.db.all(`SELECT id, embedding FROM observations
|
|
236
237
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
237
238
|
ORDER BY created_at DESC
|
|
238
|
-
LIMIT 200`,[
|
|
239
|
+
LIMIT 200`,[J]),H=[];for(let K of X)try{let z=JSON.parse(K.embedding);if(!Array.isArray(z)||z.length!==$.length)continue;let B=j1($,z);if(B>=V)H.push({id:K.id,similarity:B})}catch{}return H.sort((K,z)=>z.similarity-K.similarity).slice(0,Z)}insertVecEmbedding($,J){let V=new Float32Array(J);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[$]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[$,V]),this.db.run("COMMIT")}catch(Z){throw this.db.run("ROLLBACK"),Z}}migrateExistingEmbeddings($){let J=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),V=0,Z=0;for(let X of J)try{let H=JSON.parse(X.embedding);if(!Array.isArray(H)||H.length!==$){Z++;continue}this.insertVecEmbedding(X.id,H),V++}catch{Z++}return{migrated:V,skipped:Z}}getVecEmbeddingMatches($,J){try{let V=new Float32Array($);return this.db.all(`SELECT observation_id, distance
|
|
239
240
|
FROM observation_embeddings
|
|
240
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
241
|
+
WHERE embedding MATCH ? AND k = ?`,[V,J]).map((Z)=>({observationId:Z.observation_id,distance:Z.distance}))}catch{return[]}}searchVecSubset($,J,V){if(J.length===0)return[];try{let Z=new Float32Array($),X=Math.max(V*5,J.length),H=this.db.all(`SELECT observation_id, distance
|
|
241
242
|
FROM observation_embeddings
|
|
242
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
243
|
+
WHERE embedding MATCH ? AND k = ?`,[Z,X]),K=new Set(J);return H.filter((z)=>K.has(z.observation_id)).slice(0,V).map((z)=>({observationId:z.observation_id,distance:z.distance}))}catch{return[]}}update($,J){let V=this.getById($);if(!V)return null;if(Object.keys(J).length===0)return V;let Z=this.create({sessionId:V.sessionId,scope:V.scope??"project",type:J.type??V.type,title:J.title??V.title,subtitle:J.subtitle??V.subtitle,facts:J.facts??V.facts,narrative:J.narrative??V.narrative,concepts:J.concepts??V.concepts,filesRead:J.filesRead??V.filesRead,filesModified:J.filesModified??V.filesModified,rawToolOutput:V.rawToolOutput,toolName:"mem-revise",tokenCount:V.tokenCount,discoveryTokens:V.discoveryTokens,importance:J.importance??V.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[$,Z.id]),this.supersede($,Z.id),this.getById(Z.id)}supersede($,J){let V=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[J,V,$])}delete($){if(this.db.all("SELECT id FROM observations WHERE id = ?",[$]).length===0)return!1;let V=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[V,$]),this.deleteEmbeddingsForObservations([$]),!0}getLineage($){let J=this.getByIdIncludingArchived($);if(!J)return[];let V=new Set([J.id]),Z=[J];while(Z[0].revisionOf){let X=this.getByIdIncludingArchived(Z[0].revisionOf);if(!X||V.has(X.id))break;Z.unshift(X),V.add(X.id)}while(Z[Z.length-1].supersededBy){let X=Z[Z.length-1].supersededBy;if(!X)break;let H=this.getByIdIncludingArchived(X);if(!H||V.has(H.id))break;Z.push(H),V.add(H.id)}return Z}deleteOlderThan($){return this.db.all(`DELETE FROM observations
|
|
243
244
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
244
245
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
245
|
-
RETURNING id`,[
|
|
246
|
+
RETURNING id`,[$]).length}deleteEmbeddingsForObservations($){if($.length===0)return;let J=$.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${J})`,$)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${J})`,$)}mapRow($){return{id:$.id,sessionId:$.session_id,scope:$.scope??"project",type:$.type,title:$.title,subtitle:$.subtitle,facts:JSON.parse($.facts),narrative:$.narrative,concepts:JSON.parse($.concepts),filesRead:JSON.parse($.files_read),filesModified:JSON.parse($.files_modified),rawToolOutput:$.raw_tool_output,toolName:$.tool_name,createdAt:$.created_at,tokenCount:$.token_count,discoveryTokens:$.discovery_tokens??0,importance:$.importance??3,revisionOf:$.revision_of??null,deletedAt:$.deleted_at??null,supersededBy:$.superseded_by??null,supersededAt:$.superseded_at??null}}}import{randomUUID as yJ}from"crypto";class R${db;constructor($){this.db=$}create($){let J=yJ(),V=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
|
|
246
247
|
(id, session_id, tool_name, tool_output, call_id, created_at)
|
|
247
|
-
VALUES (?, ?, ?, ?, ?, ?)`,[
|
|
248
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[J,$.sessionId,$.toolName,$.toolOutput,$.callId,V]),{...$,id:J,createdAt:V,status:"pending",retryCount:0,error:null}}getPending($=10){return this.db.all("SELECT * FROM pending_messages WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?",[$]).map((J)=>this.mapRow(J))}getByStatus($){return this.db.all("SELECT * FROM pending_messages WHERE status = ? ORDER BY created_at ASC",[$]).map((J)=>this.mapRow(J))}markProcessing($){this.db.run("UPDATE pending_messages SET status = 'processing' WHERE id = ?",[$])}markCompleted($){this.db.run("UPDATE pending_messages SET status = 'completed' WHERE id = ?",[$])}markFailed($,J){this.db.run("UPDATE pending_messages SET status = 'failed', error = ?, retry_count = retry_count + 1 WHERE id = ?",[J,$])}resetStale($=5){return this.db.all(`UPDATE pending_messages SET status = 'pending'
|
|
248
249
|
WHERE status = 'processing'
|
|
249
250
|
AND created_at < datetime('now', ? || ' minutes')
|
|
250
|
-
RETURNING id`,[`-${
|
|
251
|
+
RETURNING id`,[`-${$}`]).length}deleteCompletedOlderThan($){return this.db.all(`DELETE FROM pending_messages
|
|
251
252
|
WHERE status = 'completed'
|
|
252
253
|
AND created_at < datetime('now', '-' || ? || ' days')
|
|
253
|
-
RETURNING id`,[
|
|
254
|
+
RETURNING id`,[$]).length}mapRow($){return{id:$.id,sessionId:$.session_id,toolName:$.tool_name,toolOutput:$.tool_output,callId:$.call_id,createdAt:$.created_at,status:$.status,retryCount:$.retry_count,error:$.error??null}}}var OJ=[{version:1,name:"create-schema",up:`
|
|
254
255
|
-- Sessions table
|
|
255
256
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
256
257
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -544,22 +545,22 @@ Respond with EXACTLY this XML format:
|
|
|
544
545
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
545
546
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
546
547
|
END;
|
|
547
|
-
`}];function
|
|
548
|
+
`}];function q1($,J){if($.migrate(OJ),J?.hasVectorExtension&&J?.embeddingDimension&&J.embeddingDimension>0)EJ($,J.embeddingDimension)}function EJ($,J){if($.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let Z=$.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(Z&&Number(Z.value)!==J){console.warn(`[open-mem] vec0 table exists with dimension ${Z.value}, but config specifies ${J}. Drop observation_embeddings to re-create with new dimension.`);return}}else $.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
548
549
|
observation_id TEXT PRIMARY KEY,
|
|
549
|
-
embedding float[${
|
|
550
|
-
)`)
|
|
551
|
-
VALUES (?, ?, ?, 'active')`,[
|
|
550
|
+
embedding float[${J}] distance_metric=cosine
|
|
551
|
+
)`);$.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(J)])}class C${db;constructor($){this.db=$}create($,J){let V=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
|
|
552
|
+
VALUES (?, ?, ?, 'active')`,[$,J,V]),this.getById($)}getOrCreate($,J){let V=this.getById($);if(V)return V;return this.create($,J)}getById($){let J=this.db.get("SELECT * FROM sessions WHERE id = ?",[$]);return J?this.mapRow(J):null}getRecent($,J=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[$,J]).map((V)=>this.mapRow(V))}getAll($){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[$]).map((J)=>this.mapRow(J))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map(($)=>this.mapRow($))}updateStatus($,J){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[J,$])}markCompleted($){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[$])}incrementObservationCount($){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[$])}setSummary($,J){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[J,$])}mapRow($){return{id:$.id,projectPath:$.project_path,startedAt:$.started_at,endedAt:$.ended_at??null,status:$.status,observationCount:$.observation_count,summaryId:$.summary_id??null}}}import{randomUUID as SJ}from"crypto";class y${db;constructor($){this.db=$}create($){let J=SJ(),V=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
|
|
552
553
|
(id, session_id, summary, key_decisions, files_modified,
|
|
553
554
|
concepts, created_at, token_count,
|
|
554
555
|
request, investigated, learned, completed, next_steps)
|
|
555
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
556
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[J,$.sessionId,$.summary,JSON.stringify($.keyDecisions),JSON.stringify($.filesModified),JSON.stringify($.concepts),V,$.tokenCount,$.request??"",$.investigated??"",$.learned??"",$.completed??"",$.nextSteps??""]),{...$,id:J,createdAt:V}}importSummary($){this.db.run(`INSERT INTO session_summaries
|
|
556
557
|
(id, session_id, summary, key_decisions, files_modified,
|
|
557
558
|
concepts, created_at, token_count,
|
|
558
559
|
request, investigated, learned, completed, next_steps)
|
|
559
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
560
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[$.id,$.sessionId,$.summary,JSON.stringify($.keyDecisions),JSON.stringify($.filesModified),JSON.stringify($.concepts),$.createdAt,$.tokenCount,$.request??"",$.investigated??"",$.learned??"",$.completed??"",$.nextSteps??""])}getBySessionId($){let J=this.db.get("SELECT * FROM session_summaries WHERE session_id = ?",[$]);return J?this.mapRow(J):null}getRecent($=10){return this.db.all("SELECT * FROM session_summaries ORDER BY created_at DESC LIMIT ?",[$]).map((J)=>this.mapRow(J))}search($,J=10){return this.db.all(`SELECT ss.*
|
|
560
561
|
FROM session_summaries ss
|
|
561
562
|
JOIN summaries_fts fts ON ss._rowid = fts.rowid
|
|
562
563
|
WHERE summaries_fts MATCH ?
|
|
563
564
|
ORDER BY rank
|
|
564
|
-
LIMIT ?`,[
|
|
565
|
-
`)}function
|
|
565
|
+
LIMIT ?`,[$,J]).map((V)=>this.mapRow(V))}mapRow($){return{id:$.id,sessionId:$.session_id,summary:$.summary,keyDecisions:JSON.parse($.key_decisions),filesModified:JSON.parse($.files_modified),concepts:JSON.parse($.concepts),createdAt:$.created_at,tokenCount:$.token_count,request:$.request||void 0,investigated:$.investigated||void 0,learned:$.learned||void 0,completed:$.completed||void 0,nextSteps:$.next_steps||void 0}}}class O${config;compressor;summarizer;pendingRepo;observationRepo;sessionRepo;summaryRepo;embeddingModel;conflictEvaluator;entityExtractor;entityRepo;observer;processing=!1;timer=null;mode="in-process";onEnqueue=null;constructor($,J,V,Z,X,H,K,z=null,B=null,Y=null,Q=null,U=null){this.config=$;this.compressor=J;this.summarizer=V;this.pendingRepo=Z;this.observationRepo=X;this.sessionRepo=H;this.summaryRepo=K;this.embeddingModel=z;this.conflictEvaluator=B;this.entityExtractor=Y;this.entityRepo=Q;this.observer=U}setMode($){if(this.mode=$,$==="enqueue-only")this.stop()}getMode(){return this.mode}setOnEnqueue($){this.onEnqueue=$}enqueue($,J,V,Z){if(this.pendingRepo.create({sessionId:$,toolName:J,toolOutput:V,callId:Z}),this.observer?.onEnqueue?.({sessionId:$,toolName:J,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 $=0,J=0,V=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(V).toISOString()}),Z.length===0)return 0;for(let X of Z)try{this.pendingRepo.markProcessing(X.id);let K=await this.compressor.compress(X.toolName,X.toolOutput)??this.compressor.createFallbackObservation(X.toolName,X.toolOutput),z=!1,B=null;if(this.embeddingModel)try{let Q=L$({title:K.title,narrative:K.narrative,concepts:K.concepts}),U=await D$(this.embeddingModel,Q);if(U){let A=this.config.conflictResolutionEnabled&&this.conflictEvaluator,W=this.config.conflictSimilarityBandLow??0.7,M=this.config.conflictSimilarityBandHigh??0.92;if(A){let D=this.observationRepo.findSimilar(U,K.type,W,5),L=D.find((_)=>_.similarity>M);if(L)console.log(`[open-mem] Dedup: skipping duplicate of ${L.id} (similarity: ${L.similarity.toFixed(3)})`),z=!0;else{let _=D.filter((G)=>G.similarity>=W&&G.similarity<=M);if(_.length>0)try{let G=_.map((F)=>{let R=this.observationRepo.getById(F.id);return R?{id:R.id,title:R.title,narrative:R.narrative,concepts:R.concepts,type:R.type}:null}).filter((F)=>F!==null);if(G.length>0&&this.conflictEvaluator){let F=await this.conflictEvaluator.evaluate({title:K.title,narrative:K.narrative,concepts:K.concepts,type:K.type},G);if(F&&F.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${F.reason})`),z=!0;else if(F&&F.outcome==="update"&&F.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${F.supersedesId} (${F.reason})`),B=F.supersedesId}}catch{}}}else{let D=this.observationRepo.findSimilar(U,K.type,0.92,1);if(D.length>0)console.log(`[open-mem] Dedup: skipping duplicate of ${D[0].id} (similarity: ${D[0].similarity.toFixed(3)})`),z=!0}}}catch{}if(z){this.pendingRepo.markCompleted(X.id);continue}let Y=this.observationRepo.create({sessionId:X.sessionId,type:K.type,title:K.title,subtitle:K.subtitle,facts:K.facts,narrative:K.narrative,concepts:K.concepts,filesRead:K.filesRead,filesModified:K.filesModified,rawToolOutput:X.toolOutput,toolName:X.toolName,tokenCount:f(`${K.title} ${K.narrative} ${K.facts.join(" ")}`),discoveryTokens:K.discoveryTokens??f(X.toolOutput),importance:K.importance??3});if(this.embeddingModel)try{let Q=L$({title:Y.title,narrative:Y.narrative,concepts:Y.concepts}),U=await D$(this.embeddingModel,Q);if(U)this.observationRepo.setEmbedding(Y.id,U)}catch{}if(B)try{this.observationRepo.supersede(B,Y.id),console.log(`[open-mem] Superseded observation ${B} with ${Y.id}`)}catch(Q){console.error(`[open-mem] Failed to supersede ${B}:`,Q)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let Q=await this.entityExtractor.extract({title:Y.title,narrative:Y.narrative,concepts:Y.concepts,facts:Y.facts,filesRead:Y.filesRead,filesModified:Y.filesModified,type:Y.type});if(Q){let U=new Map;for(let A of Q.entities){let W=this.entityRepo.upsertEntity(A.name,A.entityType);U.set(A.name,W.id),this.entityRepo.linkObservation(W.id,Y.id)}for(let A of Q.relations){let W=U.get(A.sourceName),M=U.get(A.targetName);if(W&&M)this.entityRepo.createRelation(W,M,A.relationship,Y.id)}}}catch{}this.sessionRepo.incrementObservationCount(X.sessionId),this.pendingRepo.markCompleted(X.id),$++}catch(H){this.pendingRepo.markFailed(X.id,String(H)),J++,this.observer?.onItemFailed?.({pendingId:X.id,error:String(H),failedAt:new Date().toISOString()})}return $}finally{this.observer?.onBatchEnd?.({processed:$,failed:J,durationMs:Date.now()-V,finishedAt:new Date().toISOString()}),this.processing=!1}}async summarizeSession($){let J=this.observationRepo.getBySession($);if(!this.summarizer.shouldSummarize(J.length))return;if(this.summaryRepo.getBySessionId($))return;let Z=await this.summarizer.summarize($,J);if(!Z)return;let X=this.summaryRepo.create({sessionId:$,summary:Z.summary,keyDecisions:Z.keyDecisions,filesModified:Z.filesModified,concepts:Z.concepts,tokenCount:f(Z.summary)});this.sessionRepo.setSummary($,X.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}}}function x1($){return{start:()=>$.start(),stop:()=>{$.setOnEnqueue(null),$.stop()},setInProcess:()=>{$.setOnEnqueue(null),$.setMode("in-process"),$.start()},setEnqueueOnly:(J)=>{$.setMode("enqueue-only"),$.setOnEnqueue(J)}}}import{spawnSync as f1}from"child_process";import{dirname as kJ,resolve as I1}from"path";function TJ($){try{let J=f1("git",["rev-parse","--git-common-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(J.status!==0||!J.stdout)return null;let V=J.stdout.trim();if(V===".git")return null;let Z=f1("git",["rev-parse","--git-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(Z.status!==0||!Z.stdout)return null;let X=Z.stdout.trim(),H=I1($,V),K=I1($,X);if(H===K)return null;let z=kJ(H);if(z===H||z==="/")return null;return z}catch{return null}}function u1($){return TJ($)??$}function S$($,J){if(J)console.warn(`[open-mem] ${J}`);if($.queueRuntime.setInProcess(),$.daemonLivenessTimer)clearInterval($.daemonLivenessTimer),$.daemonLivenessTimer=null}function E$($){process.stdout.write(`${JSON.stringify($)}
|
|
566
|
+
`)}function xJ(){let{values:$}=qJ({options:{project:{type:"string",short:"p"},"http-port":{type:"string"}},strict:!1}),J=typeof $.project==="string"?$.project:process.cwd(),V=$["http-port"],Z=typeof V==="string"&&Number.parseInt(V,10)>0?Number.parseInt(V,10):void 0;return{projectDir:J,httpPort:Z}}function fJ($,J){if($==="claude-code"&&!J.platformClaudeCodeEnabled)throw Error("Claude Code adapter is disabled. Set OPEN_MEM_PLATFORM_CLAUDE_CODE=true.");if($==="cursor"&&!J.platformCursorEnabled)throw Error("Cursor adapter is disabled. Set OPEN_MEM_PLATFORM_CURSOR=true.")}function IJ($,J){let V=u1(J),Z=z1(V);fJ($,Z);let X=$==="claude-code"?"platform-worker-claude":"platform-worker-cursor",H=F1(Z.dbPath,$==="claude-code"?"claude":"cursor");a.enableExtensionSupport();let K=k1(Z.dbPath,{processRole:X});q1(K,{hasVectorExtension:K.hasVectorExtension,embeddingDimension:Z.embeddingDimension});let z=new C$(K),B=new _$(K),Y=new y$(K),Q=new R$(K),U=new m(Z),A=new Q$(Z),W=Z.provider!=="bedrock",M=Z.compressionEnabled&&(!W||Z.apiKey)?X1({provider:Z.provider,model:Z.model,apiKey:Z.apiKey}):null,D=Z.conflictResolutionEnabled&&(!W||Z.apiKey)?new z$({provider:Z.provider,apiKey:Z.apiKey,model:Z.model,rateLimitingEnabled:Z.rateLimitingEnabled}):null,L=Z.entityExtractionEnabled&&(!W||Z.apiKey)?new B$({provider:Z.provider,apiKey:Z.apiKey,model:Z.model,rateLimitingEnabled:Z.rateLimitingEnabled}):null,_=new M$(K),G=new O$(Z,U,A,Q,B,z,Y,M,D,L,_),F=x1(G),R=$==="claude-code"?f$():u$(),e=new H$({adapter:R,queue:G,sessions:z,observations:B,pendingMessages:Q,projectPath:V,config:Z}),y={db:K,queue:G,queueRuntime:F,runtime:e,platform:$,projectPath:V,daemonManager:null,daemonLivenessTimer:null,daemonConfigured:Z.daemonEnabled,workerPidPath:H};if(Z.daemonEnabled)if(y.daemonManager=new N$({dbPath:Z.dbPath,projectPath:V,daemonScript:""}),y.daemonManager.getStatus().running)F.setEnqueueOnly(()=>{let k$=y.daemonManager?.signal("PROCESS_NOW");if(!k$?.ok)console.warn(`[open-mem] Daemon signal failed (${k$?.state??"no-daemon"}), falling back to in-process processing`),S$(y)}),y.daemonLivenessTimer=setInterval(()=>{if(!y.daemonManager||!y.daemonManager.getStatus().running)console.warn("[open-mem] Daemon died, falling back to in-process processing"),S$(y)},30000);else F.setInProcess();else F.setInProcess();return y}function w1($,J){let V=$.queue.getStats(),Z=$.daemonManager?.getStatus()??null;return{id:J,ok:!0,code:"OK",status:{platform:$.platform,projectPath:$.projectPath,queue:{mode:$.queue.getMode(),running:$.queue.isRunning,processing:V.processing,pending:V.pending},daemon:{enabled:$.daemonConfigured,running:Z?.running??!1,pid:Z?.pid??null}}}}function P1($){if(!$||typeof $!=="object"||Array.isArray($))return{command:"event",payload:$};let J=$,V=typeof J.command==="string"&&(J.command==="event"||J.command==="flush"||J.command==="health"||J.command==="shutdown")?J.command:void 0,Z=typeof J.id==="string"||typeof J.id==="number"?J.id:void 0;if(!V)return{command:"event",payload:$,id:Z};return{id:Z,command:V,payload:"payload"in J?J.payload:void 0}}async function v1($){let J=xJ(),V=IJ($,J.projectDir);W1(V.workerPidPath);let Z=!1,X=()=>{A$(V.workerPidPath,process.pid)},H=async()=>{if(Z)return;Z=!0;try{await V.queue.processBatch()}catch{}try{if(V.daemonLivenessTimer)clearInterval(V.daemonLivenessTimer),V.daemonLivenessTimer=null;V.queueRuntime.stop(),V.db.close()}finally{X(),process.exit(0)}},K=async(Y)=>{let Q=Y.command??"event";if(Q==="health")return w1(V,Y.id);if(Q==="flush"){if(V.queue.getMode()==="enqueue-only"&&V.daemonManager){let M=V.daemonManager.signal("PROCESS_NOW");if(!M.ok)S$(V,`Daemon signal failed (${M.state}), falling back to in-process processing`);else return{id:Y.id,ok:!0,code:"ENQUEUED",message:"Daemon signaled; flush is asynchronous in enqueue-only mode"}}let W=await V.queue.processBatch();return{id:Y.id,ok:!0,code:"OK",processed:W}}if(Q==="shutdown")return{id:Y.id,ok:!0,code:"OK",message:"shutting down"};if(!await V.runtime.ingestRaw(Y.payload))return{id:Y.id,ok:!1,code:"UNSUPPORTED_EVENT",message:"Payload did not match adapter event schema"};return{id:Y.id,ok:!0,code:"OK",ingested:!0}};if(J.httpPort)T$("127.0.0.1","Platform worker HTTP server"),Bun.serve({port:J.httpPort,hostname:"127.0.0.1",idleTimeout:0,fetch:async(Q)=>{if(Q.method==="GET"&&new URL(Q.url).pathname==="/v1/health")return Response.json(w1(V));if(Q.method==="POST"&&new URL(Q.url).pathname==="/v1/events"){let U;try{U=await Q.json()}catch{return Response.json({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"},{status:400})}let A=P1(U);try{let W=await K(A);if((A.command??"event")==="shutdown")setTimeout(()=>{H()},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",()=>{H()}),process.on("SIGTERM",()=>{H()});let z=Promise.resolve(),B=jJ({input:process.stdin,terminal:!1});B.on("line",(Y)=>{let Q=Y.trim();if(!Q)return;z=z.then(async()=>{let U;try{U=JSON.parse(Q)}catch{E$({ok:!1,code:"INVALID_JSON",message:"Invalid JSON payload"});return}try{let A=P1(U),W=await K(A);if(E$(W),(A.command??"event")==="shutdown")await H()}catch(A){E$({ok:!1,code:"INGESTION_FAILED",message:String(A)})}})}),B.on("close",()=>{z.finally(()=>H())})}v1("cursor");
|