open-mem 0.14.0 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,39 @@
1
+ import { type KnownProcessType } from "./pid";
1
2
  interface DaemonManagerConfig {
2
3
  dbPath: string;
3
4
  projectPath: string;
4
5
  daemonScript: string;
5
6
  }
7
+ export interface DaemonStatus {
8
+ state: "running" | "missing" | "dead";
9
+ running: boolean;
10
+ pid: number | null;
11
+ stalePid: number | null;
12
+ stalePidRemoved: boolean;
13
+ }
14
+ export interface DaemonSignalResult {
15
+ ok: boolean;
16
+ state: "delivered" | "no-daemon" | "daemon-dead" | "unsupported-signal" | "delivery-failed";
17
+ via: "ipc" | "os-signal" | "none";
18
+ pid: number | null;
19
+ message: string;
20
+ error?: string;
21
+ }
22
+ export interface MaintenancePreflightProcessStatus {
23
+ processType: KnownProcessType;
24
+ state: "running" | "missing" | "dead";
25
+ running: boolean;
26
+ pidPath: string;
27
+ pid: number | null;
28
+ stalePid: number | null;
29
+ stalePidRemoved: boolean;
30
+ }
31
+ export interface MaintenancePreflightStatus {
32
+ blocked: boolean;
33
+ activeProcesses: MaintenancePreflightProcessStatus[];
34
+ checks: MaintenancePreflightProcessStatus[];
35
+ }
36
+ export declare function getMaintenancePreflightStatus(dbPath: string): MaintenancePreflightStatus;
6
37
  /** Manages the lifecycle of a background daemon subprocess for queue processing. */
