open-mem 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +73 -565
  3. package/dist/adapters/http/loopback.d.ts +3 -0
  4. package/dist/adapters/http/loopback.d.ts.map +1 -0
  5. package/dist/adapters/http/server.d.ts.map +1 -1
  6. package/dist/adapters/mcp/server.d.ts +0 -2
  7. package/dist/adapters/mcp/server.d.ts.map +1 -1
  8. package/dist/adapters/opencode/tools.d.ts.map +1 -1
  9. package/dist/ai/fallback-policy.d.ts +18 -0
  10. package/dist/ai/fallback-policy.d.ts.map +1 -0
  11. package/dist/ai/fallback.d.ts +3 -1
  12. package/dist/ai/fallback.d.ts.map +1 -1
  13. package/dist/ai/provider.d.ts +2 -1
  14. package/dist/ai/provider.d.ts.map +1 -1
  15. package/dist/claude-code.js +87 -87
  16. package/dist/config/store.d.ts.map +1 -1
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/contracts/api.d.ts +2 -120
  19. package/dist/contracts/api.d.ts.map +1 -1
  20. package/dist/contracts/schemas.d.ts +134 -0
  21. package/dist/contracts/schemas.d.ts.map +1 -0
  22. package/dist/cursor.js +87 -87
  23. package/dist/daemon.js +70 -70
  24. package/dist/db/observations.d.ts.map +1 -1
  25. package/dist/doctor.d.ts +3 -0
  26. package/dist/doctor.d.ts.map +1 -0
  27. package/dist/doctor.js +5 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +122 -122
  30. package/dist/maintenance.js +43 -43
  31. package/dist/mcp.js +73 -73
  32. package/dist/modes/loader.d.ts.map +1 -1
  33. package/dist/modes/resolver.d.ts +21 -0
  34. package/dist/modes/resolver.d.ts.map +1 -0
  35. package/dist/platform-worker.d.ts.map +1 -1
  36. package/dist/search/orchestrator.d.ts +4 -13
  37. package/dist/search/orchestrator.d.ts.map +1 -1
  38. package/dist/search/registry.d.ts +19 -0
  39. package/dist/search/registry.d.ts.map +1 -0
  40. package/dist/search/strategies/filter-only.d.ts +4 -0
  41. package/dist/search/strategies/filter-only.d.ts.map +1 -0
  42. package/dist/search/strategies/hybrid.d.ts +3 -0
  43. package/dist/search/strategies/hybrid.d.ts.map +1 -0
  44. package/dist/search/strategies/semantic.d.ts +4 -0
  45. package/dist/search/strategies/semantic.d.ts.map +1 -0
  46. package/dist/search/strategies/types.d.ts +22 -0
  47. package/dist/search/strategies/types.d.ts.map +1 -0
  48. package/dist/services/readiness.d.ts +26 -0
  49. package/dist/services/readiness.d.ts.map +1 -0
  50. package/dist/services/setup-diagnostics.d.ts +23 -0
  51. package/dist/services/setup-diagnostics.d.ts.map +1 -0
  52. package/dist/types.d.ts +3 -1
  53. package/dist/types.d.ts.map +1 -1
  54. package/package.json +8 -9