7
38
  export declare class DaemonManager {
8
39
  private readonly pidPath;
@@ -11,13 +42,10 @@ export declare class DaemonManager {
11
42
  private subprocess;
12
43
  constructor(config: DaemonManagerConfig);
13
44
  start(): boolean;
14
- signal(message: string): void;
45
+ signal(message: string): DaemonSignalResult;
15
46
  stop(): void;
16
47
  isRunning(): boolean;
17
- getStatus(): {
18
- running: boolean;
19
- pid: number | null;
20
- };
48
+ getStatus(): DaemonStatus;
21
49
  }
22
50
  export {};
23
51
  //# sourceMappingURL=manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/daemon/manager.ts"],"names":[],"mappings":"AAOA,UAAU,mBAAmB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,UAAU,CAA6C;gBAEnD,MAAM,EAAE,mBAAmB;IAMvC,KAAK,IAAI,OAAO;IA+BhB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ7B,IAAI,IAAI,IAAI;IAaZ,SAAS,IAAI,OAAO;IAQpB,SAAS,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAUrD"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/daemon/manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAKN,KAAK,gBAAgB,EAGrB,MAAM,OAAO,CAAC;AAKf,UAAU,mBAAmB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,oBAAoB,GAAG,iBAAiB,CAAC;IAC5F,GAAG,EAAE,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;IAClC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iCAAiC;IACjD,WAAW,EAAE,gBAAgB,CAAC;IAC9B,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,iCAAiC,EAAE,CAAC;IACrD,MAAM,EAAE,iCAAiC,EAAE,CAAC;CAC5C;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,0BAA0B,CAyDxF;AAED,oFAAoF;AACpF,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,UAAU,CAA6C;gBAEnD,MAAM,EAAE,mBAAmB;IAMvC,KAAK,IAAI,OAAO;IA+BhB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB;IAgF3C,IAAI,IAAI,IAAI;IAaZ,SAAS,IAAI,OAAO;IAIpB,SAAS,IAAI,YAAY;CAGzB"}
@@ -1,11 +1,34 @@
1
+ export interface PidLivenessStatus {
2
+ state: "alive" | "missing" | "dead";
3
+ pid: number | null;
4
+ stalePid: number | null;
5
+ stalePidRemoved: boolean;
6
+ }
7
+ export type PlatformWorkerProcessKind = "claude" | "cursor";
8
+ export type KnownProcessType = "daemon" | "platform-worker-claude" | "platform-worker-cursor";
9
+ export interface KnownProcessPidFile {
10
+ type: KnownProcessType;
11
+ pidPath: string;
12
+ }
1
13
  /** Write the current process PID to the given file path. */
2
14
  export declare function writePid(pidPath: string): void;
3
15
  /** Read a PID from file, returning null if missing or invalid. */
4
16
  export declare function readPid(pidPath: string): number | null;
5
17
  /** Check whether a process with the given PID is still running. */
6
18
  export declare function isProcessAlive(pid: number): boolean;
19
+ /** Resolve process liveness from a PID file with optional stale cleanup. */
20
+ export declare function getPidLiveness(pidPath: string, removeStale: boolean): PidLivenessStatus;
7
21
  /** Remove a PID file, ignoring errors if it doesn't exist. */
8
22
  export declare function removePid(pidPath: string): void;
23
+ /**
24
+ * Remove a PID file only when it still belongs to the expected PID.
25
+ * Returns true only when a matching PID file was removed.
26
+ */
27
+ export declare function removePidIfMatches(pidPath: string, expectedPid: number): boolean;
9
28
  /** Derive the PID file path from the database path. */
10
29
  export declare function getPidPath(dbPath: string): string;
30
+ /** Derive the platform worker PID path from the database path and worker kind. */
31
+ export declare function getPlatformWorkerPidPath(dbPath: string, kind: PlatformWorkerProcessKind): string;
32
+ /** Derive known process PID files associated with the database path. */
33
+ export declare function getKnownProcessPidFiles(dbPath: string): KnownProcessPidFile[];
11
34
  //# sourceMappingURL=pid.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pid.d.ts","sourceRoot":"","sources":["../../src/daemon/pid.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAO9C;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtD;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAWnD;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM/C;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjD"}
1
+ {"version":3,"file":"pid.d.ts","sourceRoot":"","sources":["../../src/daemon/pid.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,wBAAwB,GAAG,wBAAwB,CAAC;AAE9F,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAO9C;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtD;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAWnD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,iBAAiB,CAavF;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAYhF;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,MAAM,CAIhG;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAM7E"}
package/dist/daemon.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
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>
3
+ var A=import.meta.require;import{parseArgs as KJ}from"util";import{generateText as XV}from"ai";function j($){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 P($){if($&&typeof $==="object"){let V=$.status;if(typeof V==="number")return V===400||V===401||V===403}return!1}function C($){return new Promise((V)=>setTimeout(V,$))}var i$=new Set(["decision","bugfix","feature","refactor","discovery","change"]);function U($,V){let J=new RegExp(`<${V}[^>]*>([\\s\\S]*?)</${V}>`,"i"),X=$.match(J);return X?X[1].trim():""}function _($,V){let J=new RegExp(`<${V}[^>]*>([\\s\\S]*?)</${V}>`,"gi"),X=[];for(let Z of $.matchAll(J)){let H=Z[1].trim();if(H)X.push(H)}return X}function G$($){let V=U($,"observation");if(!V)return null;let J=U(V,"type").toLowerCase(),X=i$.has(J)?J:"discovery",Z=U(V,"title")||"Untitled observation",H=U(V,"subtitle"),Y=U(V,"narrative"),K=_(U(V,"facts"),"fact"),Q=_(U(V,"concepts"),"concept"),G=_(U(V,"files_read"),"file"),F=_(U(V,"files_modified"),"file"),W=U(V,"importance"),B=Number.parseInt(W,10),N=Number.isNaN(B)?3:Math.max(1,Math.min(5,B));return{type:X,title:Z,subtitle:H,facts:K,narrative:Y,concepts:Q,filesRead:G,filesModified:F,importance:N}}function F$($){let V=U($,"session_summary");if(!V)return null;let J=U(V,"summary")||"No summary available",X=_(U(V,"key_decisions"),"decision"),Z=_(U(V,"files_modified"),"file"),H=_(U(V,"concepts"),"concept"),Y=U(V,"request")||void 0,K=U(V,"investigated")||void 0,Q=U(V,"learned")||void 0,G=U(V,"completed")||void 0,F=U(V,"next_steps")||void 0;return{summary:J,keyDecisions:X,filesModified:Z,concepts:H,request:Y,investigated:K,learned:Q,completed:G,nextSteps:F}}var r$=new Set(["new_fact","update","duplicate"]);function W$($){let V=U($,"evaluation");if(!V)return null;let J=U(V,"outcome").toLowerCase().trim();if(!r$.has(J))return null;let X=J,Z=U(V,"reason");if(!Z)return null;let H=U(V,"supersedes"),Y={outcome:X,reason:Z};if(X==="update"&&H)Y.supersedesId=H;if(X==="update"&&!Y.supersedesId)return null;return Y}var o$=new Set(["technology","library","pattern","concept","file","person","project","other"]),t$=new Set(["uses","depends_on","implements","extends","related_to","replaces","configures"]);function U$($){let V=U($,"extraction");if(!V)return null;let J=U(V,"entities"),X=U(V,"relations"),Z=_(J,"entity"),H=[];for(let Q of Z){let G=U(Q,"name");if(!G)continue;let F=U(Q,"type").toLowerCase(),W=o$.has(F)?F:"other";H.push({name:G,entityType:W})}let Y=_(X,"relation"),K=[];for(let Q of Y){let G=U(Q,"source"),F=U(Q,"target"),W=U(Q,"relationship").toLowerCase();if(!G||!F||!W)continue;if(!t$.has(W))continue;K.push({sourceName:G,targetName:F,relationship:W})}return{entities:H,relations:K}}function R($){return Math.ceil($.length/4)}function z$($,V,J,X){let Z=J?`<session_context>
4
4
  ${J}
5
5
  </session_context>
6
6
 
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(`
7
+ `:"",H=X?X.observationTypes.join("|"):"decision|bugfix|feature|refactor|discovery|change",K=(X?X.conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"]).map((Q)=>{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"}[Q];return F?`- ${Q}: ${F}`:`- ${Q}`}).join(`
8
8
  `);return`<task>
9
9
  Analyze the following tool output and extract a structured observation.
10
10
  </task>
@@ -15,11 +15,11 @@ Analyze the following tool output and extract a structured observation.
15
15
  ${V}
16
16
  </tool_output>
17
17
 
18
- ${Q}<instructions>
18
+ ${Z}<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
- ${Y}
22
+ ${K}
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,7 +44,7 @@ Respond with EXACTLY this XML format:
44
44
  <file>path/to/file/modified</file>
45
45
  </files_modified>
46
46
  </observation>
47
- </instructions>`}function z$($,V){let J=$.map((X,Q)=>` <obs index="${Q+1}" type="${X.type}">
47
+ </instructions>`}function B$($,V){let J=$.map((X,Z)=>` <obs index="${Z+1}" type="${X.type}">
48
48
  <title>${X.title}</title>
49
49
  <narrative>${X.narrative}</narrative>
50
50
  </obs>`).join(`
@@ -79,7 +79,7 @@ Respond with EXACTLY this XML format:
79
79
  <concept>key-concept</concept>
80
80
  </concepts>
81
81
  </session_summary>
82
- </instructions>`}function B$($,V){let J=V.map((X)=>` <candidate id="${X.id}">
82
+ </instructions>`}function N$($,V){let J=V.map((X)=>` <candidate id="${X.id}">
83
83
  <title>${X.title}</title>
84
84
  <narrative>${X.narrative}</narrative>
85
85
  <concepts>${X.concepts.join(", ")}</concepts>
@@ -108,7 +108,7 @@ Respond with EXACTLY this XML format:
108
108
  <reason>Brief explanation</reason>
109
109
  </evaluation>
110
110
  </instructions>
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>
111
+ </conflict_evaluation>`}function M$($,V){let J=[...$.filesRead,...$.filesModified],X=V?V.entityTypes.join(", "):"technology, library, pattern, concept, file, person, project, other",Z=V?V.relationshipTypes.join(", "):"uses, depends_on, implements, extends, related_to, replaces, configures";return`<entity_extraction>
112
112
  <observation>
113
113
  <title>${$.title}</title>
114
114
  <type>${$.type}</type>
@@ -123,7 +123,7 @@ Respond with EXACTLY this XML format:
123
123
  Extract entities and relationships from this observation.
124
124
 
125
125
  Entity types: ${X}
126
- Relationship types: ${Q}
126
+ Relationship types: ${Z}
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,32 +137,33 @@ Respond with EXACTLY this XML format:
137
137
  </relations>
138
138
  </extraction>
139
139
  </instructions>
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)}
140
+ </entity_extraction>`}class m{shouldFailover($){let{error:V,attemptIndex:J,totalProviders:X}=$;if(P(V))return!1;if(J>=X-1)return!1;return j(V)}onFailover($){let V=$.error?.status??"unknown";if(!$.nextProvider)return;console.error(`[open-mem] Provider ${$.provider} failed (${V}), falling over to ${$.nextProvider}`)}}class l{specificationVersion;provider;modelId;supportedUrls;providers;policy;constructor($,V=new m){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(Z){if(V=Z,P(Z))throw Z;let H=this.providers[J+1]?.name,Y={error:Z,provider:X.name,nextProvider:H,attemptIndex:J,totalProviders:this.providers.length};if(this.policy.shouldFailover(Y)){this.policy.onFailover(Y);continue}throw this.policy.onFinalFailure?.(Y),Z}}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(Z){if(V=Z,P(Z))throw Z;let H=this.providers[J+1]?.name,Y={error:Z,provider:X.name,nextProvider:H,attemptIndex:J,totalProviders:this.providers.length};if(this.policy.shouldFailover(Y)){this.policy.onFailover(Y);continue}throw this.policy.onFinalFailure?.(Y),Z}}throw V}}var a$={"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 e$($){if($.includes("."))return $;return a$[$]||`us.anthropic.${$}-v1:0`}function _$($){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()(e$($.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 A$($){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 $V={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 VV($){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 D($){if(!$.fallbackProviders||$.fallbackProviders.length===0)return[];return $.fallbackProviders.map((V)=>({provider:V,model:$V[V]??"gemini-2.5-flash-lite",apiKey:VV(V)}))}function L($,V=[],J){let X=_$($);if(V.length===0)return X;let Z=[{name:$.provider,model:X},...V.map((H)=>({name:H.provider,model:_$(H)}))];return new l(Z,J)}var JV={"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},j$=0;async function O($,V){if(!V)return;let J=JV[$]||5,X=Math.ceil(60000/J)+100,H=Date.now()-j$;if(H<X){let Y=X-H;await new Promise((K)=>setTimeout(K,Y))}j$=Date.now()}class f{model;config;_generate=XV;constructor($){this.config=$,this.model=null;let V=$.provider!=="bedrock";if($.compressionEnabled&&(!V||$.apiKey))try{this.model=L({provider:$.provider,model:$.model,apiKey:$.apiKey},D($))}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),Z=V.length>f.MAX_INPUT_LENGTH?`${V.substring(0,f.MAX_INPUT_LENGTH)}
141
141
 
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(`
142
+ [... truncated ...]`:V,H=z$($,Z,J),Y=2;for(let K=0;K<=Y;K++)try{if(this.config.provider==="google")await O(this.config.model,this.config.rateLimitingEnabled);let{text:Q}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:H}),G=G$(Q);if(G)G.discoveryTokens=X;return G}catch(Q){if(j(Q)&&K<Y){let G=2**K*1000;await C(G);continue}return null}return null}async compressBatch($){let V=new Map;for(let J=0;J<$.length;J++){let X=$[J],Z=await this.compress(X.toolName,X.toolOutput,X.sessionContext);if(V.set(X.callId,Z),J<$.length-1)await C(200)}return V}createFallbackObservation($,V){let J=YV(V),X=ZV[$]??"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 ZV={Read:"discovery",Write:"change",Edit:"change",Bash:"change",Glob:"discovery",Grep:"discovery"},HV=/(?:^|\s)((?:\.\/|\/|src\/|tests\/|lib\/)\S+\.\w+)/gm;function YV($){let V=[];for(let J of $.matchAll(HV))V.push(J[1]);return[...new Set(V)]}import{generateText as KV}from"ai";class c{model;config;_generate=KV;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=L({provider:$.provider,model:$.model,apiKey:$.apiKey},D($))}catch{}}async evaluate($,V){if(!this.model||V.length===0)return null;let J=N$($,V),X=2;for(let Z=0;Z<=X;Z++)try{if(this.config.provider==="google")await O(this.config.model,this.config.rateLimitingEnabled);let{text:H}=await this._generate({model:this.model,maxOutputTokens:512,prompt:J});return W$(H)}catch(H){if(j(H)&&Z<X){let Y=2**Z*1000;await C(Y);continue}return null}return null}}import{generateText as QV}from"ai";class d{model;config;_generate=QV;constructor($){if(this.config=$,this.model=null,$.provider==="bedrock"||$.apiKey)try{this.model=L({provider:$.provider,model:$.model,apiKey:$.apiKey},D($))}catch{}}async extract($){if(!this.model)return null;let V=M$($),J=2;for(let X=0;X<=J;X++)try{if(this.config.provider==="google")await O(this.config.model,this.config.rateLimitingEnabled);let{text:Z}=await this._generate({model:this.model,maxOutputTokens:1024,prompt:V});return U$(Z)}catch(Z){if(j(Z)&&X<J){let H=2**X*1000;await C(H);continue}return null}return null}}import{generateText as GV}from"ai";class n{model;config;_generate=GV;constructor($){this.config=$,this.model=null;let V=$.provider!=="bedrock";if($.compressionEnabled&&(!V||$.apiKey))try{this.model=L({provider:$.provider,model:$.model,apiKey:$.apiKey},D($))}catch{}}async summarize($,V){if(V.length===0)return null;if(!this.config.compressionEnabled||!this.model)return this.createFallbackSummary(V);let J=B$(V.map((X)=>({type:X.type,title:X.title,narrative:X.narrative})),$);try{if(this.config.provider==="google")await O(this.config.model,this.config.rateLimitingEnabled);let{text:X}=await this._generate({model:this.model,maxOutputTokens:this.config.maxTokensPerCompression,prompt:J}),Z=F$(X);if(!Z)return this.createFallbackSummary(V);return Z}catch{return this.createFallbackSummary(V)}}createFallbackSummary($){let V=new Set,J=new Set,X=[];for(let K of $){for(let Q of K.filesModified)V.add(Q);for(let Q of K.concepts)J.add(Q);if(K.type==="decision")X.push(K.title)}let Z=new Map;for(let K of $)Z.set(K.type,(Z.get(K.type)??0)+1);let H=Array.from(Z.entries()).map(([K,Q])=>`${Q} ${K}${Q>1?"s":""}`).join(", "),Y=Array.from(J).slice(0,5).join(", ");return{summary:`Session with ${$.length} observations: ${H}. Files modified: ${V.size}. Key concepts: ${Y}.`,keyDecisions:X.slice(0,5),filesModified:Array.from(V),concepts:Array.from(J)}}shouldSummarize($){return $>=2}}import{existsSync as DV,readFileSync as LV}from"fs";import{join as MV}from"path";import{existsSync as FV,readdirSync as WV,readFileSync as UV}from"fs";import{join as zV}from"path";var q={id:"code",name:"Code",description:"Default coding workflow mode",observationTypes:["decision","bugfix","feature","refactor","discovery","change"],conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"],entityTypes:["technology","library","pattern","concept","file","person","project","other"],relationshipTypes:["uses","depends_on","implements","extends","related_to","replaces","configures"]};function T($){return{...$,observationTypes:[...$.observationTypes],conceptVocabulary:[...$.conceptVocabulary],entityTypes:[...$.entityTypes],relationshipTypes:[...$.relationshipTypes],promptOverrides:$.promptOverrides?{...$.promptOverrides}:void 0}}function BV($){if(!$||typeof $!=="object")return!1;let V=$,J=(Z)=>Array.isArray(Z)&&Z.every((H)=>typeof H==="string"),X=(Z)=>typeof Z==="object"&&Z!==null&&!Array.isArray(Z)&&Object.values(Z).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 NV($){return typeof $.name==="string"&&typeof $.description==="string"&&Array.isArray($.observationTypes)&&Array.isArray($.conceptVocabulary)&&Array.isArray($.entityTypes)&&Array.isArray($.relationshipTypes)}function D$($,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 s{modesDir;constructor($){this.modesDir=$}loadAllRaw(){let $=new Map;if(!FV(this.modesDir))return $;for(let V of WV(this.modesDir)){if(!V.endsWith(".json"))continue;let J=zV(this.modesDir,V);try{let X=UV(J,"utf-8"),Z=JSON.parse(X);if(!BV(Z))continue;if($.has(Z.id))console.warn(`[open-mem] Duplicate mode id "${Z.id}" in ${J}; overriding previous definition.`);$.set(Z.id,Z)}catch{}}return $}resolveById($,V){let J=new Set,X=!1,Z=(Y)=>{if(J.has(Y))return X=!0,T(q);J.add(Y);let K=V.get(Y);if(!K)return T(q);if(!K.extends){if(!NV(K))return T(q);return D$(T(q),K)}let Q=Z(K.extends);if(X)return T(q);return D$(Q,K)},H=Z($);return X?T(q):T(H)}}var _V=MV(import.meta.dir,"."),AV=new s(_V),w=null;function jV(){if(w)return w;return w=AV.loadAllRaw(),w}function L$(){return[...jV().keys()].sort()}var OV={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,folderContextMode:"single",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1,fallbackProviders:void 0,mode:"code"};function SV(){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 CV($){let V=`${$}/.open-mem/config.json`;if(!DV(V))return{};try{let J=LV(V,"utf-8"),X=JSON.parse(J);if(!X||typeof X!=="object"||Array.isArray(X))return{};return X}catch{return{}}}function RV($){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 O$($,V){let J=CV($),X=SV(),Z={...OV,...J,...X,...V};if(!Z.dbPath.startsWith("/"))Z.dbPath=`${$}/${Z.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!V?.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=RV(Z.provider);if(Z.mode&&!L$().includes(Z.mode))Z.mode="code";return Z}import{existsSync as M2,mkdirSync as TV,readFileSync as _2,unlinkSync as EV,writeFileSync as yV}from"fs";function S$($){let V=$.lastIndexOf("/");if(V>0){let J=$.substring(0,V);TV(J,{recursive:!0})}yV($,String(process.pid),"utf-8")}function C$($){try{return process.kill($,0),!0}catch(V){if(V instanceof Error&&"code"in V&&V.code==="EPERM")return!0;return!1}}function R$($){try{EV($)}catch{}}function T$($){let V=$.lastIndexOf("/");if(V>=0)return`${$.substring(0,V)}/worker.pid`;return"worker.pid"}class i{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 f$}from"bun:sqlite";import{existsSync as gV,mkdirSync as pV}from"fs";import*as v$ from"sqlite-vec";import{closeSync as qV,fsyncSync as xV,openSync as IV,readFileSync as kV,unlinkSync as y$,writeFileSync as PV}from"fs";import{hostname as q$}from"os";var x$="plugin";class u extends Error{lockPath;role;waitDurationMs;owner;constructor($){super(`Timed out acquiring advisory write lock after ${$.waitDurationMs}ms (role=${$.role}, lockPath=${$.lockPath})`);this.name="AdvisoryLockTimeoutError",this.lockPath=$.lockPath,this.role=$.role,this.waitDurationMs=$.waitDurationMs,this.owner=$.owner}}var fV=5000,hV=50,x=new Map;function vV($){if($<=0)return;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,$)}function E$($,V){if(typeof $!=="number"||!Number.isFinite($)||$<=0)return V;return Math.floor($)}function I$($){try{let V=kV($,"utf8").trim();if(!V)return null;let J=JSON.parse(V);if(typeof J!=="object"||J===null||typeof J.pid!=="number"||typeof J.role!=="string"||typeof J.hostname!=="string"||typeof J.acquiredAt!=="string")return null;return{pid:J.pid,role:J.role,hostname:J.hostname,acquiredAt:J.acquiredAt,ownerId:typeof J.ownerId==="string"?J.ownerId:void 0}}catch{return null}}function wV($,V){if(!$||!V)return!1;return $.pid===V.pid&&$.role===V.role&&$.hostname===V.hostname&&$.acquiredAt===V.acquiredAt&&$.ownerId===V.ownerId}function uV($,V){if(!V)return!1;if(V.hostname!==q$())return!1;if(C$(V.pid))return!1;let J=I$($);if(!wV(J,V))return!1;try{return y$($),!0}catch(X){if(X.code==="ENOENT")return!1;throw X}}function r($,V){qV(V);try{y$($)}catch(J){if(J.code!=="ENOENT")throw J}}function k$($){return`${$}.write.lock`}function bV($,V){let J=V.now??Date.now,X=E$(V.timeoutMs,fV),Z=E$(V.retryIntervalMs,hV),H=x.get($);if(H){H.count+=1;let G=!1;return{lockPath:$,role:V.role,waitDurationMs:0,reentrant:!0,release:()=>{if(G)return;G=!0;let F=x.get($);if(!F)return;if(F.count-=1,F.count===0)x.delete($),r($,F.fd)}}}let Y={pid:process.pid,role:V.role,hostname:q$(),acquiredAt:new Date(J()).toISOString(),ownerId:V.ownerId},K=J(),Q=null;for(;;)try{let G=IV($,"wx");try{PV(G,JSON.stringify(Y),"utf8"),xV(G)}catch(W){throw r($,G),W}x.set($,{count:1,fd:G});let F=!1;return{lockPath:$,role:V.role,waitDurationMs:J()-K,reentrant:!1,release:()=>{if(F)return;F=!0;let W=x.get($);if(!W)return;if(W.count-=1,W.count===0)x.delete($),r($,W.fd)}}}catch(G){if(G.code!=="EEXIST")throw G;if(Q=I$($),uV($,Q))continue;let W=J()-K;if(W>=X)throw new u({lockPath:$,role:V.role,waitDurationMs:W,owner:Q});vV(Math.min(Z,X-W))}}function P$($,V,J){let X=bV($,V);try{return J()}finally{X.release()}}var mV=new Set(["SQLITE_BUSY","SQLITE_LOCKED","SQLITE_IOERR","SQLITE_IOERR_VNODE","SQLITE_IOERR_READ","SQLITE_IOERR_WRITE","SQLITE_IOERR_SHORT_READ","SQLITE_IOERR_FSYNC","SQLITE_PROTOCOL"]),lV=3,h$=50,cV=new Set(["INSERT","UPDATE","DELETE","REPLACE","CREATE","ALTER","DROP","VACUUM","REINDEX","ANALYZE","ATTACH","DETACH"]),dV=new Set(["WAL_CHECKPOINT","OPTIMIZE","INCREMENTAL_VACUUM","SHRINK_MEMORY"]),nV=/^(?:\s+|--[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)+/;function sV($){let V=$;for(;;){let J=V.replace(nV,"");if(J===V)return V.trimStart();V=J}}function iV($){let V=[],J=0,X=!1,Z=!1,H=!1,Y=!1,K=!1,Q=!1;for(let F=0;F<$.length;F+=1){let W=$[F],B=$[F+1];if(K){if(W===`
143
+ `)K=!1;continue}if(Q){if(W==="*"&&B==="/")Q=!1,F+=1;continue}if(X){if(W==="'")if(B==="'")F+=1;else X=!1;continue}if(Z){if(W==='"')if(B==='"')F+=1;else Z=!1;continue}if(H){if(W==="`")H=!1;continue}if(Y){if(W==="]")Y=!1;continue}if(W==="-"&&B==="-"){K=!0,F+=1;continue}if(W==="/"&&B==="*"){Q=!0,F+=1;continue}if(W==="'"){X=!0;continue}if(W==='"'){Z=!0;continue}if(W==="`"){H=!0;continue}if(W==="["){Y=!0;continue}if(W===";"){let N=$.slice(J,F).trim();if(N.length>0)V.push(N);J=F+1}}let G=$.slice(J).trim();if(G.length>0)V.push(G);return V}function rV($){let V=sV($);if(!V)return!1;let J=V.toUpperCase();if(/\bRETURNING\b/.test(J))return!0;if(J.startsWith("PRAGMA")){if(/^PRAGMA\s+(?:[A-Z0-9_]+\.)?[A-Z0-9_]+\s*=/.test(J))return!0;let Z=/^PRAGMA\s+(?:[A-Z0-9_]+\.)?([A-Z0-9_]+)/.exec(J)?.[1];if(!Z)return!1;return dV.has(Z)}let X=/^[A-Z]+/.exec(J)?.[0];if(!X)return!1;if(cV.has(X))return!0;if(X==="WITH")return/\b(INSERT|UPDATE|DELETE|REPLACE)\b/.test(J);return!1}function o($){let V=iV($);if(V.length===0)return!1;for(let J of V)if(rV(J))return!0;return!1}var oV=new Set(["PASSIVE","FULL","RESTART","TRUNCATE"]);function h($){if($ instanceof Error){let V=$.code;return{code:typeof V==="string"?V:"UNKNOWN",message:$.message}}return{code:"UNKNOWN",message:String($)}}function tV($){if($&&typeof $==="object"&&"code"in $){let V=$.code;return mV.has(V)}return!1}class b{db;dbPath;advisoryWriteLockPath;processRole;transactionDepth=0;_hasVectorExtension=!1;static enableExtensionSupport(){let $=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let V of $)try{if(gV(V))return f$.setCustomSQLite(V),!0}catch{return!1}return!1}constructor($,V={}){this.dbPath=$,this.processRole=V.processRole??x$,this.advisoryWriteLockPath=k$($),this.db=this.open($),this.configure()}open($){let V=$.lastIndexOf("/");if(V>0){let J=$.substring(0,V);pV(J,{recursive:!0})}return new f$($,{create:!0})}configure(){this.runConfigureStage("applyPragmas",()=>this.applyPragmas()),this.runConfigureStage("loadExtensions",()=>this.loadExtensions())}runConfigureStage($,V){try{V()}catch(J){this.throwConfigureFailure($,J)}}throwConfigureFailure($,V){let J=h(V);try{this.db.close()}catch{}throw console.error("[open-mem] Database configure failed (non-destructive fail-safe)",{stage:$,dbPath:this.dbPath,sqliteCode:J.code,sqliteMessage:J.message,action:"startup-abort",deletionAttempted:!1}),Error(`Database startup failed during ${$} (fail-safe, non-destructive): [${J.code}] ${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{v$.load(this.db),this._hasVectorExtension=!0}catch($){let V=h($);console.warn("[open-mem] SQLite extension load skipped",{stage:"loadExtensions",dbPath:this.dbPath,sqliteCode:V.code,sqliteMessage:V.message,action:"continue-without-extension"}),this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}ensureMigrationTable(){this.db.exec(`
143
144
  CREATE TABLE IF NOT EXISTS _migrations (
144
145
  version INTEGER PRIMARY KEY,
145
146
  name TEXT NOT NULL,
146
147
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
147
148
  )
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
+ `)}migrate($){this.withAdvisoryWriteLock(this.processRole,()=>{this.ensureMigrationTable();let V=this.withRetry("migrate.applied_versions",()=>{return this.db.query("SELECT version FROM _migrations ORDER BY version").all()}),J=new Set(V.map((Z)=>Z.version)),X=$.filter((Z)=>!J.has(Z.version)).sort((Z,H)=>Z.version-H.version);for(let Z of X)this.transaction(()=>{this.exec(Z.up),this.run("INSERT INTO _migrations (version, name) VALUES ($version, $name)",[{$version:Z.version,$name:Z.name}])})})}withRetry($,V){let J=this.transactionDepth>0?0:lV,X;for(let Z=0;Z<=J;Z++)try{return V()}catch(H){if(X=H,!tV(H)||Z===J)throw H;let Y=h$*2**Z+Math.random()*h$;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Y);let K=h(H);console.warn("[open-mem] Retrying after transient SQLite error",{attempt:Z+1,maxRetries:J,operation:$,role:this.processRole,dbPath:this.dbPath,sqliteCode:K.code,sqliteMessage:K.message})}throw X}run($,V){this.withAdvisoryWriteLock(this.processRole,()=>{this.withRetry("run",()=>{let J=this.db.query($);if(V)J.run(...V);else J.run()})})}get($,V){let J=()=>{let X=this.db.query($);return V?X.get(...V):X.get()};if(o($))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("get",J));return this.withRetry("get",J)}all($,V){let J=()=>{let X=this.db.query($);return V?X.all(...V):X.all()};if(o($))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("all",J));return this.withRetry("all",J)}exec($){let V=()=>this.withRetry("exec",()=>this.db.exec($));if(o($)){this.withAdvisoryWriteLock(this.processRole,V);return}V()}transaction($){return this.withAdvisoryWriteLock(this.processRole,()=>{if(this.transactionDepth>0)return $();let V=this.db.transaction($);if(typeof V.immediate==="function"){this.transactionDepth+=1;try{return V.immediate()}finally{this.transactionDepth-=1}}this.db.exec("BEGIN IMMEDIATE"),this.transactionDepth+=1;try{let J=$();return this.db.exec("COMMIT"),J}catch(J){let X=J;try{this.db.exec("ROLLBACK")}catch(Z){if(X instanceof Error){let H=X;if(H.cause===void 0)H.cause=Z;else H.suppressed=[...H.suppressed??[],Z]}console.warn("[open-mem] Transaction rollback failed after transaction error",{dbPath:this.dbPath,originalError:h(X),rollbackError:h(Z)})}throw X}finally{this.transactionDepth-=1}})}get writeLockPath(){return this.advisoryWriteLockPath}withAdvisoryWriteLock($,V,J){try{return P$(this.advisoryWriteLockPath,{...J,role:$},V)}catch(X){if(X instanceof u)console.error("[open-mem] Advisory write lock timeout",{role:$,dbPath:this.dbPath,lockPath:X.lockPath,waitDurationMs:X.waitDurationMs,owner:X.owner});throw X}}checkpointWal($="PASSIVE"){let V=typeof $==="string"?$.toUpperCase():"";if(!oV.has(V))throw Error(`Invalid wal_checkpoint mode: ${String($)}`);return this.withAdvisoryWriteLock(this.processRole,()=>{return this.withRetry("maintenance.wal_checkpoint",()=>{let J=this.db.query(`PRAGMA wal_checkpoint(${V})`).get();if(!J)throw Error("wal_checkpoint returned no result row");return{mode:V,busy:J.busy??0,logFrames:J.log??0,checkpointedFrames:J.checkpointed??0}})})}integrityCheck($=1){let V=Number.isFinite($)?Math.max(1,Math.floor($)):1;return this.withRetry("maintenance.integrity_check",()=>{let J=this.db.query(`PRAGMA integrity_check(${V})`).all();if(J.length===0)throw Error("integrity_check returned no result rows");let X=J.map((Z)=>Object.values(Z).find((H)=>typeof H==="string")).filter((Z)=>typeof Z==="string").map((Z)=>Z.trim()).filter((Z)=>Z.length>0);if(X.length===0)throw Error("integrity_check returned no diagnostic messages");return{ok:X.length===1&&X[0].toLowerCase()==="ok",messages:X,maxErrors:V}})}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function w$($,V){return new b($,V)}import{randomUUID as u$}from"crypto";class t{db;constructor($){this.db=$}upsertEntity($,V){let J=u$(),X=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
149
150
  VALUES (?, ?, ?, ?, ?, 1)
150
151
  ON CONFLICT(name, entity_type) DO UPDATE SET
151
152
  mention_count = mention_count + 1,
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
+ last_seen_at = ?`,[J,$,V,X,X,X]);let Z=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[$,V]);if(!Z)throw Error(`Failed to upsert entity: ${$} (${V})`);return this.mapEntityRow(Z)}createRelation($,V,J,X){let Z=u$(),H=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
153
154
  (id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
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.*
155
+ VALUES (?, ?, ?, ?, ?, ?)`,[Z,$,V,J,X,H])}catch{return null}let Y=this.db.get(`SELECT * FROM entity_relations
156
+ WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[$,V,J]);return Y?this.mapRelationRow(Y):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
157
  FROM entities e
157
158
  JOIN entities_fts fts ON e._rowid = fts.rowid
158
159
  WHERE entities_fts MATCH ?
159
160
  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
161
+ WHERE source_entity_id = ? OR target_entity_id = ?`,[$,$]).map((J)=>this.mapRelationRow(J))}traverseRelations($,V=1){let J=Math.min(V,2),X=100,Z=new Set,H=[{id:$,currentDepth:0}];Z.add($);while(H.length>0){if(Z.size>=100)break;let Y=H.shift();if(!Y)continue;if(Y.currentDepth>=J)continue;let K=this.getRelationsFor(Y.id);for(let Q of K){let G=Q.sourceEntityId===Y.id?Q.targetEntityId:Q.sourceEntityId;if(!Z.has(G))Z.add(G),H.push({id:G,currentDepth:Y.currentDepth+1})}}return Z}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 eV}from"crypto";import{embed as aV}from"ai";async function a($,V){try{let{embedding:J}=await aV({model:$,value:V});return J}catch{return null}}function b$($,V){if($.length!==V.length||$.length===0)return 0;let J=0,X=0,Z=0;for(let Y=0;Y<$.length;Y++)J+=$[Y]*V[Y],X+=$[Y]*$[Y],Z+=V[Y]*V[Y];let H=Math.sqrt(X)*Math.sqrt(Z);if(H===0)return 0;return J/H}function e($){let V=[$.title,$.narrative];if($.concepts.length>0)V.push($.concepts.join(", "));return V.join(`
162
+ `)}function $J($){return $.replace(/[%_\\]/g,"\\$&")}class $${db;constructor($){this.db=$}create($){let V=eV(),J=new Date().toISOString(),X=$.discoveryTokens??0,Z=$.importance??3,H=$.scope??"project";return this.db.run(`INSERT INTO observations
162
163
  (id, session_id, scope, type, title, subtitle, facts, narrative,
163
164
  concepts, files_read, files_modified, raw_tool_output,
164
165
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
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
+ 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,Z,null,null]),{...$,id:V,scope:H,createdAt:J,discoveryTokens:X,importance:Z,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation($){this.db.run(`INSERT INTO observations
166
167
  (id, session_id, scope, type, title, subtitle, facts, narrative,
167
168
  concepts, files_read, files_modified, raw_tool_output,
168
169
  tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
@@ -171,7 +172,7 @@ Respond with EXACTLY this XML format:
171
172
  JOIN sessions s ON o.session_id = s.id
172
173
  WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
173
174
  ORDER BY o.created_at DESC
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
+ 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 Z=V>0?this.db.all(`SELECT o.*
175
176
  FROM observations o
176
177
  JOIN sessions s ON o.session_id = s.id
177
178
  WHERE s.project_path = ? AND o.created_at < ?
@@ -183,17 +184,17 @@ Respond with EXACTLY this XML format:
183
184
  WHERE s.project_path = ? AND o.created_at > ?
184
185
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
185
186
  ORDER BY o.created_at ASC
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
+ LIMIT ?`,[X,$,J]):[];return[...Z,...H].map((Y)=>this.mapRow(Y))}listByProject($,V={}){let{limit:J=50,offset:X=0,type:Z,state:H,sessionId:Y}=V,K=`SELECT o.*
187
188
  FROM observations o
188
189
  JOIN sessions s ON o.session_id = s.id
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
+ WHERE s.project_path = ?`,Q=[$];if(Y)K+=" AND o.session_id = ?",Q.push(Y);if(Z)K+=" AND o.type = ?",Q.push(Z);if(H==="current")K+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(H==="superseded")K+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(H==="tombstoned")K+=" AND o.deleted_at IS NOT NULL";else K+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return K+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",Q.push(J,X),this.db.all(K,Q).map((G)=>this.mapRow(G))}search($){let V=!!$.projectPath,J=`
190
191
  SELECT o.*, rank
191
192
  FROM observations o
192
193
  JOIN observations_fts fts ON o._rowid = fts.rowid
193
194
  ${V?"JOIN sessions s ON o.session_id = s.id":""}
194
195
  WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
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.*
196
+ `,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 Z=$.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");J+=` AND (${Z.join(" OR ")})`;for(let H of $.concepts)X.push(H)}if($.files&&$.files.length>0){let Z=$.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
197
+ OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);J+=` AND (${Z.join(" OR ")})`;for(let H of $.files){let Y=`%${$J(H)}%`;X.push(Y,Y)}}return J+=" ORDER BY rank LIMIT ? OFFSET ?",X.push($.limit??10),X.push($.offset??0),this.db.all(J,X).map((Z)=>({observation:this.mapRow(Z),rank:Z.rank,snippet:Z.title}))}searchByConcept($,V=10,J){let X=!!J,Z=`SELECT o.*
197
198
  FROM observations o
198
199
  JOIN observations_fts fts ON o._rowid = fts.rowid
199
200
  ${X?"JOIN sessions s ON o.session_id = s.id":""}
@@ -201,7 +202,7 @@ Respond with EXACTLY this XML format:
201
202
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
202
203
  ${X?"AND s.project_path = ?":""}
203
204
  ORDER BY rank
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
+ LIMIT ?`,Y=[`concepts:"${$.replace(/"/g,'""')}"`];if(X&&J)Y.push(J);return Y.push(V),this.db.all(Z,Y).map((K)=>this.mapRow(K))}searchByFile($,V=10,J){let X=!!J,Z=`SELECT o.*
205
206
  FROM observations o
206
207
  JOIN observations_fts fts ON o._rowid = fts.rowid
207
208
  ${X?"JOIN sessions s ON o.session_id = s.id":""}
@@ -209,22 +210,22 @@ Respond with EXACTLY this XML format:
209
210
  AND o.superseded_by IS NULL AND o.deleted_at IS NULL
210
211
  ${X?"AND s.project_path = ?":""}
211
212
  ORDER BY rank
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
+ LIMIT ?`,H=[`files_read:"${$.replace(/"/g,'""')}" OR files_modified:"${$.replace(/"/g,'""')}"`];if(X&&J)H.push(J);return H.push(V),this.db.all(Z,H).map((Y)=>this.mapRow(Y))}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
214
  FROM observations o
214
215
  JOIN sessions s ON o.session_id = s.id
215
216
  WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
216
217
  ORDER BY o.created_at DESC
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
+ 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 Z=this.db.all(`SELECT id, embedding FROM observations
218
219
  WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
219
220
  ORDER BY created_at DESC
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
+ LIMIT 200`,[V]),H=[];for(let Y of Z)try{let K=JSON.parse(Y.embedding);if(!Array.isArray(K)||K.length!==$.length)continue;let Q=b$($,K);if(Q>=J)H.push({id:Y.id,similarity:Q})}catch{}return H.sort((Y,K)=>K.similarity-Y.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 Z of V)try{let H=JSON.parse(Z.embedding);if(!Array.isArray(H)||H.length!==$){X++;continue}this.insertVecEmbedding(Z.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
222
  FROM observation_embeddings
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
+ 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($),Z=Math.max(J*5,V.length),H=this.db.all(`SELECT observation_id, distance
223
224
  FROM observation_embeddings
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
+ WHERE embedding MATCH ? AND k = ?`,[X,Z]),Y=new Set(V);return H.filter((K)=>Y.has(K.observation_id)).slice(0,J).map((K)=>({observationId:K.observation_id,distance:K.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 Z=this.getByIdIncludingArchived(X[0].revisionOf);if(!Z||J.has(Z.id))break;X.unshift(Z),J.add(Z.id)}while(X[X.length-1].supersededBy){let Z=X[X.length-1].supersededBy;if(!Z)break;let H=this.getByIdIncludingArchived(Z);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
226
  WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
226
227
  AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
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
+ 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 VJ}from"crypto";class V${db;constructor($){this.db=$}create($){let V=VJ(),J=new Date().toISOString();return this.db.run(`INSERT INTO pending_messages
228
229
  (id, session_id, tool_name, tool_output, call_id, created_at)
229
230
  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
231
  WHERE status = 'processing'
@@ -232,7 +233,7 @@ Respond with EXACTLY this XML format:
232
233
  RETURNING id`,[`-${$}`]).length}deleteCompletedOlderThan($){return this.db.all(`DELETE FROM pending_messages
233
234
  WHERE status = 'completed'
234
235
  AND created_at < datetime('now', '-' || ? || ' days')
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
+ 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 JJ=[{version:1,name:"create-schema",up:`
236
237
  -- Sessions table
237
238
  CREATE TABLE IF NOT EXISTS sessions (
238
239
  _rowid INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -526,11 +527,11 @@ Respond with EXACTLY this XML format:
526
527
  INSERT INTO entities_fts(rowid, name, entity_type)
527
528
  VALUES (new._rowid, new.name, new.entity_type);
528
529
  END;
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
+ `}];function g$($,V){if($.migrate(JJ),V?.hasVectorExtension&&V?.embeddingDimension&&V.embeddingDimension>0)XJ($,V.embeddingDimension)}function XJ($,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
531
  observation_id TEXT PRIMARY KEY,
531
532
  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
533
+ )`);$.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(V)])}class J${db;constructor($){this.db=$}create($,V){let J=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
534
+ 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 ZJ}from"crypto";class X${db;constructor($){this.db=$}create($){let V=ZJ(),J=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
534
535
  (id, session_id, summary, key_decisions, files_modified,
535
536
  concepts, created_at, token_count,
536
537
  request, investigated, learned, completed, next_steps)
@@ -543,4 +544,4 @@ Respond with EXACTLY this XML format:
543
544
  JOIN summaries_fts fts ON ss._rowid = fts.rowid
544
545
  WHERE summaries_fts MATCH ?
545
546
  ORDER BY rank
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();
547
+ 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 Z${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,Z,H,Y,K=null,Q=null,G=null,F=null,W=null){this.config=$;this.compressor=V;this.summarizer=J;this.pendingRepo=X;this.observationRepo=Z;this.sessionRepo=H;this.summaryRepo=Y;this.embeddingModel=K;this.conflictEvaluator=Q;this.entityExtractor=G;this.entityRepo=F;this.observer=W}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 Z of X)try{this.pendingRepo.markProcessing(Z.id);let Y=await this.compressor.compress(Z.toolName,Z.toolOutput)??this.compressor.createFallbackObservation(Z.toolName,Z.toolOutput),K=!1,Q=null;if(this.embeddingModel)try{let F=e({title:Y.title,narrative:Y.narrative,concepts:Y.concepts}),W=await a(this.embeddingModel,F);if(W){let B=this.config.conflictResolutionEnabled&&this.conflictEvaluator,N=this.config.conflictSimilarityBandLow??0.7,I=this.config.conflictSimilarityBandHigh??0.92;if(B){let E=this.observationRepo.findSimilar(W,Y.type,N,5),p=E.find((v)=>v.similarity>I);if(p)console.log(`[open-mem] Dedup: skipping duplicate of ${p.id} (similarity: ${p.similarity.toFixed(3)})`),K=!0;else{let v=E.filter((k)=>k.similarity>=N&&k.similarity<=I);if(v.length>0)try{let k=v.map((M)=>{let y=this.observationRepo.getById(M.id);return y?{id:y.id,title:y.title,narrative:y.narrative,concepts:y.concepts,type:y.type}:null}).filter((M)=>M!==null);if(k.length>0&&this.conflictEvaluator){let M=await this.conflictEvaluator.evaluate({title:Y.title,narrative:Y.narrative,concepts:Y.concepts,type:Y.type},k);if(M&&M.outcome==="duplicate")console.log(`[open-mem] Conflict eval: duplicate (${M.reason})`),K=!0;else if(M&&M.outcome==="update"&&M.supersedesId)console.log(`[open-mem] Conflict eval: update supersedes ${M.supersedesId} (${M.reason})`),Q=M.supersedesId}}catch{}}}else{let E=this.observationRepo.findSimilar(W,Y.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)})`),K=!0}}}catch{}if(K){this.pendingRepo.markCompleted(Z.id);continue}let G=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:R(`${Y.title} ${Y.narrative} ${Y.facts.join(" ")}`),discoveryTokens:Y.discoveryTokens??R(Z.toolOutput),importance:Y.importance??3});if(this.embeddingModel)try{let F=e({title:G.title,narrative:G.narrative,concepts:G.concepts}),W=await a(this.embeddingModel,F);if(W)this.observationRepo.setEmbedding(G.id,W)}catch{}if(Q)try{this.observationRepo.supersede(Q,G.id),console.log(`[open-mem] Superseded observation ${Q} with ${G.id}`)}catch(F){console.error(`[open-mem] Failed to supersede ${Q}:`,F)}if(this.config.entityExtractionEnabled&&this.entityExtractor&&this.entityRepo)try{let F=await this.entityExtractor.extract({title:G.title,narrative:G.narrative,concepts:G.concepts,facts:G.facts,filesRead:G.filesRead,filesModified:G.filesModified,type:G.type});if(F){let W=new Map;for(let B of F.entities){let N=this.entityRepo.upsertEntity(B.name,B.entityType);W.set(B.name,N.id),this.entityRepo.linkObservation(N.id,G.id)}for(let B of F.relations){let N=W.get(B.sourceName),I=W.get(B.targetName);if(N&&I)this.entityRepo.createRelation(N,I,B.relationship,G.id)}}}catch{}this.sessionRepo.incrementObservationCount(Z.sessionId),this.pendingRepo.markCompleted(Z.id),$++}catch(H){this.pendingRepo.markFailed(Z.id,String(H)),V++,this.observer?.onItemFailed?.({pendingId:Z.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 Z=this.summaryRepo.create({sessionId:$,summary:X.summary,keyDecisions:X.keyDecisions,filesModified:X.filesModified,concepts:X.concepts,tokenCount:R(X.summary)});this.sessionRepo.setSummary($,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 p$}from"child_process";import{dirname as HJ,resolve as m$}from"path";function YJ($){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 Z=X.stdout.trim(),H=m$($,J),Y=m$($,Z);if(H===Y)return null;let K=HJ(H);if(K===H||K==="/")return null;return K}catch{return null}}function l$($){return YJ($)??$}var QJ=5000,{values:H$}=KJ({options:{project:{type:"string",short:"p"},"poll-interval":{type:"string"}},strict:!1}),n$=typeof H$.project==="string"?H$.project:null;if(!n$)console.error("Usage: open-mem-daemon --project <path> [--poll-interval <ms>]"),process.exit(1);var c$=H$["poll-interval"],Y$=typeof c$==="string"?Number.parseInt(c$,10):QJ;if(Number.isNaN(Y$)||Y$<100)console.error("--poll-interval must be a number >= 100"),process.exit(1);var GJ=l$(n$),z=O$(GJ);b.enableExtensionSupport();var S=w$(z.dbPath,{processRole:"daemon"});g$(S,{hasVectorExtension:S.hasVectorExtension,embeddingDimension:z.embeddingDimension});var FJ=new V$(S),WJ=new $$(S),UJ=new J$(S),zJ=new X$(S),BJ=new f(z),NJ=new n(z),K$=z.provider!=="bedrock",MJ=z.compressionEnabled&&(!K$||z.apiKey)?A$({provider:z.provider,model:z.model,apiKey:z.apiKey}):null,_J=z.conflictResolutionEnabled&&(!K$||z.apiKey)?new c({provider:z.provider,apiKey:z.apiKey,model:z.model,rateLimitingEnabled:z.rateLimitingEnabled}):null,AJ=z.entityExtractionEnabled&&(!K$||z.apiKey)?new d({provider:z.provider,apiKey:z.apiKey,model:z.model,rateLimitingEnabled:z.rateLimitingEnabled}):null,jJ=new t(S),DJ=new Z$(z,BJ,NJ,FJ,WJ,UJ,zJ,MJ,_J,AJ,jJ),s$=T$(z.dbPath);S$(s$);var g=new i({queueProcessor:DJ,pollIntervalMs:Y$});if(process.send)process.on("message",($)=>{g.handleMessage($)});process.on("SIGUSR1",()=>{g.handleMessage("PROCESS_NOW")});var d$=!1,Q$=()=>{if(d$)return;d$=!0,g.stop(),R$(s$),S.close()};process.on("SIGTERM",()=>{Q$(),process.exit(0)});process.on("SIGINT",()=>{Q$(),process.exit(0)});process.on("beforeExit",Q$);g.start();