package/dist/daemon.js CHANGED
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- var A=import.meta.require;import{parseArgs as MX}from"util";import{generateText as pJ}from"ai";function L(J){if(typeof J!=="object"||J===null)return!1;let X=J,$=X.status;if($===429||$===500||$===503)return!0;let Q=X.error;if(typeof Q==="object"&&Q!==null&&Q.type==="overloaded_error")return!0;return!1}function w(J){if(J&&typeof J==="object"){let X=J.status;if(typeof X==="number")return X===400||X===401||X===403}return!1}function R(J){return new Promise((X)=>setTimeout(X,J))}var hJ=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function z(J,X){let $=new RegExp(`<${X}[^>]*>([\\s\\S]*?)</${X}>`,"i"),Q=J.match($);return Q?Q[1].trim():""}function M(J,X){let $=new RegExp(`<${X}[^>]*>([\\s\\S]*?)</${X}>`,"gi"),Q=[];for(let Z of J.matchAll($)){let H=Z[1].trim();if(H)Q.push(H)}return Q}function $J(J){let X=z(J,"observation");if(!X)return null;let $=z(X,"type").toLowerCase(),Q=hJ.has($)?$:"discovery",Z=z(X,"title")||"Untitled observation",H=z(X,"subtitle"),Y=z(X,"narrative"),V=M(z(X,"facts"),"fact"),W=M(z(X,"concepts"),"concept"),K=M(z(X,"files_read"),"file"),B=M(z(X,"files_modified"),"file"),U=z(X,"importance"),_=Number.parseInt(U,10),F=Number.isNaN(_)?3:Math.max(1,Math.min(5,_));return{type:Q,title:Z,subtitle:H,facts:V,narrative:Y,concepts:W,filesRead:K,filesModified:B,importance:F}}function QJ(J){let X=z(J,"session_summary");if(!X)return null;let $=z(X,"summary")||"No summary available",Q=M(z(X,"key_decisions"),"decision"),Z=M(z(X,"files_modified"),"file"),H=M(z(X,"concepts"),"concept"),Y=z(X,"request")||void 0,V=z(X,"investigated")||void 0,W=z(X,"learned")||void 0,K=z(X,"completed")||void 0,B=z(X,"next_steps")||void 0;return{summary:$,keyDecisions:Q,filesModified:Z,concepts:H,request:Y,investigated:V,learned:W,completed:K,nextSteps:B}}var yJ=new Set(["new_fact","update","duplicate"]);function ZJ(J){let X=z(J,"evaluation");if(!X)return null;let $=z(X,"outcome").toLowerCase().trim();if(!yJ.has($))return null;let Q=$,Z=z(X,"reason");if(!Z)return null;let H=z(X,"supersedes"),Y={outcome:Q,reason:Z};if(Q==="update"&&H)Y.supersedesId=H;if(Q==="update"&&!Y.supersedesId)return null;return Y}var wJ=new Set(["technology","library","pattern","concept","file","person","project","other"]),vJ=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function HJ(J){let X=z(J,"extraction");if(!X)return null;let $=z(X,"entities"),Q=z(X,"relations"),Z=M($,"entity"),H=[];for(let W of Z){let K=z(W,"name");if(!K)continue;let B=z(W,"type").toLowerCase(),U=wJ.has(B)?B:"other";H.push({name:K,entityType:U})}let Y=M(Q,"relation"),V=[];for(let W of Y){let K=z(W,"source"),B=z(W,"target"),U=z(W,"relationship").toLowerCase();if(!K||!B||!U)continue;if(!vJ.has(U))continue;V.push({sourceName:K,targetName:B,relationship:U})}return{entities:H,relations:V}}function O(J){return Math.ceil(J.length/4)}function YJ(J,X,$,Q){let Z=$?`<session_context>
4
- ${$}
3
+ var A=import.meta.require;import{parseArgs as EV}from"util";import{generateText as n$}from"ai";function L($){if(typeof $!=="object"||$===null)return!1;let V=$,J=V.status;if(J===429||J===500||J===503)return!0;let X=V.error;if(typeof X==="object"&&X!==null&&X.type==="overloaded_error")return!0;return!1}function x($){if($&&typeof $==="object"){let V=$.status;if(typeof V==="number")return V===400||V===401||V===403}return!1}function j($){return new Promise((V)=>setTimeout(V,$))}var u$=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function z($,V){let J=new RegExp(`<${V}[^>]*>([\\s\\S]*?)</${V}>`,"i"),X=$.match(J);return X?X[1].trim():""}function N($,V){let J=new RegExp(`<${V}[^>]*>([\\s\\S]*?)</${V}>`,"gi"),X=[];for(let Q of $.matchAll(J)){let H=Q[1].trim();if(H)X.push(H)}return X}function Z$($){let V=z($,"observation");if(!V)return null;let J=z(V,"type").toLowerCase(),X=u$.has(J)?J:"discovery",Q=z(V,"title")||"Untitled observation",H=z(V,"subtitle"),Z=z(V,"narrative"),Y=N(z(V,"facts"),"fact"),W=N(z(V,"concepts"),"concept"),K=N(z(V,"files_read"),"file"),F=N(z(V,"files_modified"),"file"),G=z(V,"importance"),M=Number.parseInt(G,10),_=Number.isNaN(M)?3:Math.max(1,Math.min(5,M));return{type:X,title:Q,subtitle:H,facts:Y,narrative:Z,concepts:W,filesRead:K,filesModified:F,importance:_}}function H$($){let V=z($,"session_summary");if(!V)return null;let J=z(V,"summary")||"No summary available",X=N(z(V,"key_decisions"),"decision"),Q=N(z(V,"files_modified"),"file"),H=N(z(V,"concepts"),"concept"),Z=z(V,"request")||void 0,Y=z(V,"investigated")||void 0,W=z(V,"learned")||void 0,K=z(V,"completed")||void 0,F=z(V,"next_steps")||void 0;return{summary:J,keyDecisions:X,filesModified:Q,concepts:H,request:Z,investigated:Y,learned:W,completed:K,nextSteps:F}}var w$=new Set(["new_fact","update","duplicate"]);function Y$($){let V=z($,"evaluation");if(!V)return null;let J=z(V,"outcome").toLowerCase().trim();if(!w$.has(J))return null;let X=J,Q=z(V,"reason");if(!Q)return null;let H=z(V,"supersedes"),Z={outcome:X,reason:Q};if(X==="update"&&H)Z.supersedesId=H;if(X==="update"&&!Z.supersedesId)return null;return Z}var v$=new Set(["technology","library","pattern","concept","file","person","project","other"]),b$=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function W$($){let V=z($,"extraction");if(!V)return null;let J=z(V,"entities"),X=z(V,"relations"),Q=N(J,"entity"),H=[];for(let W of Q){let K=z(W,"name");if(!K)continue;let F=z(W,"type").toLowerCase(),G=v$.has(F)?F:"other";H.push({name:K,entityType:G})}let Z=N(X,"relation"),Y=[];for(let W of Z){let K=z(W,"source"),F=z(W,"target"),G=z(W,"relationship").toLowerCase();if(!K||!F||!G)continue;if(!b$.has(G))continue;Y.push({sourceName:K,targetName:F,relationship:G})}return{entities:H,relations:Y}}function R($){return Math.ceil($.length/4)}function K$($,V,J,X){let Q=J?`<session_context>
4
+ ${J}
5
5
  </session_context>
6
6
 
7
- `:"",H=Q?Q.observationTypes.join("|"):"decision|bugfix|feature|refactor|discovery|change",V=(Q?Q.conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"]).map((W)=>{let B={"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"}[W];return B?`- ${W}: ${B}`:`- ${W}`}).join(`
7
+ `:"",H=X?X.observationTypes.join("|"):"decision|bugfix|feature|refactor|discovery|change",Y=(X?X.conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"]).map((W)=>{let F={"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"}[W];return F?`- ${W}: ${F}`:`- ${W}`}).join(`
8
8
  `);return`<task>
9
9
  Analyze the following tool output and extract a structured observation.
10
10
  </task>
11
11
 
12
- <tool_name>${J}</tool_name>
12
+ <tool_name>${$}</tool_name>
13
13
 
14
14
  <tool_output>
15
- ${X}
15
+ ${V}
16
16
  </tool_output>
17
17
 
18
- ${Z}<instructions>
18
+ ${Q}<instructions>
19
19
  Extract a structured observation from the tool output. Determine the most appropriate type and provide a concise but informative summary.
20
20
 
21
21
  When extracting concepts, prefer established vocabulary where appropriate:
22
- ${V}
22
+ ${Y}
23
23
  You may also use any domain-specific concepts relevant to the observation.
24
24
 
25
25
  Respond with EXACTLY this XML format:
@@ -44,18 +44,18 @@ Respond with EXACTLY this XML format:
44
44
  <file>path/to/file/modified</file>
45
45
  </files_modified>
46
46
  </observation>
47
- </instructions>`}function VJ(J,X){let $=J.map((Q,Z)=>` <obs index="${Z+1}" type="${Q.type}">
48
- <title>${Q.title}</title>
49
- <narrative>${Q.narrative}</narrative>
47
+ </instructions>`}function z$($,V){let J=$.map((X,Q)=>` <obs index="${Q+1}" type="${X.type}">
48
+ <title>${X.title}</title>
49
+ <narrative>${X.narrative}</narrative>
50
50
  </obs>`).join(`
51
51
  `);return`<task>
52
52
  Summarize the following coding session based on its observations.
53
53
  </task>
54
54
 
55
- <session_id>${X}</session_id>
55
+ <session_id>${V}</session_id>
56
56
 
57
57
  <observations>
58
- ${$}
58
+ ${J}
59
59
  </observations>
60
60
 
61
61
  <instructions>
@@ -79,21 +79,21 @@ Respond with EXACTLY this XML format:
79
79
  <concept>key-concept</concept>
80
80
  </concepts>
81
81
  </session_summary>
82
- </instructions>`}function WJ(J,X){let $=X.map((Q)=>` <candidate id="${Q.id}">
83
- <title>${Q.title}</title>
84
- <narrative>${Q.narrative}</narrative>
85
- <concepts>${Q.concepts.join(", ")}</concepts>
86
- <type>${Q.type}</type>
82
+ </instructions>`}function B$($,V){let J=V.map((X)=>` <candidate id="${X.id}">
83
+ <title>${X.title}</title>
84
+ <narrative>${X.narrative}</narrative>
85
+ <concepts>${X.concepts.join(", ")}</concepts>
86
+ <type>${X.type}</type>
87
87
  </candidate>`).join(`
88
88
  `);return`<conflict_evaluation>
89
89
  <new_observation>
90
- <title>${J.title}</title>
91
- <narrative>${J.narrative}</narrative>
92
- <concepts>${J.concepts.join(", ")}</concepts>
93
- <type>${J.type}</type>
90
+ <title>${$.title}</title>
91
+ <narrative>${$.narrative}</narrative>
92
+ <concepts>${$.concepts.join(", ")}</concepts>
93
+ <type>${$.type}</type>
94
94
  </new_observation>
95
95
  <existing_candidates>
96
- ${$}
96
+ ${J}
97
97
  </existing_candidates>
98
98
  <instructions>
99
99
  Evaluate whether the new observation represents:
@@ -108,22 +108,22 @@ Respond with EXACTLY this XML format:
108
108
  <reason>Brief explanation</reason>
109
109
  </evaluation>
110
110
  </instructions>
111
- </conflict_evaluation>`}function KJ(J,X){let $=[...J.filesRead,...J.filesModified],Q=X?X.entityTypes.join(", "):"technology, library, pattern, concept, file, person, project, other",Z=X?X.relationshipTypes.join(", "):"uses, depends_on, implements, extends, related_to, replaces, configures";return`<entity_extraction>
111
+ </conflict_evaluation>`}function F$($,V){let J=[...$.filesRead,...$.filesModified],X=V?V.entityTypes.join(", "):"technology, library, pattern, concept, file, person, project, other",Q=V?V.relationshipTypes.join(", "):"uses, depends_on, implements, extends, related_to, replaces, configures";return`<entity_extraction>
112
112
  <observation>
113
- <title>${J.title}</title>
114
- <type>${J.type}</type>
115
- <narrative>${J.narrative}</narrative>
116
- <facts>${J.facts.join(`
113
+ <title>${$.title}</title>
114
+ <type>${$.type}</type>
115
+ <narrative>${$.narrative}</narrative>
116
+ <facts>${$.facts.join(`
117
117
  `)}</facts>
118
- <files>${$.join(`
118
+ <files>${J.join(`
119
119
  `)}</files>
120
- <concepts>${J.concepts.join(", ")}</concepts>
120
+ <concepts>${$.concepts.join(", ")}</concepts>
121
121
  </observation>
122
122
  <instructions>
123
123
  Extract entities and relationships from this observation.
124
124
 
125
- Entity types: ${Q}
126
- Relationship types: ${Z}
125
+ Entity types: ${X}
126
+ Relationship types: ${Q}
127
127
 
128
128
  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.
129
129
  Respond with EXACTLY this XML format:
@@ -137,102 +137,102 @@ Respond with EXACTLY this XML format:
137
137
  </relations>
138
138
  </extraction>
139
139
  </instructions>
140
- </entity_extraction>`}class v{specificationVersion;provider;modelId;supportedUrls;providers;constructor(J){if(J.length===0)throw Error("At least one provider required");let X=J[0].model;this.specificationVersion=X.specificationVersion,this.provider=X.provider,this.modelId=X.modelId,this.supportedUrls=X.supportedUrls,this.providers=J}async doGenerate(J){let X;for(let $=0;$<this.providers.length;$++){let Q=this.providers[$];try{return await Q.model.doGenerate(J)}catch(Z){if(X=Z,w(Z))throw Z;if(L(Z)&&$<this.providers.length-1){let H=this.providers[$+1],Y=Z.status??"unknown";console.error(`[open-mem] Provider ${Q.name} failed (${Y}), falling over to ${H.name}`);continue}throw Z}}throw X}async doStream(J){let X;for(let $=0;$<this.providers.length;$++){let Q=this.providers[$];try{return await Q.model.doStream(J)}catch(Z){if(X=Z,w(Z))throw Z;if(L(Z)&&$<this.providers.length-1){let H=this.providers[$+1],Y=Z.status??"unknown";console.error(`[open-mem] Provider ${Q.name} failed (${Y}), falling over to ${H.name}`);continue}throw Z}}throw X}}var fJ={"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 uJ(J){if(J.includes("."))return J;return fJ[J]||`us.anthropic.${J}-v1:0`}function zJ(J){switch(J.provider){case"anthropic":{let{createAnthropic:X}=A("@ai-sdk/anthropic");return X({apiKey:J.apiKey})(J.model)}case"bedrock":{let{createAmazonBedrock:X}=A("@ai-sdk/amazon-bedrock");return X()(uJ(J.model))}case"openai":{let{createOpenAI:X}=A("@ai-sdk/openai");return X({apiKey:J.apiKey})(J.model)}case"google":{let{createGoogleGenerativeAI:X}=A("@ai-sdk/google");return X({apiKey:J.apiKey})(J.model)}case"openrouter":{let{createOpenRouter:X}=A("@openrouter/ai-sdk-provider");return X({apiKey:J.apiKey})(J.model)}default:throw Error(`Unknown provider: ${J.provider}. Supported: anthropic, bedrock, openai, google, openrouter`)}}function GJ(J){try{switch(J.provider){case"google":{let{createGoogleGenerativeAI:X}=A("@ai-sdk/google");return X({apiKey:J.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:X}=A("@ai-sdk/openai");return X({apiKey:J.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:X}=A("@ai-sdk/amazon-bedrock");return X().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;case"openrouter":return null;default:return null}}catch{return null}}var bJ={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 gJ(J){switch(J){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 S(J){if(!J.fallbackProviders||J.fallbackProviders.length===0)return[];return J.fallbackProviders.map((X)=>({provider:X,model:bJ[X]??"gemini-2.5-flash-lite",apiKey:gJ(X)}))}function j(J,X=[]){let $=zJ(J);if(X.length===0)return $;let Q=[{name:J.provider,model:$},...X.map((Z)=>({name:Z.provider,model:zJ(Z)}))];return new v(Q)}var mJ={"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},BJ=0;async function D(J,X){if(!X)return;let $=mJ[J]||5,Q=Math.ceil(60000/$)+100,H=Date.now()-BJ;if(H<Q){let Y=Q-H;await new Promise((V)=>setTimeout(V,Y))}BJ=Date.now()}class x{model;config;_generate=pJ;constructor(J){this.config=J,this.model=null;let X=J.provider!=="bedrock";if(J.compressionEnabled&&(!X||J.apiKey))try{this.model=j({provider:J.provider,model:J.model,apiKey:J.apiKey},S(J))}catch{}}static MAX_INPUT_LENGTH=50000;async compress(J,X,$){if(!this.config.compressionEnabled||!this.model)return null;if(X.length<this.config.minOutputLength)return null;let Q=O(X),Z=X.length>x.MAX_INPUT_LENGTH?`${X.substring(0,x.MAX_INPUT_LENGTH)}
140
+ </entity_extraction>`}class v{shouldFailover($){let{error:V,attemptIndex:J,totalProviders:X}=$;if(x(V))return!1;if(J>=X-1)return!1;return L(V)}onFailover($){let V=$.error?.status??"unknown";if(!$.nextProvider)return;console.error(`[open-mem] Provider ${$.provider} failed (${V}), falling over to ${$.nextProvider}`)}}class b{specificationVersion;provider;modelId;supportedUrls;providers;policy;constructor($,V=new v){if($.length===0)throw Error("At least one provider required");let J=$[0].model;this.specificationVersion=J.specificationVersion,this.provider=J.provider,this.modelId=J.modelId,this.supportedUrls=J.supportedUrls,this.providers=$,this.policy=V}async doGenerate($){let V;for(let J=0;J<this.providers.length;J++){let X=this.providers[J];try{return this.policy.onAttempt?.({error:null,provider:X.name,nextProvider:this.providers[J+1]?.name,attemptIndex:J,totalProviders:this.providers.length}),await X.model.doGenerate($)}catch(Q){if(V=Q,x(Q))throw Q;let H=this.providers[J+1]?.name,Z={error:Q,provider:X.name,nextProvider:H,attemptIndex:J,totalProviders:this.providers.length};if(this.policy.shouldFailover(Z)){this.policy.onFailover(Z);continue}throw this.policy.onFinalFailure?.(Z),Q}}throw V}async doStream($){let V;for(let J=0;J<this.providers.length;J++){let X=this.providers[J];try{return this.policy.onAttempt?.({error:null,provider:X.name,nextProvider:this.providers[J+1]?.name,attemptIndex:J,totalProviders:this.providers.length}),await X.model.doStream($)}catch(Q){if(V=Q,x(Q))throw Q;let H=this.providers[J+1]?.name,Z={error:Q,provider:X.name,nextProvider:H,attemptIndex:J,totalProviders:this.providers.length};if(this.policy.shouldFailover(Z)){this.policy.onFailover(Z);continue}throw this.policy.onFinalFailure?.(Z),Q}}throw V}}var g$={"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 p$($){if($.includes("."))return $;return g$[$]||`us.anthropic.${$}-v1:0`}function G$($){switch($.provider){case"anthropic":{let{createAnthropic:V}=A("@ai-sdk/anthropic");return V({apiKey:$.apiKey})($.model)}case"bedrock":{let{createAmazonBedrock:V}=A("@ai-sdk/amazon-bedrock");return V()(p$($.model))}case"openai":{let{createOpenAI:V}=A("@ai-sdk/openai");return V({apiKey:$.apiKey})($.model)}case"google":{let{createGoogleGenerativeAI:V}=A("@ai-sdk/google");return V({apiKey:$.apiKey})($.model)}case"openrouter":{let{createOpenRouter:V}=A("@openrouter/ai-sdk-provider");return V({apiKey:$.apiKey})($.model)}default:throw Error(`Unknown provider: ${$.provider}. Supported: anthropic, bedrock, openai, google, openrouter`)}}function U$($){try{switch($.provider){case"google":{let{createGoogleGenerativeAI:V}=A("@ai-sdk/google");return V({apiKey:$.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:V}=A("@ai-sdk/openai");return V({apiKey:$.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:V}=A("@ai-sdk/amazon-bedrock");return V().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;case"openrouter":return null;default:return null}}catch{return null}}var l$={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 m$($){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 S($){if(!$.fallbackProviders||$.fallbackProviders.length===0)return[];return $.fallbackProviders.map((V)=>({provider:V,model:l$[V]??"gemini-2.5-flash-lite",apiKey:m$(V)}))}function D($,V=[],J){let X=G$($);if(V.length===0)return X;let Q=[{name:$.provider,model:X},...V.map((H)=>({name:H.provider,model:G$(H)}))];return new b(Q,J)}var c$={"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},M$=0;async function C($,V){if(!V)return;let J=c$[$]||5,X=Math.ceil(60000/J)+100,H=Date.now()-M$;if(H<X){let Z=X-H;await new Promise((Y)=>setTimeout(Y,Z))}M$=Date.now()}class I{model;config;_generate=n$;constructor($){this.config=$,this.model=null;let V=$.provider!=="bedrock";if($.compressionEnabled&&(!V||$.apiKey))try{this.model=D({provider:$.provider,model:$.model,apiKey:$.apiKey},S($))}catch{}}static MAX_INPUT_LENGTH=50000;async compress($,V,J){if(!this.config.compressionEnabled||!this.model)return null;if(V.length<this.config.minOutputLength)return null;let X=R(V),Q=V.length>I.MAX_INPUT_LENGTH?`${V.substring(0,I.MAX_INPUT_LENGTH)}
141
141
 
142
- [... truncated ...]`:X,H=YJ(J,Z,$),Y=2;for(let V=0;V<=Y;V++)try{if(this.config.provider==="google")await D(this.config.model,this.config.rateLimitingEnabled);let{text:W}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:H}),K=$J(W);if(K)K.discoveryTokens=Q;return K}catch(W){if(L(W)&&V<Y){let K=2**V*1000;await R(K);continue}return null}return null}async compressBatch(J){let X=new Map;for(let $=0;$<J.length;$++){let Q=J[$],Z=await this.compress(Q.toolName,Q.toolOutput,Q.sessionContext);if(X.set(Q.callId,Z),$<J.length-1)await R(200)}return X}createFallbackObservation(J,X){let $=dJ(X),Q=lJ[J]??"discovery";return{type:Q,title:`${J} execution`,subtitle:X.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${J} was executed. Output length: ${X.length} chars.`,concepts:[],filesRead:Q==="discovery"?$:[],filesModified:Q==="change"?$:[],discoveryTokens:O(X),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 lJ={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},cJ=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function dJ(J){let X=[];for(let $ of J.matchAll(cJ))X.push($[1]);return[...new Set(X)]}import{generateText as nJ}from"ai";class f{model;config;_generate=nJ;constructor(J){if(this.config=J,this.model=null,J.provider==="bedrock"||J.apiKey)try{this.model=j({provider:J.provider,model:J.model,apiKey:J.apiKey},S(J))}catch{}}async evaluate(J,X){if(!this.model||X.length===0)return null;let $=WJ(J,X),Q=2;for(let Z=0;Z<=Q;Z++)try{if(this.config.provider==="google")await D(this.config.model,this.config.rateLimitingEnabled);let{text:H}=await this._generate({model:this.model,maxOutputTokens:512,prompt:$});return ZJ(H)}catch(H){if(L(H)&&Z<Q){let Y=2**Z*1000;await R(Y);continue}return null}return null}}import{generateText as sJ}from"ai";class u{model;config;_generate=sJ;constructor(J){if(this.config=J,this.model=null,J.provider==="bedrock"||J.apiKey)try{this.model=j({provider:J.provider,model:J.model,apiKey:J.apiKey},S(J))}catch{}}async extract(J){if(!this.model)return null;let X=KJ(J),$=2;for(let Q=0;Q<=$;Q++)try{if(this.config.provider==="google")await D(this.config.model,this.config.rateLimitingEnabled);let{text:Z}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:X});return HJ(Z)}catch(Z){if(L(Z)&&Q<$){let H=2**Q*1000;await R(H);continue}return null}return null}}import{generateText as iJ}from"ai";class b{model;config;_generate=iJ;constructor(J){this.config=J,this.model=null;let X=J.provider!=="bedrock";if(J.compressionEnabled&&(!X||J.apiKey))try{this.model=j({provider:J.provider,model:J.model,apiKey:J.apiKey},S(J))}catch{}}async summarize(J,X){if(X.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(X);let $=VJ(X.map((Q)=>({type:Q.type,title:Q.title,narrative:Q.narrative})),J);try{if(this.config.provider==="google")await D(this.config.model,this.config.rateLimitingEnabled);let{text:Q}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:$}),Z=QJ(Q);if(!Z)return this.createFallbackSummary(X);return Z}catch{return this.createFallbackSummary(X)}}createFallbackSummary(J){let X=new Set,$=new Set,Q=[];for(let V of J){for(let W of V.filesModified)X.add(W);for(let W of V.concepts)$.add(W);if(V.type==="decision")Q.push(V.title)}let Z=new Map;for(let V of J)Z.set(V.type,(Z.get(V.type)??0)+1);let H=Array.from(Z.entries()).map(([V,W])=>`${W} ${V}${W>1?"s":""}`).join(", "),Y=Array.from($).slice(0,5).join(", ");return{summary:`Session with ${J.length} observations: ${H}. Files modified: ${X.size}. Key concepts: ${Y}.`,keyDecisions:Q.slice(0,5),filesModified:Array.from(X),concepts:Array.from($)}}shouldSummarize(J){return J>=2}}import{existsSync as eJ,readFileSync as JX}from"fs";import{existsSync as aJ,readdirSync as rJ,readFileSync as tJ}from"fs";import{join as UJ}from"path";var g=UJ(import.meta.dir,"."),T=null;function oJ(){if(T)return T;if(T=new Map,!aJ(g))return T;for(let J of rJ(g)){if(!J.endsWith(".json"))continue;try{let X=tJ(UJ(g,J),"utf-8"),$=JSON.parse(X);if($.id&&$.observationTypes&&$.conceptVocabulary)T.set($.id,$)}catch{}}return T}function NJ(){return[...oJ().keys()].sort()}var XX={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"dispersed",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0,mode:"code"};function $X(){let J={};if(process.env.OPEN_MEM_DB_PATH)J.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)J.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)J.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)J.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")J.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")J.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)J.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((X)=>X.trim());if(process.env.OPEN_MEM_BATCH_SIZE)J.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)J.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)J.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")J.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)J.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((X)=>X.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)J.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)J.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")J.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")J.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")J.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)J.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")J.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")J.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)J.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")J.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")J.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)J.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")J.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")J.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")J.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)J.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)J.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)J.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((X)=>X.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)J.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")J.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let X=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(X))J.conflictSimilarityBandLow=X}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let X=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(X))J.conflictSimilarityBandHigh=X}if(process.env.OPEN_MEM_USER_MEMORY==="true")J.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)J.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)J.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")J.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)J.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")J.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)J.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((X)=>X.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)J.mode=process.env.OPEN_MEM_MODE;return J}function QX(J){let X=`${J}/.open-mem/config.json`;if(!eJ(X))return{};try{let $=JX(X,"utf-8"),Q=JSON.parse($);if(!Q||typeof Q!=="object"||Array.isArray(Q))return{};return Q}catch{return{}}}function ZX(J){switch(J){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function _J(J,X){let $=QX(J),Q=$X(),Z={...XX,...$,...Q,...X};if(!Z.dbPath.startsWith("/"))Z.dbPath=`${J}/${Z.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!X?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)Z.provider="google";else if(process.env.ANTHROPIC_API_KEY)Z.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)Z.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)Z.provider="openrouter"}if(!Z.apiKey)switch(Z.provider){case"google":Z.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":Z.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":Z.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":Z.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(Z.provider==="openrouter"&&Z.model==="gemini-2.5-flash-lite")Z.model="google/gemini-2.5-flash-lite";if(Z.embeddingDimension===void 0)Z.embeddingDimension=ZX(Z.provider);if(Z.mode&&!NJ().includes(Z.mode))Z.mode="code";return Z}import{existsSync as j2,mkdirSync as HX,readFileSync as D2,unlinkSync as YX,writeFileSync as VX}from"fs";function FJ(J){let X=J.lastIndexOf("/");if(X>0){let $=J.substring(0,X);HX($,{recursive:!0})}VX(J,String(process.pid),"utf-8")}function LJ(J){try{YX(J)}catch{}}function MJ(J){let X=J.lastIndexOf("/");if(X>=0)return`${J.substring(0,X)}/worker.pid`;return"worker.pid"}class m{queueProcessor;pollIntervalMs;timer=null;lastActiveAt=Date.now();processing=!1;constructor(J){this.queueProcessor=J.queueProcessor,this.pollIntervalMs=J.pollIntervalMs}start(){if(this.timer)return;this.lastActiveAt=Date.now(),this.timer=setInterval(async()=>{if(this.processing)return;this.processing=!0;try{if(await this.queueProcessor.processBatch()>0)this.lastActiveAt=Date.now()}catch{}finally{this.processing=!1}},this.pollIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get idleMs(){return Date.now()-this.lastActiveAt}get shouldAutoExit(){return this.idleMs>=60000&&!process.send}handleMessage(J){if(J==="SHUTDOWN")this.stop();else if(J==="PROCESS_NOW"){if(!this.processing)this.processing=!0,this.queueProcessor.processBatch().then((X)=>{if(X>0)this.lastActiveAt=Date.now()}).catch(()=>{}).finally(()=>{this.processing=!1})}}}import{Database as AJ}from"bun:sqlite";import{existsSync as p,mkdirSync as WX,unlinkSync as SJ}from"fs";import*as jJ from"sqlite-vec";class h{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let J=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let X of J)try{if(p(X))return AJ.setCustomSQLite(X),!0}catch{return!1}return!1}constructor(J){this.dbPath=J,this.db=this.open(J),this.configure()}open(J){let X=J.lastIndexOf("/");if(X>0){let $=J.substring(0,X);WX($,{recursive:!0})}return new AJ(J,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(J){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",J.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(X){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",X.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($){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",$.message),J}}}}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{jJ.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let J of["-wal","-shm"]){let X=this.dbPath+J;try{if(p(X))SJ(X)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(p(this.dbPath))SJ(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
142
+ [... truncated ...]`:V,H=K$($,Q,J),Z=2;for(let Y=0;Y<=Z;Y++)try{if(this.config.provider==="google")await C(this.config.model,this.config.rateLimitingEnabled);let{text:W}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:H}),K=Z$(W);if(K)K.discoveryTokens=X;return K}catch(W){if(L(W)&&Y<Z){let K=2**Y*1000;await j(K);continue}return null}return null}async compressBatch($){let V=new Map;for(let J=0;J<$.length;J++){let X=$[J],Q=await this.compress(X.toolName,X.toolOutput,X.sessionContext);if(V.set(X.callId,Q),J<$.length-1)await j(200)}return V}createFallbackObservation($,V){let J=i$(V),X=d$[$]??"discovery";return{type:X,title:`${$} execution`,subtitle:V.substring(0,100).replace(/\n/g," "),facts:[],narrative:`Tool ${$} was executed. Output length: ${V.length} chars.`,concepts:[],filesRead:X==="discovery"?J:[],filesModified:X==="change"?J:[],discoveryTokens:R(V),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 d$={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},s$=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function i$($){let V=[];for(let J of $.matchAll(s$))V.push(J[1]);return[...new Set(V)]}import{generateText as r$}from"ai";class g{model;config;_generate=r$;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=D({provider:$.provider,model:$.model,apiKey:$.apiKey},S($))}catch{}}async evaluate($,V){if(!this.model||V.length===0)return null;let J=B$($,V),X=2;for(let Q=0;Q<=X;Q++)try{if(this.config.provider==="google")await C(this.config.model,this.config.rateLimitingEnabled);let{text:H}=await this._generate({model:this.model,maxOutputTokens:512,prompt:J});return Y$(H)}catch(H){if(L(H)&&Q<X){let Z=2**Q*1000;await j(Z);continue}return null}return null}}import{generateText as t$}from"ai";class p{model;config;_generate=t$;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=D({provider:$.provider,model:$.model,apiKey:$.apiKey},S($))}catch{}}async extract($){if(!this.model)return null;let V=F$($),J=2;for(let X=0;X<=J;X++)try{if(this.config.provider==="google")await C(this.config.model,this.config.rateLimitingEnabled);let{text:Q}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:V});return W$(Q)}catch(Q){if(L(Q)&&X<J){let H=2**X*1000;await j(H);continue}return null}return null}}import{generateText as o$}from"ai";class l{model;config;_generate=o$;constructor($){this.config=$,this.model=null;let V=$.provider!=="bedrock";if($.compressionEnabled&&(!V||$.apiKey))try{this.model=D({provider:$.provider,model:$.model,apiKey:$.apiKey},S($))}catch{}}async summarize($,V){if(V.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(V);let J=z$(V.map((X)=>({type:X.type,title:X.title,narrative:X.narrative})),$);try{if(this.config.provider==="google")await C(this.config.model,this.config.rateLimitingEnabled);let{text:X}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:J}),Q=H$(X);if(!Q)return this.createFallbackSummary(V);return Q}catch{return this.createFallbackSummary(V)}}createFallbackSummary($){let V=new Set,J=new Set,X=[];for(let Y of $){for(let W of Y.filesModified)V.add(W);for(let W of Y.concepts)J.add(W);if(Y.type==="decision")X.push(Y.title)}let Q=new Map;for(let Y of $)Q.set(Y.type,(Q.get(Y.type)??0)+1);let H=Array.from(Q.entries()).map(([Y,W])=>`${W} ${Y}${W>1?"s":""}`).join(", "),Z=Array.from(J).slice(0,5).join(", ");return{summary:`Session with ${$.length} observations: ${H}. Files modified: ${V.size}. Key concepts: ${Z}.`,keyDecisions:X.slice(0,5),filesModified:Array.from(V),concepts:Array.from(J)}}shouldSummarize($){return $>=2}}import{existsSync as WV,readFileSync as KV}from"fs";import{join as QV}from"path";import{existsSync as a$,readdirSync as e$,readFileSync as $V}from"fs";import{join as VV}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 k($){return{...$,observationTypes:[...$.observationTypes],conceptVocabulary:[...$.conceptVocabulary],entityTypes:[...$.entityTypes],relationshipTypes:[...$.relationshipTypes],promptOverrides:$.promptOverrides?{...$.promptOverrides}:void 0}}function JV($){if(!$||typeof $!=="object")return!1;let V=$,J=(Q)=>Array.isArray(Q)&&Q.every((H)=>typeof H==="string"),X=(Q)=>typeof Q==="object"&&Q!==null&&!Array.isArray(Q)&&Object.values(Q).every((H)=>typeof H==="string");return typeof V.id==="string"&&(V.extends===void 0||typeof V.extends==="string")&&(V.locale===void 0||typeof V.locale==="string")&&(V.name===void 0||typeof V.name==="string")&&(V.description===void 0||typeof V.description==="string")&&(V.observationTypes===void 0||J(V.observationTypes))&&(V.conceptVocabulary===void 0||J(V.conceptVocabulary))&&(V.entityTypes===void 0||J(V.entityTypes))&&(V.relationshipTypes===void 0||J(V.relationshipTypes))&&(V.promptOverrides===void 0||X(V.promptOverrides))}function XV($){return typeof $.name==="string"&&typeof $.description==="string"&&Array.isArray($.observationTypes)&&Array.isArray($.conceptVocabulary)&&Array.isArray($.entityTypes)&&Array.isArray($.relationshipTypes)}function _$($,V){return{...$,...V,id:V.id,name:V.name??$.name,description:V.description??$.description,observationTypes:V.observationTypes??$.observationTypes,conceptVocabulary:V.conceptVocabulary??$.conceptVocabulary,entityTypes:V.entityTypes??$.entityTypes,relationshipTypes:V.relationshipTypes??$.relationshipTypes,promptOverrides:{...$.promptOverrides??{},...V.promptOverrides??{}}}}class m{modesDir;constructor($){this.modesDir=$}loadAllRaw(){let $=new Map;if(!a$(this.modesDir))return $;for(let V of e$(this.modesDir)){if(!V.endsWith(".json"))continue;let J=VV(this.modesDir,V);try{let X=$V(J,"utf-8"),Q=JSON.parse(X);if(!JV(Q))continue;if($.has(Q.id))console.warn(`[open-mem] Duplicate mode id "${Q.id}" in ${J}; overriding previous definition.`);$.set(Q.id,Q)}catch{}}return $}resolveById($,V){let J=new Set,X=!1,Q=(Z)=>{if(J.has(Z))return X=!0,k(P);J.add(Z);let Y=V.get(Z);if(!Y)return k(P);if(!Y.extends){if(!XV(Y))return k(P);return _$(k(P),Y)}let W=Q(Y.extends);if(X)return k(P);return _$(W,Y)},H=Q($);return X?k(P):k(H)}}var ZV=QV(import.meta.dir,"."),HV=new m(ZV),f=null;function YV(){if(f)return f;return f=HV.loadAllRaw(),f}function N$(){return[...YV().keys()].sort()}var zV={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 BV(){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((V)=>V.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((V)=>V.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((V)=>V.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 V=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(V))$.conflictSimilarityBandLow=V}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let V=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(V))$.conflictSimilarityBandHigh=V}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((V)=>V.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)$.mode=process.env.OPEN_MEM_MODE;return $}function FV($){let V=`${$}/.open-mem/config.json`;if(!WV(V))return{};try{let J=KV(V,"utf-8"),X=JSON.parse(J);if(!X||typeof X!=="object"||Array.isArray(X))return{};return X}catch{return{}}}function GV($){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 A$($,V){let J=FV($),X=BV(),Q={...zV,...J,...X,...V};if(!Q.dbPath.startsWith("/"))Q.dbPath=`${$}/${Q.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!V?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)Q.provider="google";else if(process.env.ANTHROPIC_API_KEY)Q.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)Q.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)Q.provider="openrouter"}if(!Q.apiKey)switch(Q.provider){case"google":Q.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":Q.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":Q.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":Q.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(Q.provider==="openrouter"&&Q.model==="gemini-2.5-flash-lite")Q.model="google/gemini-2.5-flash-lite";if(Q.embeddingDimension===void 0)Q.embeddingDimension=GV(Q.provider);if(Q.mode&&!N$().includes(Q.mode))Q.mode="code";return Q}import{existsSync as uJ,mkdirSync as UV,readFileSync as wJ,unlinkSync as MV,writeFileSync as _V}from"fs";function L$($){let V=$.lastIndexOf("/");if(V>0){let J=$.substring(0,V);UV(J,{recursive:!0})}_V($,String(process.pid),"utf-8")}function S$($){try{MV($)}catch{}}function D$($){let V=$.lastIndexOf("/");if(V>=0)return`${$.substring(0,V)}/worker.pid`;return"worker.pid"}class c{queueProcessor;pollIntervalMs;timer=null;lastActiveAt=Date.now();processing=!1;constructor($){this.queueProcessor=$.queueProcessor,this.pollIntervalMs=$.pollIntervalMs}start(){if(this.timer)return;this.lastActiveAt=Date.now(),this.timer=setInterval(async()=>{if(this.processing)return;this.processing=!0;try{if(await this.queueProcessor.processBatch()>0)this.lastActiveAt=Date.now()}catch{}finally{this.processing=!1}},this.pollIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get idleMs(){return Date.now()-this.lastActiveAt}get shouldAutoExit(){return this.idleMs>=60000&&!process.send}handleMessage($){if($==="SHUTDOWN")this.stop();else if($==="PROCESS_NOW"){if(!this.processing)this.processing=!0,this.queueProcessor.processBatch().then((V)=>{if(V>0)this.lastActiveAt=Date.now()}).catch(()=>{}).finally(()=>{this.processing=!1})}}}import{Database as C$}from"bun:sqlite";import{existsSync as n,mkdirSync as NV,unlinkSync as O$}from"fs";import*as j$ from"sqlite-vec";class u{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let $=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let V of $)try{if(n(V))return C$.setCustomSQLite(V),!0}catch{return!1}return!1}constructor($){this.dbPath=$,this.db=this.open($),this.configure()}open($){let V=$.lastIndexOf("/");if(V>0){let J=$.substring(0,V);NV(J,{recursive:!0})}return new C$($,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch($){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",$.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(V){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",V.message);try{this.db.close()}catch{}this.deleteDatabaseFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after full database recreation");return}catch(J){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",J.message),$}}}}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{j$.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let $ of["-wal","-shm"]){let V=this.dbPath+$;try{if(n(V))O$(V)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(n(this.dbPath))O$(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
143
143
  CREATE TABLE IF NOT EXISTS _migrations (
144
144
  version INTEGER PRIMARY KEY,
145
145
  name TEXT NOT NULL,
146
146
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
147
147
  )
148
- `)}migrate(J){this.ensureMigrationTable();let X=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),$=new Set(X.map((Z)=>Z.version)),Q=J.filter((Z)=>!$.has(Z.version)).sort((Z,H)=>Z.version-H.version);for(let Z of Q)this.db.transaction(()=>{this.db.exec(Z.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:Z.version,$name:Z.name})})()}run(J,X){let $=this.db.query(J);if(X)$.run(...X);else $.run()}get(J,X){let $=this.db.query(J);return X?$.get(...X):$.get()}all(J,X){let $=this.db.query(J);return X?$.all(...X):$.all()}exec(J){this.db.exec(J)}transaction(J){return this.db.transaction(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 DJ(J){return new h(J)}import{randomUUID as EJ}from"crypto";class l{db;constructor(J){this.db=J}upsertEntity(J,X){let $=EJ(),Q=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
148
+ `)}migrate($){this.ensureMigrationTable();let V=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),J=new Set(V.map((Q)=>Q.version)),X=$.filter((Q)=>!J.has(Q.version)).sort((Q,H)=>Q.version-H.version);for(let Q of X)this.db.transaction(()=>{this.db.exec(Q.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:Q.version,$name:Q.name})})()}run($,V){let J=this.db.query($);if(V)J.run(...V);else J.run()}get($,V){let J=this.db.query($);return V?J.get(...V):J.get()}all($,V){let J=this.db.query($);return V?J.all(...V):J.all()}exec($){this.db.exec($)}transaction($){return this.db.transaction($)()}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function R$($){return new u($)}import{randomUUID as k$}from"crypto";class d{db;constructor($){this.db=$}upsertEntity($,V){let J=k$(),X=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
149
149
  VALUES (?, ?, ?, ?, ?, 1)
150
150
  ON CONFLICT(name, entity_type) DO UPDATE SET
151
151
  mention_count = mention_count + 1,
152
- last_seen_at = ?`,[$,J,X,Q,Q,Q]);let Z=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[J,X]);if(!Z)throw Error(`Failed to upsert entity: ${J} (${X})`);return this.mapEntityRow(Z)}createRelation(J,X,$,Q){let Z=EJ(),H=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
152
+ last_seen_at = ?`,[J,$,V,X,X,X]);let Q=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[$,V]);if(!Q)throw Error(`Failed to upsert entity: ${$} (${V})`);return this.mapEntityRow(Q)}createRelation($,V,J,X){let Q=k$(),H=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
153
153
  (id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
154
- VALUES (?, ?, ?, ?, ?, ?)`,[Z,J,X,$,Q,H])}catch{return null}let Y=this.db.get(`SELECT * FROM entity_relations
155
- WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[J,X,$]);return Y?this.mapRelationRow(Y):null}linkObservation(J,X){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[J,X])}findByName(J){try{return this.db.all(`SELECT e.*
154
+ VALUES (?, ?, ?, ?, ?, ?)`,[Q,$,V,J,X,H])}catch{return null}let Z=this.db.get(`SELECT * FROM entity_relations
155
+ WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[$,V,J]);return Z?this.mapRelationRow(Z):null}linkObservation($,V){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[$,V])}findByName($){try{return this.db.all(`SELECT e.*
156
156
  FROM entities e
157
157
  JOIN entities_fts fts ON e._rowid = fts.rowid
158
158
  WHERE entities_fts MATCH ?
159
- ORDER BY rank`,[J]).map(($)=>this.mapEntityRow($))}catch{return[]}}getRelationsFor(J){return this.db.all(`SELECT * FROM entity_relations
160
- WHERE source_entity_id = ? OR target_entity_id = ?`,[J,J]).map(($)=>this.mapRelationRow($))}traverseRelations(J,X=1){let $=Math.min(X,2),Q=100,Z=new Set,H=[{id:J,currentDepth:0}];Z.add(J);while(H.length>0){if(Z.size>=100)break;let Y=H.shift();if(!Y)continue;if(Y.currentDepth>=$)continue;let V=this.getRelationsFor(Y.id);for(let W of V){let K=W.sourceEntityId===Y.id?W.targetEntityId:W.sourceEntityId;if(!Z.has(K))Z.add(K),H.push({id:K,currentDepth:Y.currentDepth+1})}}return Z}getObservationsForEntity(J){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[J]).map(($)=>$.observation_id)}getById(J){let X=this.db.get("SELECT * FROM entities WHERE id = ?",[J]);return X?this.mapEntityRow(X):null}mapEntityRow(J){return{id:J.id,name:J.name,entityType:J.entity_type,firstSeenAt:J.first_seen_at,lastSeenAt:J.last_seen_at,mentionCount:J.mention_count}}mapRelationRow(J){return{id:J.id,sourceEntityId:J.source_entity_id,targetEntityId:J.target_entity_id,relationship:J.relationship,observationId:J.observation_id,createdAt:J.created_at}}}import{randomUUID as zX}from"crypto";import{embed as KX}from"ai";async function c(J,X){try{let{embedding:$}=await KX({model:J,value:X});return $}catch{return null}}function RJ(J,X){if(J.length!==X.length||J.length===0)return 0;let $=0,Q=0,Z=0;for(let Y=0;Y<J.length;Y++)$+=J[Y]*X[Y],Q+=J[Y]*J[Y],Z+=X[Y]*X[Y];let H=Math.sqrt(Q)*Math.sqrt(Z);if(H===0)return 0;return $/H}function d(J){let X=[J.title,J.narrative];if(J.concepts.length>0)X.push(J.concepts.join(", "));return X.join(`
161
- `)}function GX(J){return J.replace(/[%_\\]/g,"\\$&")}class n{db;constructor(J){this.db=J}create(J){let X=zX(),$=new Date().toISOString(),Q=J.discoveryTokens??0,Z=J.importance??3,H=J.scope??"project";return this.db.run(`INSERT INTO observations
159
+ ORDER BY rank`,[$]).map((J)=>this.mapEntityRow(J))}catch{return[]}}getRelationsFor($){return this.db.all(`SELECT * FROM entity_relations
160
+ WHERE source_entity_id = ? OR target_entity_id = ?`,[$,$]).map((J)=>this.mapRelationRow(J))}traverseRelations($,V=1){let J=Math.min(V,2),X=100,Q=new Set,H=[{id:$,currentDepth:0}];Q.add($);while(H.length>0){if(Q.size>=100)break;let Z=H.shift();if(!Z)continue;if(Z.currentDepth>=J)continue;let Y=this.getRelationsFor(Z.id);for(let W of Y){let K=W.sourceEntityId===Z.id?W.targetEntityId:W.sourceEntityId;if(!Q.has(K))Q.add(K),H.push({id:K,currentDepth:Z.currentDepth+1})}}return Q}getObservationsForEntity($){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[$]).map((J)=>J.observation_id)}getById($){let V=this.db.get("SELECT * FROM entities WHERE id = ?",[$]);return V?this.mapEntityRow(V):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 LV}from"crypto";import{embed as AV}from"ai";async function s($,V){try{let{embedding:J}=await AV({model:$,value:V});return J}catch{return null}}function E$($,V){if($.length!==V.length||$.length===0)return 0;let J=0,X=0,Q=0;for(let Z=0;Z<$.length;Z++)J+=$[Z]*V[Z],X+=$[Z]*$[Z],Q+=V[Z]*V[Z];let H=Math.sqrt(X)*Math.sqrt(Q);if(H===0)return 0;return J/H}function i($){let V=[$.title,$.narrative];if($.concepts.length>0)V.push($.concepts.join(", "));return V.join(`
161
+ `)}function SV($){return $.replace(/[%_\\]/g,"\\$&")}class r{db;constructor($){this.db=$}create($){let V=LV(),J=new Date().toISOString(),X=$.discoveryTokens??0,Q=$.importance??3,H=$.scope??"project";return this.db.run(`INSERT INTO observations
162
162
  (id, session_id, scope, type, title, subtitle, facts, narrative,
163
163
  concepts, files_read, files_modified, raw_tool_output,
164
164
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
165
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[X,J.sessionId,H,J.type,J.title,J.subtitle,JSON.stringify(J.facts),J.narrative,JSON.stringify(J.concepts),JSON.stringify(J.filesRead),JSON.stringify(J.filesModified),J.rawToolOutput,J.toolName,$,J.tokenCount,Q,Z,null,null]),{...J,id:X,scope:H,createdAt:$,discoveryTokens:Q,importance:Z,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(J){this.db.run(`INSERT INTO observations
165
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[V,$.sessionId,H,$.type,$.title,$.subtitle,JSON.stringify($.facts),$.narrative,JSON.stringify($.concepts),JSON.stringify($.filesRead),JSON.stringify($.filesModified),$.rawToolOutput,$.toolName,J,$.tokenCount,X,Q,null,null]),{...$,id:V,scope:H,createdAt:J,discoveryTokens:X,importance:Q,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation($){this.db.run(`INSERT INTO observations
166
166
  (id, session_id, scope, type, title, subtitle, facts, narrative,
167
167
  concepts, files_read, files_modified, raw_tool_output,
168
168
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
169
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[J.id,J.sessionId,J.scope??"project",J.type,J.title,J.subtitle,JSON.stringify(J.facts),J.narrative,JSON.stringify(J.concepts),JSON.stringify(J.filesRead),JSON.stringify(J.filesModified),J.rawToolOutput,J.toolName,J.createdAt,J.tokenCount,J.discoveryTokens??0,J.importance??3,J.revisionOf??null,J.deletedAt??null])}getById(J){let X=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[J]);return X?this.mapRow(X):null}getByIdIncludingArchived(J){let X=this.db.get("SELECT * FROM observations WHERE id = ?",[J]);return X?this.mapRow(X):null}getBySession(J){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",[J]).map((X)=>this.mapRow(X))}getCount(J){if(J)return this.db.get("SELECT COUNT(*) as count FROM observations WHERE session_id = ?",[J])?.count??0;return this.db.get("SELECT COUNT(*) as count FROM observations")?.count??0}getIndex(J,X=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
169
+ 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 V=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[$]);return V?this.mapRow(V):null}getByIdIncludingArchived($){let V=this.db.get("SELECT * FROM observations WHERE id = ?",[$]);return V?this.mapRow(V):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((V)=>this.mapRow(V))}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($,V=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
170
170
  FROM observations o
171
171
  JOIN sessions s ON o.session_id = s.id
172
172
  WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
173
173
  ORDER BY o.created_at DESC
174
- LIMIT ?`,[J,X]).map(($)=>({id:$.id,sessionId:$.session_id,type:$.type,title:$.title,tokenCount:$.token_count,discoveryTokens:$.discovery_tokens??0,createdAt:$.created_at,importance:$.importance??3}))}getAroundTimestamp(J,X,$,Q){let Z=X>0?this.db.all(`SELECT o.*
174
+ LIMIT ?`,[$,V]).map((J)=>({id:J.id,sessionId:J.session_id,type:J.type,title:J.title,tokenCount:J.token_count,discoveryTokens:J.discovery_tokens??0,createdAt:J.created_at,importance:J.importance??3}))}getAroundTimestamp($,V,J,X){let Q=V>0?this.db.all(`SELECT o.*
175
175
  FROM observations o
176
176
  JOIN sessions s ON o.session_id = s.id
177
177
  WHERE s.project_path = ? AND o.created_at < ?
178
178
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
179
179
  ORDER BY o.created_at DESC
180
- LIMIT ?`,[Q,J,X]).reverse():[],H=$>0?this.db.all(`SELECT o.*
180
+ LIMIT ?`,[X,$,V]).reverse():[],H=J>0?this.db.all(`SELECT o.*
181
181
  FROM observations o
182
182
  JOIN sessions s ON o.session_id = s.id
183
183
  WHERE s.project_path = ? AND o.created_at > ?
184
184
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
185
185
  ORDER BY o.created_at ASC
186
- LIMIT ?`,[Q,J,$]):[];return[...Z,...H].map((Y)=>this.mapRow(Y))}listByProject(J,X={}){let{limit:$=50,offset:Q=0,type:Z,state:H,sessionId:Y}=X,V=`SELECT o.*
186
+ LIMIT ?`,[X,$,J]):[];return[...Q,...H].map((Z)=>this.mapRow(Z))}listByProject($,V={}){let{limit:J=50,offset:X=0,type:Q,state:H,sessionId:Z}=V,Y=`SELECT o.*
187
187
  FROM observations o
188
188
  JOIN sessions s ON o.session_id = s.id
189
- WHERE s.project_path = ?`,W=[J];if(Y)V+=" AND o.session_id = ?",W.push(Y);if(Z)V+=" AND o.type = ?",W.push(Z);if(H==="current")V+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(H==="superseded")V+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(H==="tombstoned")V+=" AND o.deleted_at IS NOT NULL";else V+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return V+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",W.push($,Q),this.db.all(V,W).map((K)=>this.mapRow(K))}search(J){let X=!!J.projectPath,$=`
189
+ WHERE s.project_path = ?`,W=[$];if(Z)Y+=" AND o.session_id = ?",W.push(Z);if(Q)Y+=" AND o.type = ?",W.push(Q);if(H==="current")Y+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(H==="superseded")Y+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(H==="tombstoned")Y+=" AND o.deleted_at IS NOT NULL";else Y+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return Y+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",W.push(J,X),this.db.all(Y,W).map((K)=>this.mapRow(K))}search($){let V=!!$.projectPath,J=`
190
190
  SELECT o.*, rank
191
191
  FROM observations o
192
192
  JOIN observations_fts fts ON o._rowid = fts.rowid
193
- ${X?"JOIN sessions s ON o.session_id = s.id":""}
193
+ ${V?"JOIN sessions s ON o.session_id = s.id":""}
194
194
  WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
195
- `,Q=[J.query];if(X&&J.projectPath)$+=" AND s.project_path = ?",Q.push(J.projectPath);if(J.sessionId)$+=" AND o.session_id = ?",Q.push(J.sessionId);if(J.type)$+=" AND o.type = ?",Q.push(J.type);if(J.importanceMin!==void 0)$+=" AND o.importance >= ?",Q.push(J.importanceMin);if(J.importanceMax!==void 0)$+=" AND o.importance <= ?",Q.push(J.importanceMax);if(J.createdAfter)$+=" AND o.created_at >= ?",Q.push(J.createdAfter);if(J.createdBefore)$+=" AND o.created_at <= ?",Q.push(J.createdBefore);if(J.concepts&&J.concepts.length>0){let Z=J.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");$+=` AND (${Z.join(" OR ")})`;for(let H of J.concepts)Q.push(H)}if(J.files&&J.files.length>0){let Z=J.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
196
- OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);$+=` AND (${Z.join(" OR ")})`;for(let H of J.files){let Y=`%${GX(H)}%`;Q.push(Y,Y)}}return $+=" ORDER BY rank LIMIT ? OFFSET ?",Q.push(J.limit??10),Q.push(J.offset??0),this.db.all($,Q).map((Z)=>({observation:this.mapRow(Z),rank:Z.rank,snippet:Z.title}))}searchByConcept(J,X=10,$){let Q=!!$,Z=`SELECT o.*
195
+ `,X=[$.query];if(V&&$.projectPath)J+=" AND s.project_path = ?",X.push($.projectPath);if($.sessionId)J+=" AND o.session_id = ?",X.push($.sessionId);if($.type)J+=" AND o.type = ?",X.push($.type);if($.importanceMin!==void 0)J+=" AND o.importance >= ?",X.push($.importanceMin);if($.importanceMax!==void 0)J+=" AND o.importance <= ?",X.push($.importanceMax);if($.createdAfter)J+=" AND o.created_at >= ?",X.push($.createdAfter);if($.createdBefore)J+=" AND o.created_at <= ?",X.push($.createdBefore);if($.concepts&&$.concepts.length>0){let Q=$.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");J+=` AND (${Q.join(" OR ")})`;for(let H of $.concepts)X.push(H)}if($.files&&$.files.length>0){let Q=$.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
196
+ OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);J+=` AND (${Q.join(" OR ")})`;for(let H of $.files){let Z=`%${SV(H)}%`;X.push(Z,Z)}}return J+=" ORDER BY rank LIMIT ? OFFSET ?",X.push($.limit??10),X.push($.offset??0),this.db.all(J,X).map((Q)=>({observation:this.mapRow(Q),rank:Q.rank,snippet:Q.title}))}searchByConcept($,V=10,J){let X=!!J,Q=`SELECT o.*
197
197
  FROM observations o
198
198
  JOIN observations_fts fts ON o._rowid = fts.rowid
199
- ${Q?"JOIN sessions s ON o.session_id = s.id":""}
199
+ ${X?"JOIN sessions s ON o.session_id = s.id":""}
200
200
  WHERE observations_fts MATCH ?
201
201
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
202
- ${Q?"AND s.project_path = ?":""}
202
+ ${X?"AND s.project_path = ?":""}
203
203
  ORDER BY rank
204
- LIMIT ?`,H=[`concepts:${J}`];if(Q&&$)H.push($);return H.push(X),this.db.all(Z,H).map((Y)=>this.mapRow(Y))}searchByFile(J,X=10,$){let Q=!!$,Z=`SELECT o.*
204
+ LIMIT ?`,Z=[`concepts:"${$.replace(/"/g,'""')}"`];if(X&&J)Z.push(J);return Z.push(V),this.db.all(Q,Z).map((Y)=>this.mapRow(Y))}searchByFile($,V=10,J){let X=!!J,Q=`SELECT o.*
205
205
  FROM observations o
206
206
  JOIN observations_fts fts ON o._rowid = fts.rowid
207
- ${Q?"JOIN sessions s ON o.session_id = s.id":""}
207
+ ${X?"JOIN sessions s ON o.session_id = s.id":""}
208
208
  WHERE observations_fts MATCH ?
209
209
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
210
- ${Q?"AND s.project_path = ?":""}
210
+ ${X?"AND s.project_path = ?":""}
211
211
  ORDER BY rank
212
- LIMIT ?`,H=[`files_read:"${J.replace(/"/g,'""')}" OR files_modified:"${J.replace(/"/g,'""')}"`];if(Q&&$)H.push($);return H.push(X),this.db.all(Z,H).map((Y)=>this.mapRow(Y))}setEmbedding(J,X){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(X),J])}getWithEmbeddings(J,X){return this.db.all(`SELECT o.id, o.embedding, o.title
212
+ LIMIT ?`,H=[`files_read:"${$.replace(/"/g,'""')}" OR files_modified:"${$.replace(/"/g,'""')}"`];if(X&&J)H.push(J);return H.push(V),this.db.all(Q,H).map((Z)=>this.mapRow(Z))}setEmbedding($,V){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(V),$])}getWithEmbeddings($,V){return this.db.all(`SELECT o.id, o.embedding, o.title
213
213
  FROM observations o
214
214
  JOIN sessions s ON o.session_id = s.id
215
215
  WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
216
216
  ORDER BY o.created_at DESC
217
- LIMIT ?`,[J,X]).map(($)=>{try{return{id:$.id,embedding:JSON.parse($.embedding),title:$.title}}catch{return null}}).filter(($)=>$!==null)}findSimilar(J,X,$,Q){let Z=this.db.all(`SELECT id, embedding FROM observations
217
+ LIMIT ?`,[$,V]).map((J)=>{try{return{id:J.id,embedding:JSON.parse(J.embedding),title:J.title}}catch{return null}}).filter((J)=>J!==null)}findSimilar($,V,J,X){let Q=this.db.all(`SELECT id, embedding FROM observations
218
218
  WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
219
219
  ORDER BY created_at DESC
220
- LIMIT 200`,[X]),H=[];for(let Y of Z)try{let V=JSON.parse(Y.embedding);if(!Array.isArray(V)||V.length!==J.length)continue;let W=RJ(J,V);if(W>=$)H.push({id:Y.id,similarity:W})}catch{}return H.sort((Y,V)=>V.similarity-Y.similarity).slice(0,Q)}insertVecEmbedding(J,X){let $=new Float32Array(X);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[J]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[J,$]),this.db.run("COMMIT")}catch(Q){throw this.db.run("ROLLBACK"),Q}}migrateExistingEmbeddings(J){let X=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),$=0,Q=0;for(let Z of X)try{let H=JSON.parse(Z.embedding);if(!Array.isArray(H)||H.length!==J){Q++;continue}this.insertVecEmbedding(Z.id,H),$++}catch{Q++}return{migrated:$,skipped:Q}}getVecEmbeddingMatches(J,X){try{let $=new Float32Array(J);return this.db.all(`SELECT observation_id, distance
220
+ LIMIT 200`,[V]),H=[];for(let Z of Q)try{let Y=JSON.parse(Z.embedding);if(!Array.isArray(Y)||Y.length!==$.length)continue;let W=E$($,Y);if(W>=J)H.push({id:Z.id,similarity:W})}catch{}return H.sort((Z,Y)=>Y.similarity-Z.similarity).slice(0,X)}insertVecEmbedding($,V){let J=new Float32Array(V);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 (?, ?)",[$,J]),this.db.run("COMMIT")}catch(X){throw this.db.run("ROLLBACK"),X}}migrateExistingEmbeddings($){let V=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),J=0,X=0;for(let Q of V)try{let H=JSON.parse(Q.embedding);if(!Array.isArray(H)||H.length!==$){X++;continue}this.insertVecEmbedding(Q.id,H),J++}catch{X++}return{migrated:J,skipped:X}}getVecEmbeddingMatches($,V){try{let J=new Float32Array($);return this.db.all(`SELECT observation_id, distance
221
221
  FROM observation_embeddings
222
- WHERE embedding MATCH ? AND k = ?`,[$,X]).map((Q)=>({observationId:Q.observation_id,distance:Q.distance}))}catch{return[]}}searchVecSubset(J,X,$){if(X.length===0)return[];try{let Q=new Float32Array(J),Z=Math.max($*5,X.length),H=this.db.all(`SELECT observation_id, distance
222
+ WHERE embedding MATCH ? AND k = ?`,[J,V]).map((X)=>({observationId:X.observation_id,distance:X.distance}))}catch{return[]}}searchVecSubset($,V,J){if(V.length===0)return[];try{let X=new Float32Array($),Q=Math.max(J*5,V.length),H=this.db.all(`SELECT observation_id, distance
223
223
  FROM observation_embeddings
224
- WHERE embedding MATCH ? AND k = ?`,[Q,Z]),Y=new Set(X);return H.filter((V)=>Y.has(V.observation_id)).slice(0,$).map((V)=>({observationId:V.observation_id,distance:V.distance}))}catch{return[]}}update(J,X){let $=this.getById(J);if(!$)return null;if(Object.keys(X).length===0)return $;let Q=this.create({sessionId:$.sessionId,scope:$.scope??"project",type:X.type??$.type,title:X.title??$.title,subtitle:X.subtitle??$.subtitle,facts:X.facts??$.facts,narrative:X.narrative??$.narrative,concepts:X.concepts??$.concepts,filesRead:X.filesRead??$.filesRead,filesModified:X.filesModified??$.filesModified,rawToolOutput:$.rawToolOutput,toolName:"mem-revise",tokenCount:$.tokenCount,discoveryTokens:$.discoveryTokens,importance:X.importance??$.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[J,Q.id]),this.supersede(J,Q.id),this.getById(Q.id)}supersede(J,X){let $=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[X,$,J])}delete(J){if(this.db.all("SELECT id FROM observations WHERE id = ?",[J]).length===0)return!1;let $=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[$,J]),this.deleteEmbeddingsForObservations([J]),!0}getLineage(J){let X=this.getByIdIncludingArchived(J);if(!X)return[];let $=new Set([X.id]),Q=[X];while(Q[0].revisionOf){let Z=this.getByIdIncludingArchived(Q[0].revisionOf);if(!Z||$.has(Z.id))break;Q.unshift(Z),$.add(Z.id)}while(Q[Q.length-1].supersededBy){let Z=Q[Q.length-1].supersededBy;if(!Z)break;let H=this.getByIdIncludingArchived(Z);if(!H||$.has(H.id))break;Q.push(H),$.add(H.id)}return Q}deleteOlderThan(J){return this.db.all(`DELETE FROM observations
224
+ WHERE embedding MATCH ? AND k = ?`,[X,Q]),Z=new Set(V);return H.filter((Y)=>Z.has(Y.observation_id)).slice(0,J).map((Y)=>({observationId:Y.observation_id,distance:Y.distance}))}catch{return[]}}update($,V){let J=this.getById($);if(!J)return null;if(Object.keys(V).length===0)return J;let X=this.create({sessionId:J.sessionId,scope:J.scope??"project",type:V.type??J.type,title:V.title??J.title,subtitle:V.subtitle??J.subtitle,facts:V.facts??J.facts,narrative:V.narrative??J.narrative,concepts:V.concepts??J.concepts,filesRead:V.filesRead??J.filesRead,filesModified:V.filesModified??J.filesModified,rawToolOutput:J.rawToolOutput,toolName:"mem-revise",tokenCount:J.tokenCount,discoveryTokens:J.discoveryTokens,importance:V.importance??J.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[$,X.id]),this.supersede($,X.id),this.getById(X.id)}supersede($,V){let J=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[V,J,$])}delete($){if(this.db.all("SELECT id FROM observations WHERE id = ?",[$]).length===0)return!1;let J=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[J,$]),this.deleteEmbeddingsForObservations([$]),!0}getLineage($){let V=this.getByIdIncludingArchived($);if(!V)return[];let J=new Set([V.id]),X=[V];while(X[0].revisionOf){let Q=this.getByIdIncludingArchived(X[0].revisionOf);if(!Q||J.has(Q.id))break;X.unshift(Q),J.add(Q.id)}while(X[X.length-1].supersededBy){let Q=X[X.length-1].supersededBy;if(!Q)break;let H=this.getByIdIncludingArchived(Q);if(!H||J.has(H.id))break;X.push(H),J.add(H.id)}return X}deleteOlderThan($){return this.db.all(`DELETE FROM observations
225
225
  WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
226
226
  AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
227
- RETURNING id`,[J]).length}deleteEmbeddingsForObservations(J){if(J.length===0)return;let X=J.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${X})`,J)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${X})`,J)}mapRow(J){return{id:J.id,sessionId:J.session_id,scope:J.scope??"project",type:J.type,title:J.title,subtitle:J.subtitle,facts:JSON.parse(J.facts),narrative:J.narrative,concepts:JSON.parse(J.concepts),filesRead:JSON.parse(J.files_read),filesModified:JSON.parse(J.files_modified),rawToolOutput:J.raw_tool_output,toolName:J.tool_name,createdAt:J.created_at,tokenCount:J.token_count,discoveryTokens:J.discovery_tokens??0,importance:J.importance??3,revisionOf:J.revision_of??null,deletedAt:J.deleted_at??null,supersededBy:J.superseded_by??null,supersededAt:J.superseded_at??null}}}import{randomUUID as BX}from"crypto";class s{db;constructor(J){this.db=J}create(J){let X=BX(),$=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
227
+ RETURNING id`,[$]).length}deleteEmbeddingsForObservations($){if($.length===0)return;let V=$.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${V})`,$)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${V})`,$)}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 DV}from"crypto";class t{db;constructor($){this.db=$}create($){let V=DV(),J=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
228
228
  (id, session_id, tool_name, tool_output, call_id, created_at)
229
- VALUES (?, ?, ?, ?, ?, ?)`,[X,J.sessionId,J.toolName,J.toolOutput,J.callId,$]),{...J,id:X,createdAt:$,status:"pending",retryCount:0,error:null}}getPending(J=10){return this.db.all("SELECT * FROM pending_messages WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?",[J]).map((X)=>this.mapRow(X))}getByStatus(J){return this.db.all("SELECT * FROM pending_messages WHERE status = ? ORDER BY created_at ASC",[J]).map((X)=>this.mapRow(X))}markProcessing(J){this.db.run("UPDATE pending_messages SET status = 'processing' WHERE id = ?",[J])}markCompleted(J){this.db.run("UPDATE pending_messages SET status = 'completed' WHERE id = ?",[J])}markFailed(J,X){this.db.run("UPDATE pending_messages SET status = 'failed', error = ?, retry_count = retry_count + 1 WHERE id = ?",[X,J])}resetStale(J=5){return this.db.all(`UPDATE pending_messages SET status = 'pending'
229
+ VALUES (?, ?, ?, ?, ?, ?)`,[V,$.sessionId,$.toolName,$.toolOutput,$.callId,J]),{...$,id:V,createdAt:J,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((V)=>this.mapRow(V))}getByStatus($){return this.db.all("SELECT * FROM pending_messages WHERE status = ? ORDER BY created_at ASC",[$]).map((V)=>this.mapRow(V))}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($,V){this.db.run("UPDATE pending_messages SET status = 'failed', error = ?, retry_count = retry_count + 1 WHERE id = ?",[V,$])}resetStale($=5){return this.db.all(`UPDATE pending_messages SET status = 'pending'
230
230
  WHERE status = 'processing'
231
231
  AND created_at < datetime('now', ? || ' minutes')
232
- RETURNING id`,[`-${J}`]).length}deleteCompletedOlderThan(J){return this.db.all(`DELETE FROM pending_messages
232
+ RETURNING id`,[`-${$}`]).length}deleteCompletedOlderThan($){return this.db.all(`DELETE FROM pending_messages
233
233
  WHERE status = 'completed'
234
234
  AND created_at < datetime('now', '-' || ? || ' days')
235
- RETURNING id`,[J]).length}mapRow(J){return{id:J.id,sessionId:J.session_id,toolName:J.tool_name,toolOutput:J.tool_output,callId:J.call_id,createdAt:J.created_at,status:J.status,retryCount:J.retry_count,error:J.error??null}}}var UX=[{version:1,name:"create-schema",up:`
235
+ 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 CV=[{version:1,name:"create-schema",up:`
236
236
  -- Sessions table
237
237
  CREATE TABLE IF NOT EXISTS sessions (
238
238
  _rowid INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -526,21 +526,21 @@ Respond with EXACTLY this XML format:
526
526
  INSERT INTO entities_fts(rowid, name, entity_type)
527
527
  VALUES (new._rowid, new.name, new.entity_type);
528
528
  END;
529
- `}];function OJ(J,X){if(J.migrate(UX),X?.hasVectorExtension&&X?.embeddingDimension&&X.embeddingDimension>0)NX(J,X.embeddingDimension)}function NX(J,X){if(J.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let Q=J.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(Q&&Number(Q.value)!==X){console.warn(`[open-mem] vec0 table exists with dimension ${Q.value}, but config specifies ${X}. Drop observation_embeddings to re-create with new dimension.`);return}}else J.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
529
+ `}];function T$($,V){if($.migrate(CV),V?.hasVectorExtension&&V?.embeddingDimension&&V.embeddingDimension>0)OV($,V.embeddingDimension)}function OV($,V){if($.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let X=$.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(X&&Number(X.value)!==V){console.warn(`[open-mem] vec0 table exists with dimension ${X.value}, but config specifies ${V}. Drop observation_embeddings to re-create with new dimension.`);return}}else $.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
530
530
  observation_id TEXT PRIMARY KEY,
531
- embedding float[${X}] distance_metric=cosine
532
- )`);J.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(X)])}class i{db;constructor(J){this.db=J}create(J,X){let $=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
533
- VALUES (?, ?, ?, 'active')`,[J,X,$]),this.getById(J)}getOrCreate(J,X){let $=this.getById(J);if($)return $;return this.create(J,X)}getById(J){let X=this.db.get("SELECT * FROM sessions WHERE id = ?",[J]);return X?this.mapRow(X):null}getRecent(J,X=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[J,X]).map(($)=>this.mapRow($))}getAll(J){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[J]).map((X)=>this.mapRow(X))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((J)=>this.mapRow(J))}updateStatus(J,X){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[X,J])}markCompleted(J){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[J])}incrementObservationCount(J){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[J])}setSummary(J,X){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[X,J])}mapRow(J){return{id:J.id,projectPath:J.project_path,startedAt:J.started_at,endedAt:J.ended_at??null,status:J.status,observationCount:J.observation_count,summaryId:J.summary_id??null}}}import{randomUUID as _X}from"crypto";class a{db;constructor(J){this.db=J}create(J){let X=_X(),$=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
531
+ embedding float[${V}] distance_metric=cosine
532
+ )`);$.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(V)])}class o{db;constructor($){this.db=$}create($,V){let J=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
533
+ VALUES (?, ?, ?, 'active')`,[$,V,J]),this.getById($)}getOrCreate($,V){let J=this.getById($);if(J)return J;return this.create($,V)}getById($){let V=this.db.get("SELECT * FROM sessions WHERE id = ?",[$]);return V?this.mapRow(V):null}getRecent($,V=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[$,V]).map((J)=>this.mapRow(J))}getAll($){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[$]).map((V)=>this.mapRow(V))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map(($)=>this.mapRow($))}updateStatus($,V){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[V,$])}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($,V){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[V,$])}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 jV}from"crypto";class a{db;constructor($){this.db=$}create($){let V=jV(),J=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
534
534
  (id, session_id, summary, key_decisions, files_modified,
535
535
  concepts, created_at, token_count,
536
536
  request, investigated, learned, completed, next_steps)
537
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[X,J.sessionId,J.summary,JSON.stringify(J.keyDecisions),JSON.stringify(J.filesModified),JSON.stringify(J.concepts),$,J.tokenCount,J.request??"",J.investigated??"",J.learned??"",J.completed??"",J.nextSteps??""]),{...J,id:X,createdAt:$}}importSummary(J){this.db.run(`INSERT INTO session_summaries
537
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[V,$.sessionId,$.summary,JSON.stringify($.keyDecisions),JSON.stringify($.filesModified),JSON.stringify($.concepts),J,$.tokenCount,$.request??"",$.investigated??"",$.learned??"",$.completed??"",$.nextSteps??""]),{...$,id:V,createdAt:J}}importSummary($){this.db.run(`INSERT INTO session_summaries
538
538
  (id, session_id, summary, key_decisions, files_modified,
539
539
  concepts, created_at, token_count,
540
540
  request, investigated, learned, completed, next_steps)
541
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[J.id,J.sessionId,J.summary,JSON.stringify(J.keyDecisions),JSON.stringify(J.filesModified),JSON.stringify(J.concepts),J.createdAt,J.tokenCount,J.request??"",J.investigated??"",J.learned??"",J.completed??"",J.nextSteps??""])}getBySessionId(J){let X=this.db.get("SELECT * FROM session_summaries WHERE session_id = ?",[J]);return X?this.mapRow(X):null}getRecent(J=10){return this.db.all("SELECT * FROM session_summaries ORDER BY created_at DESC LIMIT ?",[J]).map((X)=>this.mapRow(X))}search(J,X=10){return this.db.all(`SELECT ss.*
541
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[$.id,$.sessionId,$.summary,JSON.stringify($.keyDecisions),JSON.stringify($.filesModified),JSON.stringify($.concepts),$.createdAt,$.tokenCount,$.request??"",$.investigated??"",$.learned??"",$.completed??"",$.nextSteps??""])}getBySessionId($){let V=this.db.get("SELECT * FROM session_summaries WHERE session_id = ?",[$]);return V?this.mapRow(V):null}getRecent($=10){return this.db.all("SELECT * FROM session_summaries ORDER BY created_at DESC LIMIT ?",[$]).map((V)=>this.mapRow(V))}search($,V=10){return this.db.all(`SELECT ss.*
542
542
  FROM session_summaries ss
543
543
  JOIN summaries_fts fts ON ss._rowid = fts.rowid
544
544
  WHERE summaries_fts MATCH ?
545
545
  ORDER BY rank
546
- LIMIT ?`,[J,X]).map(($)=>this.mapRow($))}mapRow(J){return{id:J.id,sessionId:J.session_id,summary:J.summary,keyDecisions:JSON.parse(J.key_decisions),filesModified:JSON.parse(J.files_modified),concepts:JSON.parse(J.concepts),createdAt:J.created_at,tokenCount:J.token_count,request:J.request||void 0,investigated:J.investigated||void 0,learned:J.learned||void 0,completed:J.completed||void 0,nextSteps:J.next_steps||void 0}}}class r{config;compressor;summarizer;pendingRepo;observationRepo;sessionRepo;summaryRepo;embeddingModel;conflictEvaluator;entityExtractor;entityRepo;observer;processing=!1;timer=null;mode="in-process";onEnqueue=null;constructor(J,X,$,Q,Z,H,Y,V=null,W=null,K=null,B=null,U=null){this.config=J;this.compressor=X;this.summarizer=$;this.pendingRepo=Q;this.observationRepo=Z;this.sessionRepo=H;this.summaryRepo=Y;this.embeddingModel=V;this.conflictEvaluator=W;this.entityExtractor=K;this.entityRepo=B;this.observer=U}setMode(J){if(this.mode=J,J==="enqueue-only")this.stop()}getMode(){return this.mode}setOnEnqueue(J){this.onEnqueue=J}enqueue(J,X,$,Q){if(this.pendingRepo.create({sessionId:J,toolName:X,toolOutput:$,callId:Q}),this.observer?.onEnqueue?.({sessionId:J,toolName:X,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 J=0,X=0,$=Date.now();try{this.pendingRepo.resetStale(5);let Q=this.pendingRepo.getPending(this.config.batchSize);if(this.observer?.onBatchStart?.({pending:Q.length,mode:this.mode,startedAt:new Date($).toISOString()}),Q.length===0)return 0;for(let Z of Q)try{this.pendingRepo.markProcessing(Z.id);let Y=await this.compressor.compress(Z.toolName,Z.toolOutput)??this.compressor.createFallbackObservation(Z.toolName,Z.toolOutput),V=!1,W=null;if(this.embeddingModel)try{let B=d({title:Y.title,narrative:Y.narrative,concepts:Y.concepts}),U=await c(this.embeddingModel,B);if(U){let _=this.config.conflictResolutionEnabled&&this.conflictEvaluator,F=this.config.conflictSimilarityBandLow??0.7,q=this.config.conflictSimilarityBandHigh??0.92;if(_){let C=this.observationRepo.findSimilar(U,Y.type,F,5),y=C.find((I)=>I.similarity>q);if(y)console.log(`[open-mem] Dedup: skipping duplicate of ${y.id} (similarity: ${y.similarity.toFixed(3)})`),V=!0;else{let I=C.filter((P)=>P.similarity>=F&&P.similarity<=q);if(I.length>0)try{let P=I.map((N)=>{let k=this.observationRepo.getById(N.id);return k?{id:k.id,title:k.title,narrative:k.narrative,concepts:k.concepts,type:k.type}:null}).filter((N)=>N!==null);if(P.length>0&&this.conflictEvaluator){let N=await this.conflictEvaluator.evaluate({title:Y.title,narrative:Y.narrative,concepts:Y.concepts,type:Y.type},P);if(N&&N.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${N.reason})`),V=!0;else if(N&&N.outcome==="update"&&N.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${N.supersedesId} (${N.reason})`),W=N.supersedesId}}catch{}}}else{let C=this.observationRepo.findSimilar(U,Y.type,0.92,1);if(C.length>0)console.log(`[open-mem] Dedup: skipping duplicate of ${C[0].id} (similarity: ${C[0].similarity.toFixed(3)})`),V=!0}}}catch{}if(V){this.pendingRepo.markCompleted(Z.id);continue}let K=this.observationRepo.create({sessionId:Z.sessionId,type:Y.type,title:Y.title,subtitle:Y.subtitle,facts:Y.facts,narrative:Y.narrative,concepts:Y.concepts,filesRead:Y.filesRead,filesModified:Y.filesModified,rawToolOutput:Z.toolOutput,toolName:Z.toolName,tokenCount:O(`${Y.title} ${Y.narrative} ${Y.facts.join(" ")}`),discoveryTokens:Y.discoveryTokens??O(Z.toolOutput),importance:Y.importance??3});if(this.embeddingModel)try{let B=d({title:K.title,narrative:K.narrative,concepts:K.concepts}),U=await c(this.embeddingModel,B);if(U)this.observationRepo.setEmbedding(K.id,U)}catch{}if(W)try{this.observationRepo.supersede(W,K.id),console.log(`[open-mem] Superseded observation ${W} with ${K.id}`)}catch(B){console.error(`[open-mem] Failed to supersede ${W}:`,B)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let B=await this.entityExtractor.extract({title:K.title,narrative:K.narrative,concepts:K.concepts,facts:K.facts,filesRead:K.filesRead,filesModified:K.filesModified,type:K.type});if(B){let U=new Map;for(let _ of B.entities){let F=this.entityRepo.upsertEntity(_.name,_.entityType);U.set(_.name,F.id),this.entityRepo.linkObservation(F.id,K.id)}for(let _ of B.relations){let F=U.get(_.sourceName),q=U.get(_.targetName);if(F&&q)this.entityRepo.createRelation(F,q,_.relationship,K.id)}}}catch{}this.sessionRepo.incrementObservationCount(Z.sessionId),this.pendingRepo.markCompleted(Z.id),J++}catch(H){this.pendingRepo.markFailed(Z.id,String(H)),X++,this.observer?.onItemFailed?.({pendingId:Z.id,error:String(H),failedAt:new Date().toISOString()})}return J}finally{this.observer?.onBatchEnd?.({processed:J,failed:X,durationMs:Date.now()-$,finishedAt:new Date().toISOString()}),this.processing=!1}}async summarizeSession(J){let X=this.observationRepo.getBySession(J);if(!this.summarizer.shouldSummarize(X.length))return;if(this.summaryRepo.getBySessionId(J))return;let Q=await this.summarizer.summarize(J,X);if(!Q)return;let Z=this.summaryRepo.create({sessionId:J,summary:Q.summary,keyDecisions:Q.keyDecisions,filesModified:Q.filesModified,concepts:Q.concepts,tokenCount:O(Q.summary)});this.sessionRepo.setSummary(J,Z.id)}start(){if(this.mode==="enqueue-only")return;if(this.timer)return;this.timer=setInterval(async()=>{try{await this.processBatch()}catch{}},this.config.batchIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get isProcessing(){return this.processing}getStats(){return{pending:this.pendingRepo.getPending(1000).length,processing:this.processing}}}import{spawnSync as CJ}from"child_process";import{dirname as FX,resolve as kJ}from"path";function LX(J){try{let X=CJ("git",["rev-parse","--git-common-dir"],{cwd:J,encoding:"utf-8",timeout:5000});if(X.status!==0||!X.stdout)return null;let $=X.stdout.trim();if($===".git")return null;let Q=CJ("git",["rev-parse","--git-dir"],{cwd:J,encoding:"utf-8",timeout:5000});if(Q.status!==0||!Q.stdout)return null;let Z=Q.stdout.trim(),H=kJ(J,$),Y=kJ(J,Z);if(H===Y)return null;let V=FX(H);if(V===H||V==="/")return null;return V}catch{return null}}function TJ(J){return LX(J)??J}var AX=5000,{values:t}=MX({options:{project:{type:"string",short:"p"},"poll-interval":{type:"string"}},strict:!1}),xJ=typeof t.project==="string"?t.project:null;if(!xJ)console.error("Usage: open-mem-daemon --project <path> [--poll-interval <ms>]"),process.exit(1);var qJ=t["poll-interval"],o=typeof qJ==="string"?Number.parseInt(qJ,10):AX;if(Number.isNaN(o)||o<100)console.error("--poll-interval must be a number >= 100"),process.exit(1);var SX=TJ(xJ),G=_J(SX);h.enableExtensionSupport();var E=DJ(G.dbPath);OJ(E,{hasVectorExtension:E.hasVectorExtension,embeddingDimension:G.embeddingDimension});var jX=new s(E),DX=new n(E),EX=new i(E),RX=new a(E),OX=new x(G),CX=new b(G),e=G.provider!=="bedrock",kX=G.compressionEnabled&&(!e||G.apiKey)?GJ({provider:G.provider,model:G.model,apiKey:G.apiKey}):null,TX=G.conflictResolutionEnabled&&(!e||G.apiKey)?new f({provider:G.provider,apiKey:G.apiKey,model:G.model,rateLimitingEnabled:G.rateLimitingEnabled}):null,qX=G.entityExtractionEnabled&&(!e||G.apiKey)?new u({provider:G.provider,apiKey:G.apiKey,model:G.model,rateLimitingEnabled:G.rateLimitingEnabled}):null,PX=new l(E),xX=new r(G,OX,CX,jX,DX,EX,RX,kX,TX,qX,PX),IJ=MJ(G.dbPath);FJ(IJ);var JJ=new m({queueProcessor:xX,pollIntervalMs:o});if(process.send)process.on("message",(J)=>{JJ.handleMessage(J)});var PJ=!1,XJ=()=>{if(PJ)return;PJ=!0,JJ.stop(),LJ(IJ),E.close()};process.on("SIGTERM",()=>{XJ(),process.exit(0)});process.on("SIGINT",()=>{XJ(),process.exit(0)});process.on("beforeExit",XJ);JJ.start();
546
+ LIMIT ?`,[$,V]).map((J)=>this.mapRow(J))}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 e{config;compressor;summarizer;pendingRepo;observationRepo;sessionRepo;summaryRepo;embeddingModel;conflictEvaluator;entityExtractor;entityRepo;observer;processing=!1;timer=null;mode="in-process";onEnqueue=null;constructor($,V,J,X,Q,H,Z,Y=null,W=null,K=null,F=null,G=null){this.config=$;this.compressor=V;this.summarizer=J;this.pendingRepo=X;this.observationRepo=Q;this.sessionRepo=H;this.summaryRepo=Z;this.embeddingModel=Y;this.conflictEvaluator=W;this.entityExtractor=K;this.entityRepo=F;this.observer=G}setMode($){if(this.mode=$,$==="enqueue-only")this.stop()}getMode(){return this.mode}setOnEnqueue($){this.onEnqueue=$}enqueue($,V,J,X){if(this.pendingRepo.create({sessionId:$,toolName:V,toolOutput:J,callId:X}),this.observer?.onEnqueue?.({sessionId:$,toolName:V,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,V=0,J=Date.now();try{this.pendingRepo.resetStale(5);let X=this.pendingRepo.getPending(this.config.batchSize);if(this.observer?.onBatchStart?.({pending:X.length,mode:this.mode,startedAt:new Date(J).toISOString()}),X.length===0)return 0;for(let Q of X)try{this.pendingRepo.markProcessing(Q.id);let Z=await this.compressor.compress(Q.toolName,Q.toolOutput)??this.compressor.createFallbackObservation(Q.toolName,Q.toolOutput),Y=!1,W=null;if(this.embeddingModel)try{let F=i({title:Z.title,narrative:Z.narrative,concepts:Z.concepts}),G=await s(this.embeddingModel,F);if(G){let M=this.config.conflictResolutionEnabled&&this.conflictEvaluator,_=this.config.conflictSimilarityBandLow??0.7,q=this.config.conflictSimilarityBandHigh??0.92;if(M){let E=this.observationRepo.findSimilar(G,Z.type,_,5),w=E.find((h)=>h.similarity>q);if(w)console.log(`[open-mem] Dedup: skipping duplicate of ${w.id} (similarity: ${w.similarity.toFixed(3)})`),Y=!0;else{let h=E.filter((y)=>y.similarity>=_&&y.similarity<=q);if(h.length>0)try{let y=h.map((U)=>{let T=this.observationRepo.getById(U.id);return T?{id:T.id,title:T.title,narrative:T.narrative,concepts:T.concepts,type:T.type}:null}).filter((U)=>U!==null);if(y.length>0&&this.conflictEvaluator){let U=await this.conflictEvaluator.evaluate({title:Z.title,narrative:Z.narrative,concepts:Z.concepts,type:Z.type},y);if(U&&U.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${U.reason})`),Y=!0;else if(U&&U.outcome==="update"&&U.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${U.supersedesId} (${U.reason})`),W=U.supersedesId}}catch{}}}else{let E=this.observationRepo.findSimilar(G,Z.type,0.92,1);if(E.length>0)console.log(`[open-mem] Dedup: skipping duplicate of ${E[0].id} (similarity: ${E[0].similarity.toFixed(3)})`),Y=!0}}}catch{}if(Y){this.pendingRepo.markCompleted(Q.id);continue}let K=this.observationRepo.create({sessionId:Q.sessionId,type:Z.type,title:Z.title,subtitle:Z.subtitle,facts:Z.facts,narrative:Z.narrative,concepts:Z.concepts,filesRead:Z.filesRead,filesModified:Z.filesModified,rawToolOutput:Q.toolOutput,toolName:Q.toolName,tokenCount:R(`${Z.title} ${Z.narrative} ${Z.facts.join(" ")}`),discoveryTokens:Z.discoveryTokens??R(Q.toolOutput),importance:Z.importance??3});if(this.embeddingModel)try{let F=i({title:K.title,narrative:K.narrative,concepts:K.concepts}),G=await s(this.embeddingModel,F);if(G)this.observationRepo.setEmbedding(K.id,G)}catch{}if(W)try{this.observationRepo.supersede(W,K.id),console.log(`[open-mem] Superseded observation ${W} with ${K.id}`)}catch(F){console.error(`[open-mem] Failed to supersede ${W}:`,F)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let F=await this.entityExtractor.extract({title:K.title,narrative:K.narrative,concepts:K.concepts,facts:K.facts,filesRead:K.filesRead,filesModified:K.filesModified,type:K.type});if(F){let G=new Map;for(let M of F.entities){let _=this.entityRepo.upsertEntity(M.name,M.entityType);G.set(M.name,_.id),this.entityRepo.linkObservation(_.id,K.id)}for(let M of F.relations){let _=G.get(M.sourceName),q=G.get(M.targetName);if(_&&q)this.entityRepo.createRelation(_,q,M.relationship,K.id)}}}catch{}this.sessionRepo.incrementObservationCount(Q.sessionId),this.pendingRepo.markCompleted(Q.id),$++}catch(H){this.pendingRepo.markFailed(Q.id,String(H)),V++,this.observer?.onItemFailed?.({pendingId:Q.id,error:String(H),failedAt:new Date().toISOString()})}return $}finally{this.observer?.onBatchEnd?.({processed:$,failed:V,durationMs:Date.now()-J,finishedAt:new Date().toISOString()}),this.processing=!1}}async summarizeSession($){let V=this.observationRepo.getBySession($);if(!this.summarizer.shouldSummarize(V.length))return;if(this.summaryRepo.getBySessionId($))return;let X=await this.summarizer.summarize($,V);if(!X)return;let Q=this.summaryRepo.create({sessionId:$,summary:X.summary,keyDecisions:X.keyDecisions,filesModified:X.filesModified,concepts:X.concepts,tokenCount:R(X.summary)});this.sessionRepo.setSummary($,Q.id)}start(){if(this.mode==="enqueue-only")return;if(this.timer)return;this.timer=setInterval(async()=>{try{await this.processBatch()}catch{}},this.config.batchIntervalMs)}stop(){if(this.timer)clearInterval(this.timer),this.timer=null}get isRunning(){return this.timer!==null}get isProcessing(){return this.processing}getStats(){return{pending:this.pendingRepo.getPending(1000).length,processing:this.processing}}}import{spawnSync as P$}from"child_process";import{dirname as RV,resolve as q$}from"path";function kV($){try{let V=P$("git",["rev-parse","--git-common-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(V.status!==0||!V.stdout)return null;let J=V.stdout.trim();if(J===".git")return null;let X=P$("git",["rev-parse","--git-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(X.status!==0||!X.stdout)return null;let Q=X.stdout.trim(),H=q$($,J),Z=q$($,Q);if(H===Z)return null;let Y=RV(H);if(Y===H||Y==="/")return null;return Y}catch{return null}}function y$($){return kV($)??$}var TV=5000,{values:$$}=EV({options:{project:{type:"string",short:"p"},"poll-interval":{type:"string"}},strict:!1}),h$=typeof $$.project==="string"?$$.project:null;if(!h$)console.error("Usage: open-mem-daemon --project <path> [--poll-interval <ms>]"),process.exit(1);var x$=$$["poll-interval"],V$=typeof x$==="string"?Number.parseInt(x$,10):TV;if(Number.isNaN(V$)||V$<100)console.error("--poll-interval must be a number >= 100"),process.exit(1);var PV=y$(h$),B=A$(PV);u.enableExtensionSupport();var O=R$(B.dbPath);T$(O,{hasVectorExtension:O.hasVectorExtension,embeddingDimension:B.embeddingDimension});var qV=new t(O),yV=new r(O),xV=new o(O),IV=new a(O),hV=new I(B),fV=new l(B),J$=B.provider!=="bedrock",uV=B.compressionEnabled&&(!J$||B.apiKey)?U$({provider:B.provider,model:B.model,apiKey:B.apiKey}):null,wV=B.conflictResolutionEnabled&&(!J$||B.apiKey)?new g({provider:B.provider,apiKey:B.apiKey,model:B.model,rateLimitingEnabled:B.rateLimitingEnabled}):null,vV=B.entityExtractionEnabled&&(!J$||B.apiKey)?new p({provider:B.provider,apiKey:B.apiKey,model:B.model,rateLimitingEnabled:B.rateLimitingEnabled}):null,bV=new d(O),gV=new e(B,hV,fV,qV,yV,xV,IV,uV,wV,vV,bV),f$=D$(B.dbPath);L$(f$);var X$=new c({queueProcessor:gV,pollIntervalMs:V$});if(process.send)process.on("message",($)=>{X$.handleMessage($)});var I$=!1,Q$=()=>{if(I$)return;I$=!0,X$.stop(),S$(f$),O.close()};process.on("SIGTERM",()=>{Q$(),process.exit(0)});process.on("SIGINT",()=>{Q$(),process.exit(0)});process.on("beforeExit",Q$);X$.start();
@@ -1 +1 @@
1
- {"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../../src/db/observations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../../src/db/observations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export {};
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":""}