@membank/core 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -1 +1,3 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./global-scope-CgOQm1jp.cjs`);exports.GLOBAL_PROJECT_ID=e.t,exports.GLOBAL_PROJECT_NAME=e.n,exports.GLOBAL_SCOPE_HASH=e.r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./global-scope-CgOQm1jp.cjs`);function t(e,t){let n=e.split(`
2
+ `),r=t.split(`
3
+ `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=1;e<=i;e++){let t=o[e],i=o[e-1];if(!(t===void 0||i===void 0))for(let o=1;o<=a;o++)n[e-1]===r[o-1]?t[o]=(i[o-1]??0)+1:t[o]=Math.max(i[o]??0,t[o-1]??0)}let s=[],c=i,l=a;for(;c>0||l>0;){let e=n[c-1],t=r[l-1],i=o[c],a=o[c-1];c>0&&l>0&&e===t?(s.push({kind:`context`,line:e??``}),c--,l--):l>0&&(c===0||(i?.[l-1]??0)>=(a?.[l]??0))?(s.push({kind:`added`,line:t??``}),l--):(s.push({kind:`removed`,line:e??``}),c--)}return s.reverse(),s}exports.GLOBAL_PROJECT_ID=e.t,exports.GLOBAL_PROJECT_NAME=e.n,exports.GLOBAL_SCOPE_HASH=e.r,exports.diffLines=t;
package/dist/client.d.cts CHANGED
@@ -1,2 +1,17 @@
1
1
  import { n as GLOBAL_PROJECT_NAME, r as GLOBAL_SCOPE_HASH, t as GLOBAL_PROJECT_ID } from "./global-scope-Bv4l3n3S.cjs";
2
- export { GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH };
2
+
3
+ //#region src/diff.d.ts
4
+ type LineDiff = {
5
+ kind: "context";
6
+ line: string;
7
+ } | {
8
+ kind: "added";
9
+ line: string;
10
+ } | {
11
+ kind: "removed";
12
+ line: string;
13
+ };
14
+ declare function diffLines(a: string, b: string): LineDiff[];
15
+ //#endregion
16
+ export { GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type LineDiff, diffLines };
17
+ //# sourceMappingURL=client.d.cts.map
package/dist/client.d.mts CHANGED
@@ -1,2 +1,17 @@
1
1
  import { n as GLOBAL_PROJECT_NAME, r as GLOBAL_SCOPE_HASH, t as GLOBAL_PROJECT_ID } from "./global-scope-lgsTOiAt.mjs";
2
- export { GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH };
2
+
3
+ //#region src/diff.d.ts
4
+ type LineDiff = {
5
+ kind: "context";
6
+ line: string;
7
+ } | {
8
+ kind: "added";
9
+ line: string;
10
+ } | {
11
+ kind: "removed";
12
+ line: string;
13
+ };
14
+ declare function diffLines(a: string, b: string): LineDiff[];
15
+ //#endregion
16
+ export { GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type LineDiff, diffLines };
17
+ //# sourceMappingURL=client.d.mts.map
package/dist/client.mjs CHANGED
@@ -1 +1,4 @@
1
- import{n as e,r as t,t as n}from"./global-scope-B463kRq-.mjs";export{n as GLOBAL_PROJECT_ID,e as GLOBAL_PROJECT_NAME,t as GLOBAL_SCOPE_HASH};
1
+ import{n as e,r as t,t as n}from"./global-scope-B463kRq-.mjs";function r(e,t){let n=e.split(`
2
+ `),r=t.split(`
3
+ `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=1;e<=i;e++){let t=o[e],i=o[e-1];if(!(t===void 0||i===void 0))for(let o=1;o<=a;o++)n[e-1]===r[o-1]?t[o]=(i[o-1]??0)+1:t[o]=Math.max(i[o]??0,t[o-1]??0)}let s=[],c=i,l=a;for(;c>0||l>0;){let e=n[c-1],t=r[l-1],i=o[c],a=o[c-1];c>0&&l>0&&e===t?(s.push({kind:`context`,line:e??``}),c--,l--):l>0&&(c===0||(i?.[l-1]??0)>=(a?.[l]??0))?(s.push({kind:`added`,line:t??``}),l--):(s.push({kind:`removed`,line:e??``}),c--)}return s.reverse(),s}export{n as GLOBAL_PROJECT_ID,e as GLOBAL_PROJECT_NAME,t as GLOBAL_SCOPE_HASH,r as diffLines};
4
+ //# sourceMappingURL=client.mjs.map
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=require(`./global-scope-CgOQm1jp.cjs`);let l=require(`node:crypto`),u=require(`zod`),d=require(`node:fs`),f=require(`node:os`),p=require(`node:path`),m=require(`better-sqlite3`);m=s(m,1);let h=require(`sqlite-vec`);h=s(h,1);let g=require(`node:events`),_=require(`@huggingface/transformers`),v=require(`@anthropic-ai/claude-agent-sdk`),ee=require(`node:fs/promises`),te=require(`node:child_process`),ne=require(`node:util`);function re(e,t){return t.list(e)}const y=[`memory.created`,`memory.updated`,`memory.deleted`,`memory.flagged`,`memory.queried`],b=u.z.enum(y);function x(e,t){let n=new Date,r=n.toISOString();t.insert({id:(0,l.randomUUID)(),projectHash:e.projectHash,eventType:e.eventType,memoryId:e.memoryId??null,payload:e.payload??{},createdAt:r});let i=new Date(n);i.setDate(i.getDate()-30),t.prune(i.toISOString())}function ie(e){return{id:e.id,projectHash:e.project_hash,eventType:b.parse(e.event_type),memoryId:e.memory_id,payload:JSON.parse(e.payload),createdAt:e.created_at}}var S=class{#e;#t=0;#n;#r;constructor(e){this.#e=e,this.#n=e.db.prepare(`INSERT INTO activity_events (id, project_hash, event_type, memory_id, payload, created_at)
2
- VALUES (?, ?, ?, ?, ?, ?)`),this.#r=e.db.prepare(`DELETE FROM activity_events WHERE created_at < ?`)}insert(e){this.#n.run(e.id,e.projectHash,e.eventType,e.memoryId,JSON.stringify(e.payload),e.createdAt)}list(e){let t=[],n=[];e.scope!==void 0&&(t.push(`project_hash = ?`),n.push(e.scope)),e.type!==void 0&&(t.push(`event_type = ?`),n.push(e.type)),e.since!==void 0&&(t.push(`created_at >= ?`),n.push(e.since));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit===void 0?``:`LIMIT ?`;return e.limit!==void 0&&n.push(e.limit),this.#e.db.prepare(`SELECT * FROM activity_events ${r} ORDER BY created_at DESC ${i}`).all(...n).map(ie)}prune(e){let t=Date.now();t-this.#t<6e4||(this.#r.run(e),this.#t=t)}};function ae(e){return new S(e)}function oe(e){let t=new S(e);return{logEvent:e=>x(e,t)}}const C={logEvent(){}};function se(){let e=(0,p.join)((0,f.homedir)(),`.membank`,`config.json`);try{let t=(0,d.readFileSync)(e,`utf8`);return JSON.parse(t)}catch{return null}}function ce(){return se()?.synthesis?.enabled===!0}const w=[`correction`,`preference`,`decision`,`learning`,`fact`],T=u.z.enum(w),E=u.z.array(u.z.string()),D=u.z.object({id:u.z.string(),name:u.z.string(),scopeHash:u.z.string(),createdAt:u.z.string(),updatedAt:u.z.string()}),O=u.z.enum([`similarity_dedup`]),k=u.z.object({id:u.z.string(),memoryId:u.z.string(),conflictingMemoryId:u.z.string().nullable(),similarity:u.z.number(),conflictContentSnapshot:u.z.string(),reason:O,createdAt:u.z.string(),resolvedAt:u.z.string().nullable()}),A=u.z.object({id:u.z.string(),memory_id:u.z.string(),conflicting_memory_id:u.z.string().nullable(),similarity:u.z.number(),conflict_content_snapshot:u.z.string(),reason:O,created_at:u.z.string(),resolved_at:u.z.string().nullable()}),j=u.z.object({id:u.z.string(),content:u.z.string(),type:T,tags:u.z.array(u.z.string()),projects:u.z.array(D),sourceHarness:u.z.string().nullable(),accessCount:u.z.number().int().nonnegative(),pinned:u.z.boolean(),reviewEvents:u.z.array(k),createdAt:u.z.string(),updatedAt:u.z.string()}),M=u.z.object({query:u.z.string().min(1),type:T.optional(),projectHash:u.z.string().optional(),limit:u.z.number().int().positive().optional(),includePinned:u.z.boolean().optional()}),N=u.z.object({content:u.z.string().min(1),type:T,tags:u.z.array(u.z.string()).optional(),projectScope:u.z.object({hash:u.z.string(),name:u.z.string()}).optional(),sourceHarness:u.z.string().optional()}),P=u.z.object({content:u.z.string().min(1).optional(),tags:u.z.array(u.z.string()).optional(),type:T.optional()}),F=u.z.object({id:u.z.string(),scope:u.z.string(),content:u.z.string(),sourceMemoryHash:u.z.string(),synthesizedAt:u.z.string(),expiresAt:u.z.string(),inFlightSince:u.z.string().nullable(),createdAt:u.z.string(),updatedAt:u.z.string()}),le=u.z.object({stats:u.z.record(T,u.z.number()),pinnedGlobal:u.z.array(j),pinnedProject:u.z.array(j),synthesis:u.z.string().optional()}),I=u.z.object({id:u.z.string(),content:u.z.string(),type:u.z.string(),tags:u.z.string(),source:u.z.string().nullable(),access_count:u.z.number(),pinned:u.z.number(),created_at:u.z.string(),updated_at:u.z.string()}),L=u.z.object({id:u.z.string(),name:u.z.string(),scope_hash:u.z.string(),created_at:u.z.string(),updated_at:u.z.string()});function R(e,t,n=[]){return{id:e.id,content:e.content,type:T.parse(e.type),tags:E.parse(JSON.parse(e.tags)),projects:t,sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,reviewEvents:n,createdAt:e.created_at,updatedAt:e.updated_at}}function z(e){let t=A.parse(e);return{id:t.id,memoryId:t.memory_id,conflictingMemoryId:t.conflicting_memory_id,similarity:t.similarity,conflictContentSnapshot:t.conflict_content_snapshot,reason:t.reason,createdAt:t.created_at,resolvedAt:t.resolved_at}}function B(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var V=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},H=class extends V{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const ue=(0,p.join)((0,f.homedir)(),`.membank`,`memory.db`),de=[[1,`
2
+ VALUES (?, ?, ?, ?, ?, ?)`),this.#r=e.db.prepare(`DELETE FROM activity_events WHERE created_at < ?`)}insert(e){this.#n.run(e.id,e.projectHash,e.eventType,e.memoryId,JSON.stringify(e.payload),e.createdAt)}list(e){let t=[],n=[];e.scope!==void 0&&(t.push(`project_hash = ?`),n.push(e.scope)),e.type!==void 0&&(t.push(`event_type = ?`),n.push(e.type)),e.since!==void 0&&(t.push(`created_at >= ?`),n.push(e.since));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit===void 0?``:`LIMIT ?`;return e.limit!==void 0&&n.push(e.limit),this.#e.db.prepare(`SELECT * FROM activity_events ${r} ORDER BY created_at DESC ${i}`).all(...n).map(ie)}prune(e){let t=Date.now();t-this.#t<6e4||(this.#r.run(e),this.#t=t)}};function ae(e){return new S(e)}function oe(e){let t=new S(e);return{logEvent:e=>x(e,t)}}const C={logEvent(){}};function se(){let e=(0,p.join)((0,f.homedir)(),`.membank`,`config.json`);try{let t=(0,d.readFileSync)(e,`utf8`);return JSON.parse(t)}catch{return null}}function ce(){return se()?.synthesis?.enabled===!0}const w=[`correction`,`preference`,`decision`,`learning`,`fact`],T=u.z.enum(w),E=u.z.array(u.z.string()),D=u.z.object({id:u.z.string(),name:u.z.string(),scopeHash:u.z.string(),createdAt:u.z.string(),updatedAt:u.z.string()}),O=u.z.enum([`similarity_dedup`]),k=u.z.object({id:u.z.string(),memoryId:u.z.string(),conflictingMemoryId:u.z.string().nullable(),similarity:u.z.number(),conflictContentSnapshot:u.z.string(),reason:O,createdAt:u.z.string(),resolvedAt:u.z.string().nullable()}),A=u.z.object({id:u.z.string(),memory_id:u.z.string(),conflicting_memory_id:u.z.string().nullable(),similarity:u.z.number(),conflict_content_snapshot:u.z.string(),reason:O,created_at:u.z.string(),resolved_at:u.z.string().nullable()}),j=u.z.object({id:u.z.string(),content:u.z.string(),type:T,tags:u.z.array(u.z.string()),projects:u.z.array(D),sourceHarness:u.z.string().nullable(),accessCount:u.z.number().int().nonnegative(),pinned:u.z.boolean(),reviewEvents:u.z.array(k),createdAt:u.z.string(),updatedAt:u.z.string()}),M=u.z.object({query:u.z.string().min(1),type:T.optional(),projectHash:u.z.string().optional(),limit:u.z.number().int().positive().optional(),includePinned:u.z.boolean().optional()}),N=u.z.object({content:u.z.string().min(1),type:T,tags:u.z.array(u.z.string()).optional(),projectScope:u.z.object({hash:u.z.string(),name:u.z.string()}).optional(),sourceHarness:u.z.string().optional()}),P=u.z.object({content:u.z.string().min(1).optional(),tags:u.z.array(u.z.string()).optional(),type:T.optional()}),F=u.z.object({id:u.z.string(),scope:u.z.string(),content:u.z.string(),sourceMemoryHash:u.z.string(),synthesizedAt:u.z.string(),expiresAt:u.z.string(),inFlightSince:u.z.string().nullable(),createdAt:u.z.string(),updatedAt:u.z.string()}),le=u.z.object({stats:u.z.record(T,u.z.number()),pinnedGlobal:u.z.array(j),pinnedProject:u.z.array(j),synthesis:u.z.string().optional()}),I=u.z.object({id:u.z.string(),content:u.z.string(),type:u.z.string(),tags:u.z.string(),source:u.z.string().nullable(),access_count:u.z.number(),pinned:u.z.number(),created_at:u.z.string(),updated_at:u.z.string()}),ue=u.z.object({id:u.z.number(),memory_id:u.z.string(),version:u.z.number(),content:u.z.string(),created_at:u.z.string()}),de=u.z.object({id:u.z.number(),scope:u.z.string(),version:u.z.number(),content:u.z.string(),source_memory_hash:u.z.string(),synthesized_at:u.z.string(),created_at:u.z.string()}),L=u.z.object({id:u.z.string(),name:u.z.string(),scope_hash:u.z.string(),created_at:u.z.string(),updated_at:u.z.string()});function R(e,t,n=[]){return{id:e.id,content:e.content,type:T.parse(e.type),tags:E.parse(JSON.parse(e.tags)),projects:t,sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,reviewEvents:n,createdAt:e.created_at,updatedAt:e.updated_at}}function z(e){let t=A.parse(e);return{id:t.id,memoryId:t.memory_id,conflictingMemoryId:t.conflicting_memory_id,similarity:t.similarity,conflictContentSnapshot:t.conflict_content_snapshot,reason:t.reason,createdAt:t.created_at,resolvedAt:t.resolved_at}}function B(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}function V(e){return{version:e.version,content:e.content,createdAt:e.created_at}}function H(e){return{version:e.version,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,createdAt:e.created_at}}var U=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},W=class extends U{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const fe=(0,p.join)((0,f.homedir)(),`.membank`,`memory.db`),pe=[[1,`
3
3
  CREATE TABLE IF NOT EXISTS memories (
4
4
  id TEXT PRIMARY KEY,
5
5
  content TEXT NOT NULL,
@@ -254,14 +254,38 @@ CREATE INDEX IF NOT EXISTS idx_review_events_memory_open
254
254
  COMMIT;
255
255
 
256
256
  PRAGMA foreign_keys = ON;
257
- `]];var fe=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??ue;(0,d.mkdirSync)((0,p.dirname)(n),{recursive:!0});let r=new m.default(n);return e.#n(r,h.load)}static openInMemory(){return e.#t(h.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new m.default(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new H(`Failed to load sqlite-vec extension`,{cause:e})}t.pragma(`journal_mode = WAL`),t.pragma(`foreign_keys = ON`);let r=new e(t);return r.#r(),r}#r(){this.#e.exec(`
257
+ `],[12,`
258
+ CREATE TABLE memory_versions (
259
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
260
+ memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
261
+ version INTEGER NOT NULL,
262
+ content TEXT NOT NULL,
263
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
264
+ UNIQUE (memory_id, version)
265
+ );
266
+
267
+ CREATE INDEX idx_memory_versions_memory_id ON memory_versions(memory_id, version DESC);
268
+ `],[13,`
269
+ CREATE TABLE synthesis_versions (
270
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
271
+ scope TEXT NOT NULL REFERENCES projects(scope_hash) ON DELETE CASCADE,
272
+ version INTEGER NOT NULL,
273
+ content TEXT NOT NULL,
274
+ source_memory_hash TEXT NOT NULL,
275
+ synthesized_at TEXT NOT NULL,
276
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
277
+ UNIQUE (scope, version)
278
+ );
279
+
280
+ CREATE INDEX idx_synthesis_versions_scope ON synthesis_versions(scope, version DESC);
281
+ `]];var me=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??fe;(0,d.mkdirSync)((0,p.dirname)(n),{recursive:!0});let r=new m.default(n);return e.#n(r,h.load)}static openInMemory(){return e.#t(h.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new m.default(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new W(`Failed to load sqlite-vec extension`,{cause:e})}t.pragma(`journal_mode = WAL`),t.pragma(`foreign_keys = ON`);let r=new e(t);return r.#r(),r}#r(){this.#e.exec(`
258
282
  CREATE TABLE IF NOT EXISTS meta (
259
283
  key TEXT PRIMARY KEY,
260
284
  value TEXT NOT NULL
261
285
  );
262
- `);let e=this.#e.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get(),t=e?Number.parseInt(e.value,10):0;for(let[e,n]of de)t<e&&(this.#e.exec(n),this.#e.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`).run(String(e)))}get db(){return this.#e}close(){this.#e.close()}};const U=`Xenova/bge-small-en-v1.5`;var W=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function pe(){return(0,p.join)((0,f.homedir)(),`.membank`,`models`)}function G(e){if(!(0,d.existsSync)(e))return!1;try{return(0,d.readdirSync)(e).length>0}catch{return!1}}var me=class extends g.EventEmitter{modelPath;constructor(e){super(),this.modelPath=e??pe()}isAlreadyCached(){return G(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(G(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await(0,_.pipeline)(`feature-extraction`,U,{cache_dir:this.modelPath,progress_callback:e=>{if(e.status!==`progress`||e.total==null||e.loaded==null)return;let r=e.total,i=e.loaded,a=r>0?i/r*100:0,o=Date.now(),s=o-n,c=i-t,l=0;if(s>0&&c>0){let e=c/s;l=(r-i)/e/1e3}t=i,n=o;let u={totalBytes:r,downloadedBytes:i,percentage:a,estimatedSecondsRemaining:l};this.emit(`progress`,u)}})}catch(e){throw new W(`Failed to download model`,{cause:e})}return{skipped:!1}}},he=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??(0,p.join)((0,f.homedir)(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await(0,_.pipeline)(`feature-extraction`,`Xenova/bge-small-en-v1.5`,{cache_dir:this.modelCachePath,progress_callback:this.onProgress})),this.pipelineInstance}async embed(e){let t=(await(await this.getPipeline())(e,{pooling:`mean`,normalize:!0})).data;return t instanceof Float32Array?t:new Float32Array(t)}};async function ge(e,t){let n=t.now??(()=>new Date);if(!t.repo.tryClaim(e.sessionId,n(),t.config)){let n=t.repo.get(e.sessionId);return{status:`skipped`,reason:n?.status===`completed`&&n.completedAt!==null?`recently_completed`:`in_flight`}}try{let r=await t.transcripts.read(e.transcriptPath);return await t.agent.run({transcript:r,projectHash:e.projectHash,sessionId:e.sessionId}),t.repo.markCompleted(e.sessionId,n()),{status:`completed`}}catch(r){let i=r instanceof Error?r.message:String(r);return t.repo.markFailed(e.sessionId,n(),i),{status:`failed`,error:i}}}const _e=[`You are a memory extractor that runs after a coding session ends. You read the session transcript and CALL save_memory for every durable fact, preference, correction, decision, or learning the user expressed, so that future sessions inherit them.`,``,`Memory types (pick the closest match):`,`- correction: the user told the assistant to stop doing something or to do it differently.`,`- preference: the user stated how they want work done (tools, style, conventions).`,`- decision: the user committed to a choice future work should respect (tech pick, architectural direction, scope cut).`,`- learning: a non-obvious fact about the codebase or tooling that future sessions would otherwise rediscover.`,`- fact: stable info about the user or their project not derivable from the code.`,``,`Bias strongly toward saving. If the user said it in plain language and it would be useful in a future session, save it. Phrasing like 'stop X', 'always Y', 'we use Z', 'don't suggest W', 'we decided', 'from now on' is a clear save signal — even when the assistant in the transcript already acknowledged it, save it so the NEXT session also knows.`,``,`Process:`,`1. Read the supplied transcript end-to-end.`,`2. Identify every distinct durable signal. List them mentally before calling tools.`,`3. Optional: call query_memory with focused search terms to avoid duplicates. If a near-duplicate exists, call update_memory instead of save_memory.`,`4. Call save_memory for each new durable signal. Phrase the content as a standalone instruction or fact — strip session framing ("in this session", "just now"). Good: "Use pnpm, not npm, for all dependency operations." Bad: "User said stop using npm."`,"5. Use `global: true` only when the fact is about the user themselves or applies across every project. Otherwise default to project scope (omit `global`).",``,`Only return without saving when the transcript truly contains no durable signal — pure greetings, time-of-day questions, abandoned tasks. Do not invent facts. If in doubt and the signal is concrete, save it.`].join(`
263
- `);var ve=class{#e;constructor(e){this.#e=e}async run(e){let t=(0,v.createSdkMcpServer)({name:`membank-extraction-tools`,version:`1.0.0`,tools:[(0,v.tool)(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:u.z.string().describe(`Search text`),limit:u.z.number().optional().describe(`Maximum results to return`),global:u.z.boolean().optional().describe(`Query global memories when true, otherwise current project scope`)},async({query:t,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:t,limit:n,global:r,projectHash:e.projectHash})}]}),{annotations:{readOnlyHint:!0}}),(0,v.tool)(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:u.z.string().describe(`Memory content — concise, decontextualised`),type:u.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:u.z.array(u.z.string()).optional().describe(`Optional tags`),global:u.z.boolean().optional().describe(`Save as global memory rather than project-scoped`)},async({content:e,type:t,tags:n,global:r})=>({content:[{type:`text`,text:await this.#e.saveMemory({content:e,type:t,tags:n,global:r})}]})),(0,v.tool)(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:u.z.string().describe(`Memory id`),content:u.z.string().optional(),type:u.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:u.z.array(u.z.string()).optional()},async({id:e,content:t,type:n,tags:r})=>({content:[{type:`text`,text:await this.#e.updateMemory({id:e,content:t,type:n,tags:r})}]}))]}),n=[`Session id: ${e.sessionId}`,``,`Transcript (most recent turns):`,`---`,e.transcript,`---`,``,`Extract durable memories from this transcript following the system instructions.`].join(`
264
- `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),a=(0,v.query)({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:_e,mcpServers:{"membank-extraction-tools":t},allowedTools:[`mcp__membank-extraction-tools__query_memory`,`mcp__membank-extraction-tools__save_memory`,`mcp__membank-extraction-tools__update_memory`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:r}}),o=process.env.MEMBANK_EXTRACTION_DEBUG===`true`;for await(let e of a)if(o&&process.stderr.write(`[extraction debug] ${JSON.stringify(e).slice(0,600)}\n`),e.type===`result`&&e.subtype!==`success`){let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Extraction agent failed: ${e.subtype}${t}`)}let s=Date.now()-i;process.stderr.write(`membank extraction: session=${e.sessionId} duration=${s}ms\n`)}};function ye(e){return new ve(e)}function be(e,t,n,r){return e===void 0?{kind:`claim`}:e.status===`in_flight`?t.getTime()-e.startedAt.getTime()<n?{kind:`skip`,reason:`in_flight`}:{kind:`claim`}:e.status===`completed`&&e.completedAt!==null&&t.getTime()-e.completedAt.getTime()<r?{kind:`skip`,reason:`recently_completed`}:{kind:`claim`}}function xe(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var Se=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(be(r===void 0?void 0:{startedAt:new Date(r.started_at),completedAt:r.completed_at===null?null:new Date(r.completed_at),status:r.status},t,n.inFlightTimeoutMs??6e5,n.recentCompletionMs??6e4).kind===`skip`)return!1;let i=t.toISOString();return this.#e.db.prepare(`INSERT INTO extraction_runs (session_id, started_at, completed_at, status, error)
286
+ `);let e=this.#e.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get(),t=e?Number.parseInt(e.value,10):0;for(let[e,n]of pe)t<e&&(this.#e.exec(n),this.#e.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`).run(String(e)))}get db(){return this.#e}close(){this.#e.close()}};const G=`Xenova/bge-small-en-v1.5`;var K=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function he(){return(0,p.join)((0,f.homedir)(),`.membank`,`models`)}function q(e){if(!(0,d.existsSync)(e))return!1;try{return(0,d.readdirSync)(e).length>0}catch{return!1}}var ge=class extends g.EventEmitter{modelPath;constructor(e){super(),this.modelPath=e??he()}isAlreadyCached(){return q(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(q(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await(0,_.pipeline)(`feature-extraction`,G,{cache_dir:this.modelPath,progress_callback:e=>{if(e.status!==`progress`||e.total==null||e.loaded==null)return;let r=e.total,i=e.loaded,a=r>0?i/r*100:0,o=Date.now(),s=o-n,c=i-t,l=0;if(s>0&&c>0){let e=c/s;l=(r-i)/e/1e3}t=i,n=o;let u={totalBytes:r,downloadedBytes:i,percentage:a,estimatedSecondsRemaining:l};this.emit(`progress`,u)}})}catch(e){throw new K(`Failed to download model`,{cause:e})}return{skipped:!1}}},_e=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??(0,p.join)((0,f.homedir)(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await(0,_.pipeline)(`feature-extraction`,`Xenova/bge-small-en-v1.5`,{cache_dir:this.modelCachePath,...this.onProgress!==void 0&&{progress_callback:this.onProgress}})),this.pipelineInstance}async embed(e){let t=(await(await this.getPipeline())(e,{pooling:`mean`,normalize:!0})).data;return t instanceof Float32Array?t:new Float32Array(t)}};async function ve(e,t){let n=t.now??(()=>new Date);if(!t.repo.tryClaim(e.sessionId,n(),t.config)){let n=t.repo.get(e.sessionId);return{status:`skipped`,reason:n?.status===`completed`&&n.completedAt!==null?`recently_completed`:`in_flight`}}try{let r=await t.transcripts.read(e.transcriptPath);return await t.agent.run({transcript:r,projectHash:e.projectHash,sessionId:e.sessionId}),t.repo.markCompleted(e.sessionId,n()),{status:`completed`}}catch(r){let i=r instanceof Error?r.message:String(r);return t.repo.markFailed(e.sessionId,n(),i),{status:`failed`,error:i}}}const ye=[`You are a memory extractor that runs after a coding session ends. You read the session transcript and CALL save_memory for every durable fact, preference, correction, decision, or learning the user expressed, so that future sessions inherit them.`,``,`Memory types (pick the closest match):`,`- correction: the user told the assistant to stop doing something or to do it differently.`,`- preference: the user stated how they want work done (tools, style, conventions).`,`- decision: the user committed to a choice future work should respect (tech pick, architectural direction, scope cut).`,`- learning: a non-obvious fact about the codebase or tooling that future sessions would otherwise rediscover.`,`- fact: stable info about the user or their project not derivable from the code.`,``,`Bias strongly toward saving. If the user said it in plain language and it would be useful in a future session, save it. Phrasing like 'stop X', 'always Y', 'we use Z', 'don't suggest W', 'we decided', 'from now on' is a clear save signal — even when the assistant in the transcript already acknowledged it, save it so the NEXT session also knows.`,``,`Process:`,`1. Read the supplied transcript end-to-end.`,`2. Identify every distinct durable signal. List them mentally before calling tools.`,`3. Optional: call query_memory with focused search terms to avoid duplicates. If a near-duplicate exists, call update_memory instead of save_memory.`,`4. Call save_memory for each new durable signal. Phrase the content as a standalone instruction or fact — strip session framing ("in this session", "just now"). Good: "Use pnpm, not npm, for all dependency operations." Bad: "User said stop using npm."`,"5. Use `global: true` only when the fact is about the user themselves or applies across every project. Otherwise default to project scope (omit `global`).",``,`Only return without saving when the transcript truly contains no durable signal — pure greetings, time-of-day questions, abandoned tasks. Do not invent facts. If in doubt and the signal is concrete, save it.`].join(`
287
+ `);var be=class{#e;constructor(e){this.#e=e}async run(e){let t=(0,v.createSdkMcpServer)({name:`membank-extraction-tools`,version:`1.0.0`,tools:[(0,v.tool)(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:u.z.string().describe(`Search text`),limit:u.z.number().optional().describe(`Maximum results to return`),global:u.z.boolean().optional().describe(`Query global memories when true, otherwise current project scope`)},async({query:t,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:t,...n!==void 0&&{limit:n},...r!==void 0&&{global:r},...e.projectHash!==void 0&&{projectHash:e.projectHash}})}]}),{annotations:{readOnlyHint:!0}}),(0,v.tool)(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:u.z.string().describe(`Memory content — concise, decontextualised`),type:u.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:u.z.array(u.z.string()).optional().describe(`Optional tags`),global:u.z.boolean().optional().describe(`Save as global memory rather than project-scoped`)},async({content:e,type:t,tags:n,global:r})=>({content:[{type:`text`,text:await this.#e.saveMemory({content:e,type:t,...n!==void 0&&{tags:n},...r!==void 0&&{global:r}})}]})),(0,v.tool)(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:u.z.string().describe(`Memory id`),content:u.z.string().optional(),type:u.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:u.z.array(u.z.string()).optional()},async({id:e,content:t,type:n,tags:r})=>({content:[{type:`text`,text:await this.#e.updateMemory({id:e,...t!==void 0&&{content:t},...n!==void 0&&{type:n},...r!==void 0&&{tags:r}})}]}))]}),n=[`Session id: ${e.sessionId}`,``,`Transcript (most recent turns):`,`---`,e.transcript,`---`,``,`Extract durable memories from this transcript following the system instructions.`].join(`
288
+ `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),a=(0,v.query)({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:ye,mcpServers:{"membank-extraction-tools":t},allowedTools:[`mcp__membank-extraction-tools__query_memory`,`mcp__membank-extraction-tools__save_memory`,`mcp__membank-extraction-tools__update_memory`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:r}}),o=process.env.MEMBANK_EXTRACTION_DEBUG===`true`;for await(let e of a)if(o&&process.stderr.write(`[extraction debug] ${JSON.stringify(e).slice(0,600)}\n`),e.type===`result`&&e.subtype!==`success`){let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Extraction agent failed: ${e.subtype}${t}`)}let s=Date.now()-i;process.stderr.write(`membank extraction: session=${e.sessionId} duration=${s}ms\n`)}};function xe(e){return new be(e)}function Se(e,t,n,r){return e===void 0?{kind:`claim`}:e.status===`in_flight`?t.getTime()-e.startedAt.getTime()<n?{kind:`skip`,reason:`in_flight`}:{kind:`claim`}:e.status===`completed`&&e.completedAt!==null&&t.getTime()-e.completedAt.getTime()<r?{kind:`skip`,reason:`recently_completed`}:{kind:`claim`}}function Ce(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var we=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(Se(r===void 0?void 0:{startedAt:new Date(r.started_at),completedAt:r.completed_at===null?null:new Date(r.completed_at),status:r.status},t,n.inFlightTimeoutMs??6e5,n.recentCompletionMs??6e4).kind===`skip`)return!1;let i=t.toISOString();return this.#e.db.prepare(`INSERT INTO extraction_runs (session_id, started_at, completed_at, status, error)
265
289
  VALUES (?, ?, NULL, 'in_flight', NULL)
266
290
  ON CONFLICT(session_id) DO UPDATE SET
267
291
  started_at = excluded.started_at,
@@ -271,11 +295,11 @@ PRAGMA foreign_keys = ON;
271
295
  SET status = 'completed', completed_at = ?, error = NULL
272
296
  WHERE session_id = ?`).run(t.toISOString(),e)}markFailed(e,t,n){this.#e.db.prepare(`UPDATE extraction_runs
273
297
  SET status = 'failed', completed_at = ?, error = ?
274
- WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:xe(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function Ce(e){return new Se(e)}function we(e){if(typeof e==`string`)return e;if(!Array.isArray(e))return``;let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push(e.text):e.type===`tool_use`&&typeof e.name==`string`?t.push(`[tool_use: ${e.name}]`):e.type===`tool_result`&&t.push(`[tool_result]`)}return t.join(`
275
- `)}var Te=class{#e;#t;constructor(e={}){this.#e=e.maxTurns??80,this.#t=e.maxChars??6e4}async read(e){let t=(await(0,ee.readFile)(e,`utf8`)).split(`
276
- `).filter(e=>e.length>0),n=[];for(let e of t){let t;try{t=JSON.parse(e)}catch{continue}let r=t.message?.role;if(r!==`user`&&r!==`assistant`)continue;let i=we(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
298
+ WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:Ce(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function Te(e){return new we(e)}function Ee(e){if(typeof e==`string`)return e;if(!Array.isArray(e))return``;let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push(e.text):e.type===`tool_use`&&typeof e.name==`string`?t.push(`[tool_use: ${e.name}]`):e.type===`tool_result`&&t.push(`[tool_result]`)}return t.join(`
299
+ `)}var De=class{#e;#t;constructor(e={}){this.#e=e.maxTurns??80,this.#t=e.maxChars??6e4}async read(e){let t=(await(0,ee.readFile)(e,`utf8`)).split(`
300
+ `).filter(e=>e.length>0),n=[];for(let e of t){let t;try{t=JSON.parse(e)}catch{continue}let r=t.message?.role;if(r!==`user`&&r!==`assistant`)continue;let i=Ee(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
277
301
 
278
- `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function Ee(e={}){return new Te(e)}function De(e){let t=new Map;function n(e){t.has(e)||t.set(e,e);let r=t.get(e);if(r!==e){let i=n(r);return t.set(e,i),i}return e}function r(e,r){let i=n(e),a=n(r);i!==a&&t.set(a,i)}for(let{memoryId:t,conflictingMemoryId:n}of e)r(t,n);let i=new Map;for(let e of t.keys()){let t=n(e),r=i.get(t)??[];r.push(e),i.set(t,r)}return Array.from(i.entries()).map(([e,t])=>({clusterId:e,memoryIds:t}))}function K(e,t,n=C){let r=t.findById(e)?.projects[0]?.scopeHash??`0000000000000000`;return t.delete(e),n.logEvent({projectHash:r,eventType:`memory.deleted`,memoryId:e}),Promise.resolve()}async function Oe(e,t,n=C){let r=[];for(let i of e)try{await K(i,t,n),r.push({id:i,status:`ok`})}catch(e){r.push({id:i,status:`error`,error:e instanceof Error?e.message:String(e)})}return r}function q(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function ke(e,t){let{keepId:n,dropIds:r,mergedContent:i}=e,{repo:a,embedder:o,activityLogger:s=C}=t,c=a.findById(n);if(c===void 0)throw Error(`Memory not found: ${n}`);let l=r.map(e=>{let t=a.findById(e);if(t===void 0)throw Error(`Memory not found: ${e}`);return t});for(let e of l)if(e.type!==c.type)throw Error(`Type mismatch: keep memory has type "${c.type}" but drop memory ${e.id} has type "${e.type}"`);let u=[c,...l],d=[...new Set(u.flatMap(e=>e.tags))],f=u.some(e=>e.pinned),p=u.reduce((e,t)=>e+t.accessCount,0),m=await o.embed(i),h=a.overwrite(n,i,m),g=new Set(c.tags);if((d.length!==c.tags.length||d.some(e=>!g.has(e)))&&(h=a.update(n,{tags:d})),f&&!c.pinned&&(h=a.setPin(n,!0)),p>c.accessCount){let e=p-c.accessCount;for(let t=0;t<e;t++)a.incrementAccessCount(n);h=a.findById(n)??h}for(let e of l)a.delete(e.id);let[_]=a.findSimilar(m,c.type,c.projects[0]?.scopeHash);_!==void 0&&_.id!==n&&q(_.similarity)===`flag`&&a.createReviewEvent({memoryId:n,conflictingMemoryId:_.id,similarity:_.similarity,conflictContentSnapshot:i});let v=h.projects[0]?.scopeHash??`0000000000000000`;return s.logEvent({projectHash:v,eventType:`memory.updated`,memoryId:n,payload:{merged:r}}),h=a.findById(n)??h,{kept:h,dropped:r}}function Ae(e,t){t.resolveReviewEvents(e)}function je(e,t){return e.map(e=>{try{return t.findById(e)===void 0?{id:e,status:`error`,error:`Memory not found: ${e}`}:(t.resolveReviewEvents(e),{id:e,status:`ok`})}catch(t){return{id:e,status:`error`,error:t instanceof Error?t.message:String(t)}}})}async function Me(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=N.parse(e),{repo:s,embedder:c,activityLogger:u=C}=t,d=a?.hash??`0000000000000000`,f=await c.embed(n),[p]=s.findSimilar(f,r,a?.hash);if(p!==void 0){let e=q(p.similarity);if(e===`overwrite`){let e=s.overwrite(p.id,n,f);return u.logEvent({projectHash:d,eventType:`memory.updated`,memoryId:p.id}),e}if(e===`flag`){let e=s.create({id:(0,l.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:f,projectScope:a});return s.createReviewEvent({memoryId:p.id,conflictingMemoryId:e.id,similarity:p.similarity,conflictContentSnapshot:n}),u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:e.id}),u.logEvent({projectHash:d,eventType:`memory.flagged`,memoryId:p.id,payload:{conflictingMemoryId:e.id,similarity:p.similarity}}),e}}let m=s.create({id:(0,l.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:f,projectScope:a});return u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:m.id}),m}async function Ne(e,t,n){let{repo:r,embedder:i,activityLogger:a=C}=n,o=P.parse(t),s=o.content===void 0?void 0:await i.embed(o.content),c=r.update(e,o,s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e}),c}const J=8e3;function Pe(e){return e>=J}var Y=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}findSimilar(e,t,n){let r=Buffer.from(e.buffer),i;return i=n===void 0?this.#e.db.prepare(`SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity
302
+ `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function Oe(e={}){return new De(e)}function ke(e){let t=new Map;function n(e){t.has(e)||t.set(e,e);let r=t.get(e);if(r!==e){let i=n(r);return t.set(e,i),i}return e}function r(e,r){let i=n(e),a=n(r);i!==a&&t.set(a,i)}for(let{memoryId:t,conflictingMemoryId:n}of e)r(t,n);let i=new Map;for(let e of t.keys()){let t=n(e),r=i.get(t)??[];r.push(e),i.set(t,r)}return Array.from(i.entries()).map(([e,t])=>({clusterId:e,memoryIds:t}))}function J(e,t,n=C){let r=t.findById(e)?.projects[0]?.scopeHash??`0000000000000000`;return t.delete(e),n.logEvent({projectHash:r,eventType:`memory.deleted`,memoryId:e}),Promise.resolve()}async function Ae(e,t,n=C){let r=[];for(let i of e)try{await J(i,t,n),r.push({id:i,status:`ok`})}catch(e){r.push({id:i,status:`error`,error:e instanceof Error?e.message:String(e)})}return r}function Y(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function je(e,t){let{keepId:n,dropIds:r,mergedContent:i}=e,{repo:a,embedder:o,activityLogger:s=C}=t,c=a.findById(n);if(c===void 0)throw Error(`Memory not found: ${n}`);let l=r.map(e=>{let t=a.findById(e);if(t===void 0)throw Error(`Memory not found: ${e}`);return t});for(let e of l)if(e.type!==c.type)throw Error(`Type mismatch: keep memory has type "${c.type}" but drop memory ${e.id} has type "${e.type}"`);let u=[c,...l],d=[...new Set(u.flatMap(e=>e.tags))],f=u.some(e=>e.pinned),p=u.reduce((e,t)=>e+t.accessCount,0),m=await o.embed(i),h=a.overwrite(n,i,m),g=new Set(c.tags);if((d.length!==c.tags.length||d.some(e=>!g.has(e)))&&(h=a.update(n,{tags:d})),f&&!c.pinned&&(h=a.setPin(n,!0)),p>c.accessCount){let e=p-c.accessCount;for(let t=0;t<e;t++)a.incrementAccessCount(n);h=a.findById(n)??h}for(let e of l)a.delete(e.id);let[_]=a.findSimilar(m,c.type,c.projects[0]?.scopeHash);_!==void 0&&_.id!==n&&Y(_.similarity)===`flag`&&a.createReviewEvent({memoryId:n,conflictingMemoryId:_.id,similarity:_.similarity,conflictContentSnapshot:i});let v=h.projects[0]?.scopeHash??`0000000000000000`;return s.logEvent({projectHash:v,eventType:`memory.updated`,memoryId:n,payload:{merged:r}}),h=a.findById(n)??h,{kept:h,dropped:r}}function Me(e,t){t.resolveReviewEvents(e)}function Ne(e,t){return e.map(e=>{try{return t.findById(e)===void 0?{id:e,status:`error`,error:`Memory not found: ${e}`}:(t.resolveReviewEvents(e),{id:e,status:`ok`})}catch(t){return{id:e,status:`error`,error:t instanceof Error?t.message:String(t)}}})}async function Pe(e,t,n){let{repo:r,embedder:i,activityLogger:a=C}=n,o=r.getVersion(e,t);if(o===void 0)throw Error(`Version ${t} not found for memory: ${e}`);let s=await i.embed(o.content),c=r.update(e,{content:o.content},s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e,payload:{revertedToVersion:t}}),c}async function Fe(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=N.parse(e),{repo:s,embedder:c,activityLogger:u=C}=t,d=a?.hash??`0000000000000000`,f=await c.embed(n),[p]=s.findSimilar(f,r,a?.hash);if(p!==void 0){let e=Y(p.similarity);if(e===`overwrite`){let e=s.overwrite(p.id,n,f);return u.logEvent({projectHash:d,eventType:`memory.updated`,memoryId:p.id}),e}if(e===`flag`){let e=s.create({id:(0,l.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:f,...a!==void 0&&{projectScope:a}});return s.createReviewEvent({memoryId:p.id,conflictingMemoryId:e.id,similarity:p.similarity,conflictContentSnapshot:n}),u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:e.id}),u.logEvent({projectHash:d,eventType:`memory.flagged`,memoryId:p.id,payload:{conflictingMemoryId:e.id,similarity:p.similarity}}),e}}let m=s.create({id:(0,l.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:f,...a!==void 0&&{projectScope:a}});return u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:m.id}),m}async function Ie(e,t,n){let{repo:r,embedder:i,activityLogger:a=C}=n,o=P.parse(t),s=o.content===void 0?void 0:await i.embed(o.content),c=r.update(e,o,s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e}),c}const X=8e3;function Le(e){return e>=X}var Z=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}findSimilar(e,t,n){let r=Buffer.from(e.buffer),i;return i=n===void 0?this.#e.db.prepare(`SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity
279
303
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
280
304
  JOIN memory_projects mp ON mp.memory_id = m.id
281
305
  JOIN projects p ON p.id = mp.project_id
@@ -286,7 +310,7 @@ PRAGMA foreign_keys = ON;
286
310
  JOIN projects p ON p.id = mp.project_id
287
311
  WHERE m.type = ? AND p.scope_hash = ?
288
312
  ORDER BY similarity DESC LIMIT 1`).get(r,t,n),i===void 0?[]:[{id:i.id,similarity:i.similarity}]}create(e){let{id:t,content:n,type:r,tags:i,sourceHarness:a,embedding:o,projectScope:s}=e,c=new Date().toISOString(),l=Buffer.from(o.buffer);this.#e.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
289
- VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(t,n,r,JSON.stringify(i),a,c,c),this.#e.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(l,t);let u=s??{hash:`0000000000000000`,name:`global`},d=this.#t.upsertByHash(u.hash,u.name);return this.#t.addAssociation(t,d.id),R(I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(t)),this.#t.getProjectsForMemories([t]).get(t)??[])}overwrite(e,t,n){let r=new Date().toISOString(),i=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(t,r,e);let a=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e)?.rowid;a!==void 0&&this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(i,a);let o=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#r([e]);return R(o,s.get(e)??[],c.get(e)??[])}findById(e){let t=this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e);if(t===void 0)return;let n=this.#t.getProjectsForMemories([e]),r=this.#r([e]);return R(t,n.get(e)??[],r.get(e)??[])}findManyById(e){if(e.length===0)return[];let t=e.map(()=>`?`).join(`, `),n=this.#e.db.prepare(`SELECT * FROM memories WHERE id IN (${t})`).all(...e);if(n.length===0)return[];let r=n.map(e=>e.id),i=this.#t.getProjectsForMemories(r),a=this.#r(r);return n.map(e=>R(e,i.get(e.id)??[],a.get(e.id)??[]))}update(e,t,n){let{content:r,tags:i,type:a}=P.parse(t),o=this.#e.db.prepare(`SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`).get(e);if(o===void 0)throw Error(`Memory not found: ${e}`);let s=new Date().toISOString(),c=[`updated_at = ?`],l=[s];if(r!==void 0&&(c.push(`content = ?`),l.push(r)),i!==void 0&&(c.push(`tags = ?`),l.push(JSON.stringify(i))),a!==void 0&&(c.push(`type = ?`),l.push(a)),l.push(e),this.#e.db.prepare(`UPDATE memories SET ${c.join(`, `)} WHERE id = ?`).run(...l),n!==void 0){let e=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(e,o.rowid)}let u=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#r([e]);return R(u,d.get(e)??[],f.get(e)??[])}delete(e){let t=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e);t!==void 0&&this.#e.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(t.rowid),this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(e),this.#e.db.prepare(`DELETE FROM memories WHERE id = ?`).run(e)}list(e){let t=[],n=[];e?.type!==void 0&&(t.push(`m.type = ?`),n.push(e.type)),e?.pinned===!0&&t.push(`m.pinned = 1`),e?.needsReview===!0&&t.push(`EXISTS (SELECT 1 FROM memory_review_events e WHERE e.memory_id = m.id AND e.resolved_at IS NULL)`),e?.projectId===`global`?(t.push(`EXISTS (SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id WHERE mp.memory_id = m.id AND p.scope_hash = ?)`),n.push(c.r)):e?.projectId!==void 0&&(t.push(`m.id IN (SELECT memory_id FROM memory_projects WHERE project_id = ?)`),n.push(e.projectId));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=this.#e.db.prepare(`SELECT m.* FROM memories m ${r} ORDER BY m.created_at DESC`).all(...n);if(i.length===0)return[];let a=i.map(e=>e.id),o=this.#t.getProjectsForMemories(a),s=this.#r(a);return i.map(e=>R(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.listPinnedForProject(c.r)}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
313
+ VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(t,n,r,JSON.stringify(i),a,c,c),this.#e.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(l,t);let u=s??{hash:`0000000000000000`,name:`global`},d=this.#t.upsertByHash(u.hash,u.name);return this.#t.addAssociation(t,d.id),R(I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(t)),this.#t.getProjectsForMemories([t]).get(t)??[])}overwrite(e,t,n){let r=new Date().toISOString(),i=Buffer.from(n.buffer);this.#e.db.transaction(()=>{this.#r(e),this.#e.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(t,r,e)})();let a=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e)?.rowid;a!==void 0&&this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(i,a);let o=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#i([e]);return R(o,s.get(e)??[],c.get(e)??[])}findById(e){let t=this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e);if(t===void 0)return;let n=this.#t.getProjectsForMemories([e]),r=this.#i([e]);return R(t,n.get(e)??[],r.get(e)??[])}findManyById(e){if(e.length===0)return[];let t=e.map(()=>`?`).join(`, `),n=this.#e.db.prepare(`SELECT * FROM memories WHERE id IN (${t})`).all(...e);if(n.length===0)return[];let r=n.map(e=>e.id),i=this.#t.getProjectsForMemories(r),a=this.#i(r);return n.map(e=>R(e,i.get(e.id)??[],a.get(e.id)??[]))}update(e,t,n){let{content:r,tags:i,type:a}=P.parse(t),o=this.#e.db.prepare(`SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`).get(e);if(o===void 0)throw Error(`Memory not found: ${e}`);let s=new Date().toISOString(),c=[`updated_at = ?`],l=[s];if(r!==void 0&&(c.push(`content = ?`),l.push(r)),i!==void 0&&(c.push(`tags = ?`),l.push(JSON.stringify(i))),a!==void 0&&(c.push(`type = ?`),l.push(a)),l.push(e),this.#e.db.transaction(()=>{r!==void 0&&this.#r(e),this.#e.db.prepare(`UPDATE memories SET ${c.join(`, `)} WHERE id = ?`).run(...l)})(),n!==void 0){let e=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(e,o.rowid)}let u=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#i([e]);return R(u,d.get(e)??[],f.get(e)??[])}delete(e){let t=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e);t!==void 0&&this.#e.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(t.rowid),this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(e),this.#e.db.prepare(`DELETE FROM memories WHERE id = ?`).run(e)}list(e){let t=[],n=[];e?.type!==void 0&&(t.push(`m.type = ?`),n.push(e.type)),e?.pinned===!0&&t.push(`m.pinned = 1`),e?.needsReview===!0&&t.push(`EXISTS (SELECT 1 FROM memory_review_events e WHERE e.memory_id = m.id AND e.resolved_at IS NULL)`),e?.projectId===`global`?(t.push(`EXISTS (SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id WHERE mp.memory_id = m.id AND p.scope_hash = ?)`),n.push(c.r)):e?.projectId!==void 0&&(t.push(`m.id IN (SELECT memory_id FROM memory_projects WHERE project_id = ?)`),n.push(e.projectId));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=this.#e.db.prepare(`SELECT m.* FROM memories m ${r} ORDER BY m.created_at DESC`).all(...n);if(i.length===0)return[];let a=i.map(e=>e.id),o=this.#t.getProjectsForMemories(a),s=this.#i(a);return i.map(e=>R(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.listPinnedForProject(c.r)}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
290
314
  JOIN memory_projects mp ON mp.memory_id = m.id
291
315
  JOIN projects p ON p.id = mp.project_id
292
316
  WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>R(e,[]))}listFlagged(e){let{projectHash:t,limit:n,minSimilarity:r,maxSimilarity:i}=e??{},a=[`e.resolved_at IS NULL`];r!==void 0&&a.push(`e.similarity >= ?`),i!==void 0&&a.push(`e.similarity <= ?`);let o=[r,i].filter(e=>e!==void 0),s=`EXISTS (
@@ -297,7 +321,7 @@ PRAGMA foreign_keys = ON;
297
321
  ORDER BY created_at DESC ${c}`).all(...o,...l):this.#e.db.prepare(`SELECT * FROM memories
298
322
  WHERE ${s}
299
323
  AND ${this.#n()}
300
- ORDER BY created_at DESC ${c}`).all(...o,t,...l),u.length===0)return[];let d=u.map(e=>e.id),f=this.#t.getProjectsForMemories(d),p=this.#r(d,{unresolvedOnly:!0});return u.map(e=>R(e,f.get(e.id)??[],p.get(e.id)??[]))}listReviewEdges(e){return e===void 0?this.#e.db.prepare(`SELECT memory_id, conflicting_memory_id FROM memory_review_events
324
+ ORDER BY created_at DESC ${c}`).all(...o,t,...l),u.length===0)return[];let d=u.map(e=>e.id),f=this.#t.getProjectsForMemories(d),p=this.#i(d,{unresolvedOnly:!0});return u.map(e=>R(e,f.get(e.id)??[],p.get(e.id)??[]))}listReviewEdges(e){return e===void 0?this.#e.db.prepare(`SELECT memory_id, conflicting_memory_id FROM memory_review_events
301
325
  WHERE resolved_at IS NULL AND conflicting_memory_id IS NOT NULL`).all().map(e=>({memoryId:e.memory_id,conflictingMemoryId:e.conflicting_memory_id})):this.#e.db.prepare(`SELECT e.memory_id, e.conflicting_memory_id
302
326
  FROM memory_review_events e
303
327
  JOIN memories m ON m.id = e.memory_id
@@ -325,30 +349,42 @@ PRAGMA foreign_keys = ON;
325
349
  FROM memory_review_events e ${t}
326
350
  GROUP BY band`).all(...n),i=this.#e.db.prepare(`SELECT m.type, COUNT(DISTINCT e.memory_id) AS count
327
351
  FROM memory_review_events e ${t}
328
- GROUP BY m.type`).all(...n),a=this.#e.db.prepare(`SELECT COUNT(*) AS pairs FROM memory_review_events e ${t}`).get(...n)??{pairs:0},o={high:0,mid:0,low:0};for(let e of r)(e.band===`high`||e.band===`mid`||e.band===`low`)&&(o[e.band]=e.count);let s={};for(let e of i){let t=T.safeParse(e.type);t.success&&(s[t.data]=e.count)}return{pairs:a.pairs,byBand:o,byType:s}}setPin(e,t){if(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)===void 0)throw Error(`Memory not found: ${e}`);let n=new Date().toISOString();this.#e.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(+!!t,n,e);let r=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#r([e]);return R(r,i.get(e)??[],a.get(e)??[])}incrementAccessCount(e){this.#e.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(e)}exportAll(){return this.#e.db.prepare(`SELECT m.*, e.embedding FROM memories m LEFT JOIN embeddings e ON e.rowid = m.rowid ORDER BY m.created_at DESC`).all().map(e=>({id:e.id,content:e.content,type:T.parse(e.type),tags:E.parse(JSON.parse(e.tags)),sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,createdAt:e.created_at,updatedAt:e.updated_at,embedding:e.embedding===null?null:new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4)}))}importAll(e){let t=this.#e.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
352
+ GROUP BY m.type`).all(...n),a=this.#e.db.prepare(`SELECT COUNT(*) AS pairs FROM memory_review_events e ${t}`).get(...n)??{pairs:0},o={high:0,mid:0,low:0};for(let e of r)(e.band===`high`||e.band===`mid`||e.band===`low`)&&(o[e.band]=e.count);let s={};for(let e of i){let t=T.safeParse(e.type);t.success&&(s[t.data]=e.count)}return{pairs:a.pairs,byBand:o,byType:s}}setPin(e,t){if(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)===void 0)throw Error(`Memory not found: ${e}`);let n=new Date().toISOString();this.#e.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(+!!t,n,e);let r=I.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#i([e]);return R(r,i.get(e)??[],a.get(e)??[])}incrementAccessCount(e){this.#e.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(e)}exportAll(){return this.#e.db.prepare(`SELECT m.*, e.embedding FROM memories m LEFT JOIN embeddings e ON e.rowid = m.rowid ORDER BY m.created_at DESC`).all().map(e=>({id:e.id,content:e.content,type:T.parse(e.type),tags:E.parse(JSON.parse(e.tags)),sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,createdAt:e.created_at,updatedAt:e.updated_at,embedding:e.embedding===null?null:new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4)}))}importAll(e){let t=this.#e.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
329
353
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),n=this.#e.db.prepare(`INSERT OR REPLACE INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`);this.#e.db.transaction(()=>{for(let r of e)t.run(r.id,r.content,r.type,JSON.stringify(r.tags),r.sourceHarness,r.accessCount,+!!r.pinned,r.createdAt,r.updatedAt),r.embedding!==null&&n.run(Buffer.from(r.embedding.buffer,r.embedding.byteOffset,r.embedding.byteLength),r.id)})()}#n(e=`memories`){return`EXISTS (
330
354
  SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id
331
355
  WHERE mp.memory_id = ${e}.id AND (p.scope_hash = ? OR p.scope_hash = '${c.r}')
332
- )`}#r(e,t){if(e.length===0)return new Map;let n=e.map(()=>`?`).join(`, `),r=t?.unresolvedOnly===!0?`AND resolved_at IS NULL`:``,i=this.#e.db.prepare(`SELECT * FROM memory_review_events
356
+ )`}listVersions(e){return this.#e.db.prepare(`SELECT * FROM memory_versions WHERE memory_id = ? ORDER BY version DESC`).all(e).map(V)}getVersion(e,t){let n=this.#e.db.prepare(`SELECT * FROM memory_versions WHERE memory_id = ? AND version = ?`).get(e,t);return n===void 0?void 0:V(n)}#r(e){let t=this.#e.db.prepare(`SELECT m.content, COALESCE(MAX(v.version), 0) + 1 AS next_version
357
+ FROM memories m
358
+ LEFT JOIN memory_versions v ON v.memory_id = m.id
359
+ WHERE m.id = ?
360
+ GROUP BY m.id`).get(e);t!==void 0&&(this.#e.db.prepare(`INSERT INTO memory_versions (memory_id, version, content) VALUES (?, ?, ?)`).run(e,t.next_version,t.content),this.#e.db.prepare(`DELETE FROM memory_versions WHERE memory_id = ? AND version <= (
361
+ SELECT MAX(version) - 10 FROM memory_versions WHERE memory_id = ?
362
+ )`).run(e,e))}#i(e,t){if(e.length===0)return new Map;let n=e.map(()=>`?`).join(`, `),r=t?.unresolvedOnly===!0?`AND resolved_at IS NULL`:``,i=this.#e.db.prepare(`SELECT * FROM memory_review_events
333
363
  WHERE memory_id IN (${n}) ${r}
334
- ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=z(A.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function Fe(e,t){return new Y(e,t)}const X=(0,ne.promisify)(te.execFile);function Z(e){return(0,l.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}async function Ie(){try{let{stdout:e}=await X(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Z(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Z(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function Le(){try{let{stdout:e}=await X(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Z(t)}catch{}return Z(process.cwd())}const Re=[{name:`scope-to-projects`,description:`Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.`}];async function ze(e){let t=await Ie(),n=e.getByHash(t.hash);if(n===void 0)return null;let r=n.name,i=e.countMemories(n.id);return e.rename(n.id,t.name),{migration:`scope-to-projects`,oldName:r,newName:t.name,memoryCount:i}}var Be=class{#e;constructor(e){this.#e=e}upsertByHash(e,t){if(!/^[0-9a-f]{16}$/.test(e))throw Error(`Invalid scope hash "${e}": expected 16 lowercase hex characters`);let n=new Date().toISOString(),r=e===`0000000000000000`?c.t:(0,l.randomUUID)(),i=e===`0000000000000000`?c.n:t;return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,i,e,n,n),B(L.parse(this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e)))}rename(e,t){let n=new Date().toISOString();this.#e.db.prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`).run(t,n,e);let r=this.#e.db.prepare(`SELECT * FROM projects WHERE id = ?`).get(e);if(r===void 0)throw Error(`Project not found: ${e}`);return B(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(B)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:B(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:B(t)}addAssociation(e,t){this.#e.db.prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`).run(e,t)}removeAssociation(e,t){this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`).run(e,t)}countMemories(e){return this.#e.db.prepare(`SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`).get(e)?.count??0}getProjectsForMemories(e){if(e.length===0)return new Map;let t=e.map(()=>`?`).join(`,`),n=this.#e.db.prepare(`SELECT p.*, mp.memory_id FROM projects p
364
+ ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=z(A.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function Re(e,t){return new Z(e,t)}const ze=(0,ne.promisify)(te.execFile);function Q(e){return(0,l.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}async function Be(){try{let{stdout:e}=await ze(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Q(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Q(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function Ve(){try{let{stdout:e}=await ze(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Q(t)}catch{}return Q(process.cwd())}const He=[{name:`scope-to-projects`,description:`Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.`}];async function Ue(e){let t=await Be(),n=e.getByHash(t.hash);if(n===void 0)return null;let r=n.name,i=e.countMemories(n.id);return e.rename(n.id,t.name),{migration:`scope-to-projects`,oldName:r,newName:t.name,memoryCount:i}}var We=class{#e;constructor(e){this.#e=e}upsertByHash(e,t){if(!/^[0-9a-f]{16}$/.test(e))throw Error(`Invalid scope hash "${e}": expected 16 lowercase hex characters`);let n=new Date().toISOString(),r=e===`0000000000000000`?c.t:(0,l.randomUUID)(),i=e===`0000000000000000`?c.n:t;return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,i,e,n,n),B(L.parse(this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e)))}rename(e,t){let n=new Date().toISOString();this.#e.db.prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`).run(t,n,e);let r=this.#e.db.prepare(`SELECT * FROM projects WHERE id = ?`).get(e);if(r===void 0)throw Error(`Project not found: ${e}`);return B(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(B)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:B(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:B(t)}addAssociation(e,t){this.#e.db.prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`).run(e,t)}removeAssociation(e,t){this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`).run(e,t)}countMemories(e){return this.#e.db.prepare(`SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`).get(e)?.count??0}getProjectsForMemories(e){if(e.length===0)return new Map;let t=e.map(()=>`?`).join(`,`),n=this.#e.db.prepare(`SELECT p.*, mp.memory_id FROM projects p
335
365
  JOIN memory_projects mp ON mp.project_id = p.id
336
- WHERE mp.memory_id IN (${t})`).all(...e),r=new Map;for(let e of n){let t=r.get(e.memory_id)??[];t.push(B(e)),r.set(e.memory_id,t)}return r}};function Ve(e){return new Be(e)}const He={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function Ue(e,t,n){let r=He[e.type],i=e.accessCount/(e.accessCount+10),a=1/(1+(n-new Date(e.updatedAt).getTime())/864e5),o=+!!e.pinned;return t*.4+r*.25+i*.2+a*.1+o*.05}async function We(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=M.parse(e),{activityLogger:s=C}=t,c=await t.embedder.embed(n),l=Buffer.from(c.buffer),u=t.adapter.findByEmbedding(l,{type:r,projectHash:i,includePinned:o}),d=Date.now(),f=u.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:Ue(n,t,d)}});f.sort((e,t)=>t.score-e.score);let p=f.slice(0,a);for(let e of p)t.repo.incrementAccessCount(e.id);return s.logEvent({projectHash:i??`0000000000000000`,eventType:`memory.queried`,payload:{resultCount:p.length,topScores:p.slice(0,3).map(e=>e.score)}}),p}var Ge=class{#e;constructor(e){this.#e=e}findByEmbedding(e,t){let{type:n,projectHash:r,includePinned:i}=t,a=[],o=[e],s=``;i||a.push(`m.pinned = 0`),n!==void 0&&(a.push(`m.type = ?`),o.push(n)),r!==void 0&&(s=`JOIN memory_projects mp ON mp.memory_id = m.id JOIN projects p ON p.id = mp.project_id`,a.push(`(p.scope_hash = ? OR p.scope_hash = ?)`),o.push(r,c.r));let l=a.length>0?`WHERE ${a.join(` AND `)}`:``,u=`
366
+ WHERE mp.memory_id IN (${t})`).all(...e),r=new Map;for(let e of n){let t=r.get(e.memory_id)??[];t.push(B(e)),r.set(e.memory_id,t)}return r}};function Ge(e){return new We(e)}const Ke={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function qe(e,t,n){let r=Ke[e.type],i=e.accessCount/(e.accessCount+10),a=1/(1+(n-new Date(e.updatedAt).getTime())/864e5),o=+!!e.pinned;return t*.4+r*.25+i*.2+a*.1+o*.05}async function Je(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=M.parse(e),{activityLogger:s=C}=t,c=await t.embedder.embed(n),l=Buffer.from(c.buffer),u=t.adapter.findByEmbedding(l,{...r!==void 0&&{type:r},...i!==void 0&&{projectHash:i},...o!==void 0&&{includePinned:o}}),d=Date.now(),f=u.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:qe(n,t,d)}});f.sort((e,t)=>t.score-e.score);let p=f.slice(0,a);for(let e of p)t.repo.incrementAccessCount(e.id);return s.logEvent({projectHash:i??`0000000000000000`,eventType:`memory.queried`,payload:{resultCount:p.length,topScores:p.slice(0,3).map(e=>e.score)}}),p}var Ye=class{#e;constructor(e){this.#e=e}findByEmbedding(e,t){let{type:n,projectHash:r,includePinned:i}=t,a=[],o=[e],s=``;i||a.push(`m.pinned = 0`),n!==void 0&&(a.push(`m.type = ?`),o.push(n)),r!==void 0&&(s=`JOIN memory_projects mp ON mp.memory_id = m.id JOIN projects p ON p.id = mp.project_id`,a.push(`(p.scope_hash = ? OR p.scope_hash = ?)`),o.push(r,c.r));let l=a.length>0?`WHERE ${a.join(` AND `)}`:``,u=`
337
367
  SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim
338
368
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
339
369
  ${s}
340
370
  ${l}
341
- `;return this.#e.db.prepare(u).all(...o).map(e=>({...R(e,[]),cosineSim:e.cosine_sim}))}},Ke=class{#e;#t;#n;#r;constructor(e,t,n,r=C){this.#e=e,this.#t=t,this.#n=n,this.#r=r}async query(e){return We(e,{adapter:new Ge(this.#e),repo:this.#n,embedder:this.#t,activityLogger:this.#r})}};function Q(e,t){let n=t.repo.stats(e.projectHash);return e.synthesis!==void 0&&e.synthesis.length>0?{stats:n.byType,pinnedGlobal:[],pinnedProject:[],synthesis:e.synthesis}:{stats:n.byType,pinnedGlobal:t.repo.listPinnedGlobal(),pinnedProject:t.repo.listPinnedForProject(e.projectHash)}}function qe(){return[...w]}var Je=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Q({projectHash:e,synthesis:t},{repo:this.#e})}},Ye=class{#e;#t;#n;#r=new Set;#i=new Map;#a=!1;#o;#s=new Map;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async init(){this.#e.clearStaleInFlight(this.#t.inFlightTimeoutMs??12e4),this.#e.expireStale();let e=this.#e.getExpiredOrDirtyScopes();for(let{scope:t}of e)this.#r.add(t);this.#a=!0,await this.#l()}shutdown(){this.#a=!1,this.#o!==void 0&&(clearTimeout(this.#o),this.#o=void 0);let e=[...this.#s.values()];return e.length===0?Promise.resolve():Promise.race([Promise.allSettled(e).then(()=>void 0),new Promise(e=>setTimeout(e,5e3))])}markDirty(e){this.#r.add(e)}#c(){if(!this.#a)return;let e=this.#t.debounceMs??45e3;this.#o=setTimeout(()=>{this.#l()},e)}async#l(){let e=[...this.#r];for(let t of e){let e=this.#t.inFlightTimeoutMs??12e4,n=this.#e.getSynthesis(t);if(n?.inFlightSince!==null&&n?.inFlightSince!==void 0){if(Date.now()-new Date(n.inFlightSince).getTime()<e)continue;this.#e.clearInFlight(t)}this.#r.delete(t);let r=this.#u(t).finally(()=>{this.#s.delete(t)});this.#s.set(t,r)}this.#c()}async#u(e){this.#e.markInFlight(e);try{let t=e===`0000000000000000`?void 0:e,n=await this.#n.run(e,t),r=this.#e.computeSourceMemoryHash(e);this.#e.saveSynthesis(e,n,r),this.#i.delete(e)}catch(t){let n=(this.#i.get(e)??0)+1;this.#i.set(e,n);let r=Math.min(n,5),i=(this.#t.debounceMs??45e3)*r;process.stderr.write(`membank synthesis: error for scope=${e} failures=${n} backoff=${i}ms: ${t instanceof Error?t.message:String(t)}\n`),setTimeout(()=>{this.#r.add(e)},i),this.#e.clearInFlight(e)}}};async function Xe(e,t){let n=e===`0000000000000000`?void 0:e;t.synthRepo.markInFlight(e);try{let[r,i]=await Promise.all([t.agentRunner.run(e,n),Promise.resolve(t.synthRepo.computeSourceMemoryHash(e))]);return t.synthRepo.saveSynthesis(e,r,i),r}catch(n){throw t.synthRepo.clearInFlight(e),n}}var Ze=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=(0,v.createSdkMcpServer)({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[(0,v.tool)(`query_memory`,`Search memories by semantic similarity`,{query:u.z.string().describe(`Search text`),limit:u.z.number().optional().describe(`Maximum results to return`),global:u.z.boolean().optional().describe(`Query global memories only when true, otherwise current project scope`)},async({query:e,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:e,limit:n,global:r,projectHash:t})}]}),{annotations:{readOnlyHint:!0}}),(0,v.tool)(`get_memory_summary`,`Returns aggregate stats: total memories, counts by type, pinned count, review queue size`,{},async()=>({content:[{type:`text`,text:await this.#e.getMemorySummary()}]}),{annotations:{readOnlyHint:!0}})]}),r=`Synthesize the memories for ${e===`0000000000000000`?`global (across all projects)`:`project scope: ${e}`}. Use get_memory_summary first to understand the overall state, then use query_memory to retrieve relevant memories (query with broad terms like "preferences", "corrections", "decisions", "key facts"). After gathering information, produce a concise synthesis of the most important things to remember about this user. Output only the synthesis text — no preamble, no metadata.`,i=Date.now(),a=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),o=(0,v.query)({prompt:r,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:`You are a memory synthesizer. Your job is to read the user's stored memories and produce a concise, well-structured summary of what's most important to remember about this user — their preferences, corrections, decisions, and key facts. Pinned memories are higher fidelity and should be weighted more heavily. Exclude transient or ephemeral details. Output plain text suitable for injection into an LLM context window. Be concise — target 200-400 words.`,mcpServers:{"membank-synthesis-tools":n},allowedTools:[`mcp__membank-synthesis-tools__query_memory`,`mcp__membank-synthesis-tools__get_memory_summary`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:a}}),s=``;for await(let e of o)if(e.type===`result`)if(e.subtype===`success`)s=e.result;else{let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Synthesis agent failed: ${e.subtype}${t}`)}let c=Date.now()-i;if(process.stderr.write(`membank synthesis: scope=${e} duration=${c}ms\n`),s===``)throw Error(`Synthesis agent returned empty result`);return s}};function Qe(e,t){return new Ze(e,t)}function $(e){return F.parse({id:e.id,scope:e.scope,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,expiresAt:e.expires_at,inFlightSince:e.in_flight_since,createdAt:e.created_at,updatedAt:e.updated_at})}var $e=class{#e;constructor(e){this.#e=e}saveSynthesis(e,t,n){let r=new Date().toISOString(),i=new Date(Date.now()+720*60*60*1e3).toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses
342
- SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
343
- in_flight_since = NULL, updated_at = ?
344
- WHERE scope = ?`).run(t,n,r,i,r,e);else{let a=(0,l.randomUUID)();this.#e.db.prepare(`INSERT INTO syntheses
371
+ `;return this.#e.db.prepare(u).all(...o).map(e=>({...R(e,[]),cosineSim:e.cosine_sim}))}},Xe=class{#e;#t;#n;#r;constructor(e,t,n,r=C){this.#e=e,this.#t=t,this.#n=n,this.#r=r}async query(e){return Je(e,{adapter:new Ye(this.#e),repo:this.#n,embedder:this.#t,activityLogger:this.#r})}};function Ze(e,t){let n=t.repo.stats(e.projectHash);return e.synthesis!==void 0&&e.synthesis.length>0?{stats:n.byType,pinnedGlobal:[],pinnedProject:[],synthesis:e.synthesis}:{stats:n.byType,pinnedGlobal:t.repo.listPinnedGlobal(),pinnedProject:t.repo.listPinnedForProject(e.projectHash)}}function Qe(){return[...w]}var $e=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Ze({projectHash:e,...t!==void 0&&{synthesis:t}},{repo:this.#e})}},et=class{#e;#t;#n;#r=new Set;#i=new Map;#a=!1;#o;#s=new Map;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async init(){this.#e.clearStaleInFlight(this.#t.inFlightTimeoutMs??12e4),this.#e.expireStale();let e=this.#e.getExpiredOrDirtyScopes();for(let{scope:t}of e)this.#r.add(t);this.#a=!0,await this.#l()}shutdown(){this.#a=!1,this.#o!==void 0&&(clearTimeout(this.#o),this.#o=void 0);let e=[...this.#s.values()];return e.length===0?Promise.resolve():Promise.race([Promise.allSettled(e).then(()=>void 0),new Promise(e=>setTimeout(e,5e3))])}markDirty(e){this.#r.add(e)}#c(){if(!this.#a)return;let e=this.#t.debounceMs??45e3;this.#o=setTimeout(()=>{this.#l()},e)}async#l(){let e=[...this.#r];for(let t of e){let e=this.#t.inFlightTimeoutMs??12e4,n=this.#e.getSynthesis(t);if(n?.inFlightSince!==null&&n?.inFlightSince!==void 0){if(Date.now()-new Date(n.inFlightSince).getTime()<e)continue;this.#e.clearInFlight(t)}this.#r.delete(t);let r=this.#u(t).finally(()=>{this.#s.delete(t)});this.#s.set(t,r)}this.#c()}async#u(e){this.#e.markInFlight(e);try{let t=e===`0000000000000000`?void 0:e,n=await this.#n.run(e,t),r=this.#e.computeSourceMemoryHash(e);this.#e.saveSynthesis(e,n,r),this.#i.delete(e)}catch(t){let n=(this.#i.get(e)??0)+1;this.#i.set(e,n);let r=Math.min(n,5),i=(this.#t.debounceMs??45e3)*r;process.stderr.write(`membank synthesis: error for scope=${e} failures=${n} backoff=${i}ms: ${t instanceof Error?t.message:String(t)}\n`),setTimeout(()=>{this.#r.add(e)},i),this.#e.clearInFlight(e)}}};function tt(e,t,n){let r=n.getVersion(e,t);if(r===void 0)throw Error(`Version ${t} not found for scope: ${e}`);return n.saveSynthesis(e,r.content,r.sourceMemoryHash)}async function nt(e,t){let n=e===`0000000000000000`?void 0:e;t.synthRepo.markInFlight(e);try{let[r,i]=await Promise.all([t.agentRunner.run(e,n),Promise.resolve(t.synthRepo.computeSourceMemoryHash(e))]);return t.synthRepo.saveSynthesis(e,r,i),r}catch(n){throw t.synthRepo.clearInFlight(e),n}}var rt=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=(0,v.createSdkMcpServer)({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[(0,v.tool)(`query_memory`,`Search memories by semantic similarity`,{query:u.z.string().describe(`Search text`),limit:u.z.number().optional().describe(`Maximum results to return`),global:u.z.boolean().optional().describe(`Query global memories only when true, otherwise current project scope`)},async({query:e,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:e,...n!==void 0&&{limit:n},...r!==void 0&&{global:r},...t!==void 0&&{projectHash:t}})}]}),{annotations:{readOnlyHint:!0}}),(0,v.tool)(`get_memory_summary`,`Returns aggregate stats: total memories, counts by type, pinned count, review queue size`,{},async()=>({content:[{type:`text`,text:await this.#e.getMemorySummary()}]}),{annotations:{readOnlyHint:!0}})]}),r=`Synthesize the memories for ${e===`0000000000000000`?`global (across all projects)`:`project scope: ${e}`}. Use get_memory_summary first to understand the overall state, then use query_memory to retrieve relevant memories (query with broad terms like "preferences", "corrections", "decisions", "key facts"). After gathering information, produce a concise synthesis of the most important things to remember about this user. Output only the synthesis text — no preamble, no metadata.`,i=Date.now(),a=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),o=(0,v.query)({prompt:r,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:`You are a memory synthesizer. Your job is to read the user's stored memories and produce a concise, well-structured summary of what's most important to remember about this user — their preferences, corrections, decisions, and key facts. Pinned memories are higher fidelity and should be weighted more heavily. Exclude transient or ephemeral details. Output plain text suitable for injection into an LLM context window. Be concise — target 200-400 words.`,mcpServers:{"membank-synthesis-tools":n},allowedTools:[`mcp__membank-synthesis-tools__query_memory`,`mcp__membank-synthesis-tools__get_memory_summary`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:a}}),s=``;for await(let e of o)if(e.type===`result`)if(e.subtype===`success`)s=e.result;else{let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Synthesis agent failed: ${e.subtype}${t}`)}let c=Date.now()-i;if(process.stderr.write(`membank synthesis: scope=${e} duration=${c}ms\n`),s===``)throw Error(`Synthesis agent returned empty result`);return s}};function it(e,t){return new rt(e,t)}function at(e){return F.parse({id:e.id,scope:e.scope,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,expiresAt:e.expires_at,inFlightSince:e.in_flight_since,createdAt:e.created_at,updatedAt:e.updated_at})}function $(e){return e.content===`pending`&&e.source_memory_hash===``}var ot=class{#e;constructor(e){this.#e=e}saveSynthesis(e,t,n){let r=new Date().toISOString(),i=new Date(Date.now()+720*60*60*1e3).toISOString(),{id:a,createdAt:o}=this.#e.db.transaction(()=>{let a=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);if(a!==void 0)return $(a)||this.#t(e),this.#e.db.prepare(`UPDATE syntheses
372
+ SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
373
+ in_flight_since = NULL, updated_at = ?
374
+ WHERE scope = ?`).run(t,n,r,i,r,e),{id:a.id,createdAt:a.created_at};let o=(0,l.randomUUID)();return this.#e.db.prepare(`INSERT INTO syntheses
345
375
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
346
376
  in_flight_since, created_at, updated_at)
347
- VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`).run(a,e,t,n,r,i,r,r)}let a=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);if(a===void 0)throw Error(`Failed to save synthesis for scope: ${e}`);return $(a)}getSynthesis(e){let t=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);return t===void 0?void 0:$(t)}listAll(){return this.#e.db.prepare(`SELECT * FROM syntheses ORDER BY scope`).all().map($)}markInFlight(e){let t=new Date().toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = ?, updated_at = ? WHERE scope = ?`).run(t,t,e);else{let n=(0,l.randomUUID)(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
377
+ VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`).run(o,e,t,n,r,i,r,r),{id:o,createdAt:r}})();return F.parse({id:a,scope:e,content:t,sourceMemoryHash:n,synthesizedAt:r,expiresAt:i,inFlightSince:null,createdAt:o,updatedAt:r})}listVersions(e){return this.#e.db.prepare(`SELECT * FROM synthesis_versions WHERE scope = ? ORDER BY version DESC`).all(e).map(H)}getVersion(e,t){let n=this.#e.db.prepare(`SELECT * FROM synthesis_versions WHERE scope = ? AND version = ?`).get(e,t);return n===void 0?void 0:H(n)}#t(e){let t=this.#e.db.prepare(`SELECT s.content, s.source_memory_hash, s.synthesized_at,
378
+ COALESCE(MAX(v.version), 0) + 1 AS next_version
379
+ FROM syntheses s
380
+ LEFT JOIN synthesis_versions v ON v.scope = s.scope
381
+ WHERE s.scope = ?
382
+ GROUP BY s.scope`).get(e);t!==void 0&&(this.#e.db.prepare(`INSERT INTO synthesis_versions (scope, version, content, source_memory_hash, synthesized_at)
383
+ VALUES (?, ?, ?, ?, ?)`).run(e,t.next_version,t.content,t.source_memory_hash,t.synthesized_at),this.#e.db.prepare(`DELETE FROM synthesis_versions WHERE scope = ? AND version <= ?`).run(e,t.next_version-5))}getSynthesis(e){let t=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);return t===void 0?void 0:at(t)}listAll(){return this.#e.db.prepare(`SELECT * FROM syntheses ORDER BY scope`).all().map(at)}markInFlight(e){let t=new Date().toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = ?, updated_at = ? WHERE scope = ?`).run(t,t,e);else{let n=(0,l.randomUUID)(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
348
384
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
349
385
  in_flight_since, created_at, updated_at)
350
386
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(n,e,`pending`,``,t,r,t,t,t)}}clearInFlight(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = NULL, updated_at = ? WHERE scope = ?`).run(t,e)}clearStaleInFlight(e){let t=new Date(Date.now()-e).toISOString(),n=new Date().toISOString();this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = NULL, updated_at = ? WHERE in_flight_since IS NOT NULL AND in_flight_since < ?`).run(n,t)}computeSourceMemoryHash(e){let t=this.#e.db.prepare(`SELECT m.content FROM memories m
351
387
  JOIN memory_projects mp ON mp.memory_id = m.id
352
388
  JOIN projects p ON p.id = mp.project_id
353
389
  WHERE p.scope_hash = ?
354
- ORDER BY m.id`).all(e);return(0,l.createHash)(`sha256`).update(JSON.stringify(t.map(e=>e.content))).digest(`hex`)}getExpiredOrDirtyScopes(){let e=this.getAllActiveScopes(),t=new Date().toISOString(),n=[];for(let r of e){let e=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(r);if(e===void 0||e.content===`pending`&&e.source_memory_hash===``){n.push({scope:r,reason:`missing`});continue}if(e.expires_at<=t){n.push({scope:r,reason:`expired`});continue}this.computeSourceMemoryHash(r)!==e.source_memory_hash&&n.push({scope:r,reason:`dirty`})}return n}getAllActiveScopes(){return this.#e.db.prepare(`SELECT DISTINCT scope_hash FROM projects`).all().map(e=>e.scope_hash)}expireStale(){let e=new Date().toISOString();this.#e.db.prepare(`DELETE FROM syntheses WHERE expires_at < ?`).run(e)}};function et(e){return new $e(e)}exports.ACTIVITY_EVENT_TYPE_VALUES=y,exports.ActivityEventTypeSchema=b,exports.DatabaseError=H,exports.DatabaseManager=fe,exports.EmbeddingService=he,exports.GLOBAL_PROJECT_ID=c.t,exports.GLOBAL_PROJECT_NAME=c.n,exports.GLOBAL_SCOPE_HASH=c.r,exports.MEMORY_TYPE_VALUES=w,exports.MIGRATIONS=Re,exports.MODEL_NAME=U,exports.MembankError=V,exports.MemoryPatchSchema=P,exports.MemoryRowSchema=I,exports.MemorySchema=j,exports.MemoryTypeSchema=T,exports.ModelDownloadError=W,exports.ModelDownloader=me,exports.PIN_BUDGET_THRESHOLD=J,exports.ProjectRowSchema=L,exports.ProjectSchema=D,exports.QueryEngine=Ke,exports.QueryOptionsSchema=M,exports.RETENTION_DAYS=30,exports.ReviewEventRowSchema=A,exports.ReviewEventSchema=k,exports.ReviewReasonSchema=O,exports.SaveOptionsSchema=N,exports.SessionContextBuilder=Je,exports.SessionContextSchema=le,exports.SqliteMemoryRepository=Y,exports.SynthesisEngine=Ye,exports.SynthesisSchema=F,exports.TagsJsonSchema=E,exports.clusterFlagged=De,exports.createActivityLogger=oe,exports.createActivityRepository=ae,exports.createClaudeCodeTranscriptReader=Ee,exports.createExtractionAgentRunner=ye,exports.createExtractionRunRepository=Ce,exports.createMemoryRepository=Fe,exports.createProjectRepository=Ve,exports.createSynthesisAgentRunner=Qe,exports.createSynthesisRepository=et,exports.deleteManyMemories=Oe,exports.deleteMemory=K,exports.getSessionContext=Q,exports.isOverBudget=Pe,exports.isSynthesisEnabled=ce,exports.listEvents=re,exports.listMemoryTypes=qe,exports.logEvent=x,exports.mergeMemories=ke,exports.noopActivityLogger=C,exports.queryMemories=We,exports.resolveProject=Ie,exports.resolveReview=Ae,exports.resolveReviewMany=je,exports.resolveScope=Le,exports.rowToMemory=R,exports.rowToProject=B,exports.runExtraction=ge,exports.runScopeToProjectsMigration=ze,exports.runSynthesis=Xe,exports.saveMemory=Me,exports.updateMemory=Ne;
390
+ ORDER BY m.id`).all(e);return(0,l.createHash)(`sha256`).update(JSON.stringify(t.map(e=>e.content))).digest(`hex`)}getExpiredOrDirtyScopes(){let e=this.getAllActiveScopes(),t=new Date().toISOString(),n=[];for(let r of e){let e=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(r);if(e===void 0||$(e)){n.push({scope:r,reason:`missing`});continue}if(e.expires_at<=t){n.push({scope:r,reason:`expired`});continue}this.computeSourceMemoryHash(r)!==e.source_memory_hash&&n.push({scope:r,reason:`dirty`})}return n}getAllActiveScopes(){return this.#e.db.prepare(`SELECT DISTINCT scope_hash FROM projects`).all().map(e=>e.scope_hash)}expireStale(){let e=new Date().toISOString();this.#e.db.prepare(`DELETE FROM syntheses WHERE expires_at < ?`).run(e)}};function st(e){return new ot(e)}exports.ACTIVITY_EVENT_TYPE_VALUES=y,exports.ActivityEventTypeSchema=b,exports.DatabaseError=W,exports.DatabaseManager=me,exports.EmbeddingService=_e,exports.GLOBAL_PROJECT_ID=c.t,exports.GLOBAL_PROJECT_NAME=c.n,exports.GLOBAL_SCOPE_HASH=c.r,exports.MEMORY_TYPE_VALUES=w,exports.MIGRATIONS=He,exports.MODEL_NAME=G,exports.MembankError=U,exports.MemoryPatchSchema=P,exports.MemoryRowSchema=I,exports.MemorySchema=j,exports.MemoryTypeSchema=T,exports.MemoryVersionRowSchema=ue,exports.ModelDownloadError=K,exports.ModelDownloader=ge,exports.PIN_BUDGET_THRESHOLD=X,exports.ProjectRowSchema=L,exports.ProjectSchema=D,exports.QueryEngine=Xe,exports.QueryOptionsSchema=M,exports.RETENTION_DAYS=30,exports.ReviewEventRowSchema=A,exports.ReviewEventSchema=k,exports.ReviewReasonSchema=O,exports.SaveOptionsSchema=N,exports.SessionContextBuilder=$e,exports.SessionContextSchema=le,exports.SqliteMemoryRepository=Z,exports.SynthesisEngine=et,exports.SynthesisSchema=F,exports.SynthesisVersionRowSchema=de,exports.TagsJsonSchema=E,exports.clusterFlagged=ke,exports.createActivityLogger=oe,exports.createActivityRepository=ae,exports.createClaudeCodeTranscriptReader=Oe,exports.createExtractionAgentRunner=xe,exports.createExtractionRunRepository=Te,exports.createMemoryRepository=Re,exports.createProjectRepository=Ge,exports.createSynthesisAgentRunner=it,exports.createSynthesisRepository=st,exports.deleteManyMemories=Ae,exports.deleteMemory=J,exports.getSessionContext=Ze,exports.isOverBudget=Le,exports.isSynthesisEnabled=ce,exports.listEvents=re,exports.listMemoryTypes=Qe,exports.logEvent=x,exports.mergeMemories=je,exports.noopActivityLogger=C,exports.queryMemories=Je,exports.resolveProject=Be,exports.resolveReview=Me,exports.resolveReviewMany=Ne,exports.resolveScope=Ve,exports.revertMemory=Pe,exports.revertSynthesis=tt,exports.rowToMemory=R,exports.rowToProject=B,exports.runExtraction=ve,exports.runScopeToProjectsMigration=Ue,exports.runSynthesis=nt,exports.saveMemory=Fe,exports.updateMemory=Ie;
package/dist/index.d.cts CHANGED
@@ -103,6 +103,22 @@ declare function createActivityLogger(db: DatabaseManager): ActivityLogger;
103
103
  //#region src/config/loader.d.ts
104
104
  declare function isSynthesisEnabled(): boolean;
105
105
  //#endregion
106
+ //#region src/memory/domain/memory-version.d.ts
107
+ type MemoryVersion = {
108
+ version: number;
109
+ content: string;
110
+ createdAt: string;
111
+ };
112
+ //#endregion
113
+ //#region src/synthesis/domain/synthesis-version.d.ts
114
+ type SynthesisVersion = {
115
+ version: number;
116
+ content: string;
117
+ sourceMemoryHash: string;
118
+ synthesizedAt: string;
119
+ createdAt: string;
120
+ };
121
+ //#endregion
106
122
  //#region src/schemas.d.ts
107
123
  declare const MEMORY_TYPE_VALUES: readonly ["correction", "preference", "decision", "learning", "fact"];
108
124
  declare const MemoryTypeSchema: z.ZodEnum<{
@@ -339,6 +355,24 @@ declare const MemoryRowSchema: z.ZodObject<{
339
355
  updated_at: z.ZodString;
340
356
  }, z.core.$strip>;
341
357
  type MemoryRow = z.infer<typeof MemoryRowSchema>;
358
+ declare const MemoryVersionRowSchema: z.ZodObject<{
359
+ id: z.ZodNumber;
360
+ memory_id: z.ZodString;
361
+ version: z.ZodNumber;
362
+ content: z.ZodString;
363
+ created_at: z.ZodString;
364
+ }, z.core.$strip>;
365
+ type MemoryVersionRow = z.infer<typeof MemoryVersionRowSchema>;
366
+ declare const SynthesisVersionRowSchema: z.ZodObject<{
367
+ id: z.ZodNumber;
368
+ scope: z.ZodString;
369
+ version: z.ZodNumber;
370
+ content: z.ZodString;
371
+ source_memory_hash: z.ZodString;
372
+ synthesized_at: z.ZodString;
373
+ created_at: z.ZodString;
374
+ }, z.core.$strip>;
375
+ type SynthesisVersionRow = z.infer<typeof SynthesisVersionRowSchema>;
342
376
  declare const ProjectRowSchema: z.ZodObject<{
343
377
  id: z.ZodString;
344
378
  name: z.ZodString;
@@ -482,6 +516,8 @@ interface MemoryRepository {
482
516
  incrementAccessCount(id: string): void;
483
517
  exportAll(): MemoryExportRecord[];
484
518
  importAll(records: MemoryExportRecord[]): void;
519
+ listVersions(memoryId: string): MemoryVersion[];
520
+ getVersion(memoryId: string, version: number): MemoryVersion | undefined;
485
521
  }
486
522
  interface Embedder {
487
523
  embed(text: string): Promise<Float32Array>;
@@ -624,6 +660,13 @@ declare function resolveReview(memoryId: string, repo: MemoryRepository): void;
624
660
  //#region src/memory/application/resolve-review-many.d.ts
625
661
  declare function resolveReviewMany(ids: string[], repo: MemoryRepository): BulkOpResult[];
626
662
  //#endregion
663
+ //#region src/memory/application/revert-memory.d.ts
664
+ declare function revertMemory(id: string, version: number, deps: {
665
+ repo: MemoryRepository;
666
+ embedder: Embedder;
667
+ activityLogger?: ActivityLogger;
668
+ }): Promise<Memory>;
669
+ //#endregion
627
670
  //#region src/memory/application/save-memory.d.ts
628
671
  declare function saveMemory(opts: SaveOptions, deps: {
629
672
  repo: MemoryRepository;
@@ -696,6 +739,8 @@ declare class SqliteMemoryRepository implements MemoryRepository {
696
739
  incrementAccessCount(id: string): void;
697
740
  exportAll(): MemoryExportRecord[];
698
741
  importAll(records: MemoryExportRecord[]): void;
742
+ listVersions(memoryId: string): MemoryVersion[];
743
+ getVersion(memoryId: string, version: number): MemoryVersion | undefined;
699
744
  }
700
745
  declare function createMemoryRepository(db: DatabaseManager, projects: ProjectRepository): MemoryRepository;
701
746
  //#endregion
@@ -802,6 +847,8 @@ interface SynthesisRepository {
802
847
  saveSynthesis(scope: string, content: string, sourceHash: string): Synthesis;
803
848
  getSynthesis(scope: string): Synthesis | undefined;
804
849
  listAll(): Synthesis[];
850
+ listVersions(scope: string): SynthesisVersion[];
851
+ getVersion(scope: string, version: number): SynthesisVersion | undefined;
805
852
  markInFlight(scope: string): void;
806
853
  clearInFlight(scope: string): void;
807
854
  clearStaleInFlight(thresholdMs: number): void;
@@ -820,6 +867,9 @@ declare class SynthesisEngine {
820
867
  markDirty(scope: string): void;
821
868
  }
822
869
  //#endregion
870
+ //#region src/synthesis/application/revert-synthesis.d.ts
871
+ declare function revertSynthesis(scope: string, version: number, repo: SynthesisRepository): Synthesis;
872
+ //#endregion
823
873
  //#region src/synthesis/application/run-synthesis.d.ts
824
874
  declare function runSynthesis(scope: string, deps: {
825
875
  synthRepo: SynthesisRepository;
@@ -832,5 +882,5 @@ declare function createSynthesisAgentRunner(tools: SynthesisTools, config: Synth
832
882
  //#region src/synthesis/infrastructure/sqlite-synthesis-repository.d.ts
833
883
  declare function createSynthesisRepository(db: DatabaseManager): SynthesisRepository;
834
884
  //#endregion
835
- export { ACTIVITY_EVENT_TYPE_VALUES, type ActivityEvent, type ActivityEventInput, type ActivityEventType, ActivityEventTypeSchema, type ActivityLogger, type ActivityRepository, type AgentRunner, type BulkOpResult, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, type FlagCluster, GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type ListEventsFilter, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, type MergeMemoriesOpts, type MergeMemoriesResult, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, RETENTION_DAYS, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, type ReviewQueueStats, ReviewReason, ReviewReasonSchema, type RunExtractionInput, type RunExtractionResult, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, TagsJsonSchema, type TranscriptReader, clusterFlagged, createActivityLogger, createActivityRepository, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteManyMemories, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listEvents, listMemoryTypes, logEvent, mergeMemories, noopActivityLogger, queryMemories, resolveProject, resolveReview, resolveReviewMany, resolveScope, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
885
+ export { ACTIVITY_EVENT_TYPE_VALUES, type ActivityEvent, type ActivityEventInput, type ActivityEventType, ActivityEventTypeSchema, type ActivityLogger, type ActivityRepository, type AgentRunner, type BulkOpResult, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, type FlagCluster, GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type ListEventsFilter, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, type MemoryVersion, MemoryVersionRow, MemoryVersionRowSchema, type MergeMemoriesOpts, type MergeMemoriesResult, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, RETENTION_DAYS, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, type ReviewQueueStats, ReviewReason, ReviewReasonSchema, type RunExtractionInput, type RunExtractionResult, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, type SynthesisVersion, SynthesisVersionRow, SynthesisVersionRowSchema, TagsJsonSchema, type TranscriptReader, clusterFlagged, createActivityLogger, createActivityRepository, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteManyMemories, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listEvents, listMemoryTypes, logEvent, mergeMemories, noopActivityLogger, queryMemories, resolveProject, resolveReview, resolveReviewMany, resolveScope, revertMemory, revertSynthesis, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
836
886
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -103,6 +103,22 @@ declare function createActivityLogger(db: DatabaseManager): ActivityLogger;
103
103
  //#region src/config/loader.d.ts
104
104
  declare function isSynthesisEnabled(): boolean;
105
105
  //#endregion
106
+ //#region src/memory/domain/memory-version.d.ts
107
+ type MemoryVersion = {
108
+ version: number;
109
+ content: string;
110
+ createdAt: string;
111
+ };
112
+ //#endregion
113
+ //#region src/synthesis/domain/synthesis-version.d.ts
114
+ type SynthesisVersion = {
115
+ version: number;
116
+ content: string;
117
+ sourceMemoryHash: string;
118
+ synthesizedAt: string;
119
+ createdAt: string;
120
+ };
121
+ //#endregion
106
122
  //#region src/schemas.d.ts
107
123
  declare const MEMORY_TYPE_VALUES: readonly ["correction", "preference", "decision", "learning", "fact"];
108
124
  declare const MemoryTypeSchema: z.ZodEnum<{
@@ -339,6 +355,24 @@ declare const MemoryRowSchema: z.ZodObject<{
339
355
  updated_at: z.ZodString;
340
356
  }, z.core.$strip>;
341
357
  type MemoryRow = z.infer<typeof MemoryRowSchema>;
358
+ declare const MemoryVersionRowSchema: z.ZodObject<{
359
+ id: z.ZodNumber;
360
+ memory_id: z.ZodString;
361
+ version: z.ZodNumber;
362
+ content: z.ZodString;
363
+ created_at: z.ZodString;
364
+ }, z.core.$strip>;
365
+ type MemoryVersionRow = z.infer<typeof MemoryVersionRowSchema>;
366
+ declare const SynthesisVersionRowSchema: z.ZodObject<{
367
+ id: z.ZodNumber;
368
+ scope: z.ZodString;
369
+ version: z.ZodNumber;
370
+ content: z.ZodString;
371
+ source_memory_hash: z.ZodString;
372
+ synthesized_at: z.ZodString;
373
+ created_at: z.ZodString;
374
+ }, z.core.$strip>;
375
+ type SynthesisVersionRow = z.infer<typeof SynthesisVersionRowSchema>;
342
376
  declare const ProjectRowSchema: z.ZodObject<{
343
377
  id: z.ZodString;
344
378
  name: z.ZodString;
@@ -482,6 +516,8 @@ interface MemoryRepository {
482
516
  incrementAccessCount(id: string): void;
483
517
  exportAll(): MemoryExportRecord[];
484
518
  importAll(records: MemoryExportRecord[]): void;
519
+ listVersions(memoryId: string): MemoryVersion[];
520
+ getVersion(memoryId: string, version: number): MemoryVersion | undefined;
485
521
  }
486
522
  interface Embedder {
487
523
  embed(text: string): Promise<Float32Array>;
@@ -624,6 +660,13 @@ declare function resolveReview(memoryId: string, repo: MemoryRepository): void;
624
660
  //#region src/memory/application/resolve-review-many.d.ts
625
661
  declare function resolveReviewMany(ids: string[], repo: MemoryRepository): BulkOpResult[];
626
662
  //#endregion
663
+ //#region src/memory/application/revert-memory.d.ts
664
+ declare function revertMemory(id: string, version: number, deps: {
665
+ repo: MemoryRepository;
666
+ embedder: Embedder;
667
+ activityLogger?: ActivityLogger;
668
+ }): Promise<Memory>;
669
+ //#endregion
627
670
  //#region src/memory/application/save-memory.d.ts
628
671
  declare function saveMemory(opts: SaveOptions, deps: {
629
672
  repo: MemoryRepository;
@@ -696,6 +739,8 @@ declare class SqliteMemoryRepository implements MemoryRepository {
696
739
  incrementAccessCount(id: string): void;
697
740
  exportAll(): MemoryExportRecord[];
698
741
  importAll(records: MemoryExportRecord[]): void;
742
+ listVersions(memoryId: string): MemoryVersion[];
743
+ getVersion(memoryId: string, version: number): MemoryVersion | undefined;
699
744
  }
700
745
  declare function createMemoryRepository(db: DatabaseManager, projects: ProjectRepository): MemoryRepository;
701
746
  //#endregion
@@ -802,6 +847,8 @@ interface SynthesisRepository {
802
847
  saveSynthesis(scope: string, content: string, sourceHash: string): Synthesis;
803
848
  getSynthesis(scope: string): Synthesis | undefined;
804
849
  listAll(): Synthesis[];
850
+ listVersions(scope: string): SynthesisVersion[];
851
+ getVersion(scope: string, version: number): SynthesisVersion | undefined;
805
852
  markInFlight(scope: string): void;
806
853
  clearInFlight(scope: string): void;
807
854
  clearStaleInFlight(thresholdMs: number): void;
@@ -820,6 +867,9 @@ declare class SynthesisEngine {
820
867
  markDirty(scope: string): void;
821
868
  }
822
869
  //#endregion
870
+ //#region src/synthesis/application/revert-synthesis.d.ts
871
+ declare function revertSynthesis(scope: string, version: number, repo: SynthesisRepository): Synthesis;
872
+ //#endregion
823
873
  //#region src/synthesis/application/run-synthesis.d.ts
824
874
  declare function runSynthesis(scope: string, deps: {
825
875
  synthRepo: SynthesisRepository;
@@ -832,5 +882,5 @@ declare function createSynthesisAgentRunner(tools: SynthesisTools, config: Synth
832
882
  //#region src/synthesis/infrastructure/sqlite-synthesis-repository.d.ts
833
883
  declare function createSynthesisRepository(db: DatabaseManager): SynthesisRepository;
834
884
  //#endregion
835
- export { ACTIVITY_EVENT_TYPE_VALUES, type ActivityEvent, type ActivityEventInput, type ActivityEventType, ActivityEventTypeSchema, type ActivityLogger, type ActivityRepository, type AgentRunner, type BulkOpResult, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, type FlagCluster, GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type ListEventsFilter, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, type MergeMemoriesOpts, type MergeMemoriesResult, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, RETENTION_DAYS, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, type ReviewQueueStats, ReviewReason, ReviewReasonSchema, type RunExtractionInput, type RunExtractionResult, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, TagsJsonSchema, type TranscriptReader, clusterFlagged, createActivityLogger, createActivityRepository, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteManyMemories, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listEvents, listMemoryTypes, logEvent, mergeMemories, noopActivityLogger, queryMemories, resolveProject, resolveReview, resolveReviewMany, resolveScope, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
885
+ export { ACTIVITY_EVENT_TYPE_VALUES, type ActivityEvent, type ActivityEventInput, type ActivityEventType, ActivityEventTypeSchema, type ActivityLogger, type ActivityRepository, type AgentRunner, type BulkOpResult, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, type FlagCluster, GLOBAL_PROJECT_ID, GLOBAL_PROJECT_NAME, GLOBAL_SCOPE_HASH, type ListEventsFilter, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, type MemoryVersion, MemoryVersionRow, MemoryVersionRowSchema, type MergeMemoriesOpts, type MergeMemoriesResult, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, RETENTION_DAYS, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, type ReviewQueueStats, ReviewReason, ReviewReasonSchema, type RunExtractionInput, type RunExtractionResult, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, type SynthesisVersion, SynthesisVersionRow, SynthesisVersionRowSchema, TagsJsonSchema, type TranscriptReader, clusterFlagged, createActivityLogger, createActivityRepository, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteManyMemories, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listEvents, listMemoryTypes, logEvent, mergeMemories, noopActivityLogger, queryMemories, resolveProject, resolveReview, resolveReviewMany, resolveScope, revertMemory, revertSynthesis, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
836
886
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import{n as e,r as t,t as n}from"./global-scope-B463kRq-.mjs";import{createHash as r,randomUUID as i}from"node:crypto";import{z as a}from"zod";import{existsSync as o,mkdirSync as s,readFileSync as c,readdirSync as l}from"node:fs";import{homedir as u}from"node:os";import{dirname as d,join as f}from"node:path";import p from"better-sqlite3";import*as m from"sqlite-vec";import{EventEmitter as h}from"node:events";import{pipeline as g}from"@huggingface/transformers";import{createSdkMcpServer as _,query as v,tool as y}from"@anthropic-ai/claude-agent-sdk";import{readFile as ee}from"node:fs/promises";import{execFile as te}from"node:child_process";import{promisify as ne}from"node:util";function re(e,t){return t.list(e)}const b=[`memory.created`,`memory.updated`,`memory.deleted`,`memory.flagged`,`memory.queried`],x=a.enum(b),ie=30;function S(e,t){let n=new Date,r=n.toISOString();t.insert({id:i(),projectHash:e.projectHash,eventType:e.eventType,memoryId:e.memoryId??null,payload:e.payload??{},createdAt:r});let a=new Date(n);a.setDate(a.getDate()-30),t.prune(a.toISOString())}function ae(e){return{id:e.id,projectHash:e.project_hash,eventType:x.parse(e.event_type),memoryId:e.memory_id,payload:JSON.parse(e.payload),createdAt:e.created_at}}var C=class{#e;#t=0;#n;#r;constructor(e){this.#e=e,this.#n=e.db.prepare(`INSERT INTO activity_events (id, project_hash, event_type, memory_id, payload, created_at)
2
- VALUES (?, ?, ?, ?, ?, ?)`),this.#r=e.db.prepare(`DELETE FROM activity_events WHERE created_at < ?`)}insert(e){this.#n.run(e.id,e.projectHash,e.eventType,e.memoryId,JSON.stringify(e.payload),e.createdAt)}list(e){let t=[],n=[];e.scope!==void 0&&(t.push(`project_hash = ?`),n.push(e.scope)),e.type!==void 0&&(t.push(`event_type = ?`),n.push(e.type)),e.since!==void 0&&(t.push(`created_at >= ?`),n.push(e.since));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit===void 0?``:`LIMIT ?`;return e.limit!==void 0&&n.push(e.limit),this.#e.db.prepare(`SELECT * FROM activity_events ${r} ORDER BY created_at DESC ${i}`).all(...n).map(ae)}prune(e){let t=Date.now();t-this.#t<6e4||(this.#r.run(e),this.#t=t)}};function oe(e){return new C(e)}function se(e){let t=new C(e);return{logEvent:e=>S(e,t)}}const w={logEvent(){}};function ce(){let e=f(u(),`.membank`,`config.json`);try{let t=c(e,`utf8`);return JSON.parse(t)}catch{return null}}function le(){return ce()?.synthesis?.enabled===!0}const T=[`correction`,`preference`,`decision`,`learning`,`fact`],E=a.enum(T),D=a.array(a.string()),O=a.object({id:a.string(),name:a.string(),scopeHash:a.string(),createdAt:a.string(),updatedAt:a.string()}),k=a.enum([`similarity_dedup`]),A=a.object({id:a.string(),memoryId:a.string(),conflictingMemoryId:a.string().nullable(),similarity:a.number(),conflictContentSnapshot:a.string(),reason:k,createdAt:a.string(),resolvedAt:a.string().nullable()}),j=a.object({id:a.string(),memory_id:a.string(),conflicting_memory_id:a.string().nullable(),similarity:a.number(),conflict_content_snapshot:a.string(),reason:k,created_at:a.string(),resolved_at:a.string().nullable()}),M=a.object({id:a.string(),content:a.string(),type:E,tags:a.array(a.string()),projects:a.array(O),sourceHarness:a.string().nullable(),accessCount:a.number().int().nonnegative(),pinned:a.boolean(),reviewEvents:a.array(A),createdAt:a.string(),updatedAt:a.string()}),N=a.object({query:a.string().min(1),type:E.optional(),projectHash:a.string().optional(),limit:a.number().int().positive().optional(),includePinned:a.boolean().optional()}),P=a.object({content:a.string().min(1),type:E,tags:a.array(a.string()).optional(),projectScope:a.object({hash:a.string(),name:a.string()}).optional(),sourceHarness:a.string().optional()}),F=a.object({content:a.string().min(1).optional(),tags:a.array(a.string()).optional(),type:E.optional()}),I=a.object({id:a.string(),scope:a.string(),content:a.string(),sourceMemoryHash:a.string(),synthesizedAt:a.string(),expiresAt:a.string(),inFlightSince:a.string().nullable(),createdAt:a.string(),updatedAt:a.string()}),ue=a.object({stats:a.record(E,a.number()),pinnedGlobal:a.array(M),pinnedProject:a.array(M),synthesis:a.string().optional()}),L=a.object({id:a.string(),content:a.string(),type:a.string(),tags:a.string(),source:a.string().nullable(),access_count:a.number(),pinned:a.number(),created_at:a.string(),updated_at:a.string()}),R=a.object({id:a.string(),name:a.string(),scope_hash:a.string(),created_at:a.string(),updated_at:a.string()});function z(e,t,n=[]){return{id:e.id,content:e.content,type:E.parse(e.type),tags:D.parse(JSON.parse(e.tags)),projects:t,sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,reviewEvents:n,createdAt:e.created_at,updatedAt:e.updated_at}}function B(e){let t=j.parse(e);return{id:t.id,memoryId:t.memory_id,conflictingMemoryId:t.conflicting_memory_id,similarity:t.similarity,conflictContentSnapshot:t.conflict_content_snapshot,reason:t.reason,createdAt:t.created_at,resolvedAt:t.resolved_at}}function V(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var H=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},U=class extends H{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const de=f(u(),`.membank`,`memory.db`),fe=[[1,`
2
+ VALUES (?, ?, ?, ?, ?, ?)`),this.#r=e.db.prepare(`DELETE FROM activity_events WHERE created_at < ?`)}insert(e){this.#n.run(e.id,e.projectHash,e.eventType,e.memoryId,JSON.stringify(e.payload),e.createdAt)}list(e){let t=[],n=[];e.scope!==void 0&&(t.push(`project_hash = ?`),n.push(e.scope)),e.type!==void 0&&(t.push(`event_type = ?`),n.push(e.type)),e.since!==void 0&&(t.push(`created_at >= ?`),n.push(e.since));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit===void 0?``:`LIMIT ?`;return e.limit!==void 0&&n.push(e.limit),this.#e.db.prepare(`SELECT * FROM activity_events ${r} ORDER BY created_at DESC ${i}`).all(...n).map(ae)}prune(e){let t=Date.now();t-this.#t<6e4||(this.#r.run(e),this.#t=t)}};function oe(e){return new C(e)}function se(e){let t=new C(e);return{logEvent:e=>S(e,t)}}const w={logEvent(){}};function ce(){let e=f(u(),`.membank`,`config.json`);try{let t=c(e,`utf8`);return JSON.parse(t)}catch{return null}}function le(){return ce()?.synthesis?.enabled===!0}const T=[`correction`,`preference`,`decision`,`learning`,`fact`],E=a.enum(T),D=a.array(a.string()),O=a.object({id:a.string(),name:a.string(),scopeHash:a.string(),createdAt:a.string(),updatedAt:a.string()}),k=a.enum([`similarity_dedup`]),A=a.object({id:a.string(),memoryId:a.string(),conflictingMemoryId:a.string().nullable(),similarity:a.number(),conflictContentSnapshot:a.string(),reason:k,createdAt:a.string(),resolvedAt:a.string().nullable()}),j=a.object({id:a.string(),memory_id:a.string(),conflicting_memory_id:a.string().nullable(),similarity:a.number(),conflict_content_snapshot:a.string(),reason:k,created_at:a.string(),resolved_at:a.string().nullable()}),M=a.object({id:a.string(),content:a.string(),type:E,tags:a.array(a.string()),projects:a.array(O),sourceHarness:a.string().nullable(),accessCount:a.number().int().nonnegative(),pinned:a.boolean(),reviewEvents:a.array(A),createdAt:a.string(),updatedAt:a.string()}),N=a.object({query:a.string().min(1),type:E.optional(),projectHash:a.string().optional(),limit:a.number().int().positive().optional(),includePinned:a.boolean().optional()}),P=a.object({content:a.string().min(1),type:E,tags:a.array(a.string()).optional(),projectScope:a.object({hash:a.string(),name:a.string()}).optional(),sourceHarness:a.string().optional()}),F=a.object({content:a.string().min(1).optional(),tags:a.array(a.string()).optional(),type:E.optional()}),I=a.object({id:a.string(),scope:a.string(),content:a.string(),sourceMemoryHash:a.string(),synthesizedAt:a.string(),expiresAt:a.string(),inFlightSince:a.string().nullable(),createdAt:a.string(),updatedAt:a.string()}),ue=a.object({stats:a.record(E,a.number()),pinnedGlobal:a.array(M),pinnedProject:a.array(M),synthesis:a.string().optional()}),L=a.object({id:a.string(),content:a.string(),type:a.string(),tags:a.string(),source:a.string().nullable(),access_count:a.number(),pinned:a.number(),created_at:a.string(),updated_at:a.string()}),de=a.object({id:a.number(),memory_id:a.string(),version:a.number(),content:a.string(),created_at:a.string()}),fe=a.object({id:a.number(),scope:a.string(),version:a.number(),content:a.string(),source_memory_hash:a.string(),synthesized_at:a.string(),created_at:a.string()}),R=a.object({id:a.string(),name:a.string(),scope_hash:a.string(),created_at:a.string(),updated_at:a.string()});function z(e,t,n=[]){return{id:e.id,content:e.content,type:E.parse(e.type),tags:D.parse(JSON.parse(e.tags)),projects:t,sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,reviewEvents:n,createdAt:e.created_at,updatedAt:e.updated_at}}function B(e){let t=j.parse(e);return{id:t.id,memoryId:t.memory_id,conflictingMemoryId:t.conflicting_memory_id,similarity:t.similarity,conflictContentSnapshot:t.conflict_content_snapshot,reason:t.reason,createdAt:t.created_at,resolvedAt:t.resolved_at}}function V(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}function H(e){return{version:e.version,content:e.content,createdAt:e.created_at}}function U(e){return{version:e.version,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,createdAt:e.created_at}}var W=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},G=class extends W{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const pe=f(u(),`.membank`,`memory.db`),me=[[1,`
3
3
  CREATE TABLE IF NOT EXISTS memories (
4
4
  id TEXT PRIMARY KEY,
5
5
  content TEXT NOT NULL,
@@ -254,14 +254,38 @@ CREATE INDEX IF NOT EXISTS idx_review_events_memory_open
254
254
  COMMIT;
255
255
 
256
256
  PRAGMA foreign_keys = ON;
257
- `]];var pe=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??de;s(d(n),{recursive:!0});let r=new p(n);return e.#n(r,m.load)}static openInMemory(){return e.#t(m.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new p(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new U(`Failed to load sqlite-vec extension`,{cause:e})}t.pragma(`journal_mode = WAL`),t.pragma(`foreign_keys = ON`);let r=new e(t);return r.#r(),r}#r(){this.#e.exec(`
257
+ `],[12,`
258
+ CREATE TABLE memory_versions (
259
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
260
+ memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
261
+ version INTEGER NOT NULL,
262
+ content TEXT NOT NULL,
263
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
264
+ UNIQUE (memory_id, version)
265
+ );
266
+
267
+ CREATE INDEX idx_memory_versions_memory_id ON memory_versions(memory_id, version DESC);
268
+ `],[13,`
269
+ CREATE TABLE synthesis_versions (
270
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
271
+ scope TEXT NOT NULL REFERENCES projects(scope_hash) ON DELETE CASCADE,
272
+ version INTEGER NOT NULL,
273
+ content TEXT NOT NULL,
274
+ source_memory_hash TEXT NOT NULL,
275
+ synthesized_at TEXT NOT NULL,
276
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
277
+ UNIQUE (scope, version)
278
+ );
279
+
280
+ CREATE INDEX idx_synthesis_versions_scope ON synthesis_versions(scope, version DESC);
281
+ `]];var he=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??pe;s(d(n),{recursive:!0});let r=new p(n);return e.#n(r,m.load)}static openInMemory(){return e.#t(m.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new p(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new G(`Failed to load sqlite-vec extension`,{cause:e})}t.pragma(`journal_mode = WAL`),t.pragma(`foreign_keys = ON`);let r=new e(t);return r.#r(),r}#r(){this.#e.exec(`
258
282
  CREATE TABLE IF NOT EXISTS meta (
259
283
  key TEXT PRIMARY KEY,
260
284
  value TEXT NOT NULL
261
285
  );
262
- `);let e=this.#e.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get(),t=e?Number.parseInt(e.value,10):0;for(let[e,n]of fe)t<e&&(this.#e.exec(n),this.#e.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`).run(String(e)))}get db(){return this.#e}close(){this.#e.close()}};const W=`Xenova/bge-small-en-v1.5`;var G=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function me(){return f(u(),`.membank`,`models`)}function K(e){if(!o(e))return!1;try{return l(e).length>0}catch{return!1}}var he=class extends h{modelPath;constructor(e){super(),this.modelPath=e??me()}isAlreadyCached(){return K(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(K(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await g(`feature-extraction`,W,{cache_dir:this.modelPath,progress_callback:e=>{if(e.status!==`progress`||e.total==null||e.loaded==null)return;let r=e.total,i=e.loaded,a=r>0?i/r*100:0,o=Date.now(),s=o-n,c=i-t,l=0;if(s>0&&c>0){let e=c/s;l=(r-i)/e/1e3}t=i,n=o;let u={totalBytes:r,downloadedBytes:i,percentage:a,estimatedSecondsRemaining:l};this.emit(`progress`,u)}})}catch(e){throw new G(`Failed to download model`,{cause:e})}return{skipped:!1}}},ge=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??f(u(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await g(`feature-extraction`,`Xenova/bge-small-en-v1.5`,{cache_dir:this.modelCachePath,progress_callback:this.onProgress})),this.pipelineInstance}async embed(e){let t=(await(await this.getPipeline())(e,{pooling:`mean`,normalize:!0})).data;return t instanceof Float32Array?t:new Float32Array(t)}};async function _e(e,t){let n=t.now??(()=>new Date);if(!t.repo.tryClaim(e.sessionId,n(),t.config)){let n=t.repo.get(e.sessionId);return{status:`skipped`,reason:n?.status===`completed`&&n.completedAt!==null?`recently_completed`:`in_flight`}}try{let r=await t.transcripts.read(e.transcriptPath);return await t.agent.run({transcript:r,projectHash:e.projectHash,sessionId:e.sessionId}),t.repo.markCompleted(e.sessionId,n()),{status:`completed`}}catch(r){let i=r instanceof Error?r.message:String(r);return t.repo.markFailed(e.sessionId,n(),i),{status:`failed`,error:i}}}const ve=[`You are a memory extractor that runs after a coding session ends. You read the session transcript and CALL save_memory for every durable fact, preference, correction, decision, or learning the user expressed, so that future sessions inherit them.`,``,`Memory types (pick the closest match):`,`- correction: the user told the assistant to stop doing something or to do it differently.`,`- preference: the user stated how they want work done (tools, style, conventions).`,`- decision: the user committed to a choice future work should respect (tech pick, architectural direction, scope cut).`,`- learning: a non-obvious fact about the codebase or tooling that future sessions would otherwise rediscover.`,`- fact: stable info about the user or their project not derivable from the code.`,``,`Bias strongly toward saving. If the user said it in plain language and it would be useful in a future session, save it. Phrasing like 'stop X', 'always Y', 'we use Z', 'don't suggest W', 'we decided', 'from now on' is a clear save signal — even when the assistant in the transcript already acknowledged it, save it so the NEXT session also knows.`,``,`Process:`,`1. Read the supplied transcript end-to-end.`,`2. Identify every distinct durable signal. List them mentally before calling tools.`,`3. Optional: call query_memory with focused search terms to avoid duplicates. If a near-duplicate exists, call update_memory instead of save_memory.`,`4. Call save_memory for each new durable signal. Phrase the content as a standalone instruction or fact — strip session framing ("in this session", "just now"). Good: "Use pnpm, not npm, for all dependency operations." Bad: "User said stop using npm."`,"5. Use `global: true` only when the fact is about the user themselves or applies across every project. Otherwise default to project scope (omit `global`).",``,`Only return without saving when the transcript truly contains no durable signal — pure greetings, time-of-day questions, abandoned tasks. Do not invent facts. If in doubt and the signal is concrete, save it.`].join(`
263
- `);var ye=class{#e;constructor(e){this.#e=e}async run(e){let t=_({name:`membank-extraction-tools`,version:`1.0.0`,tools:[y(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:a.string().describe(`Search text`),limit:a.number().optional().describe(`Maximum results to return`),global:a.boolean().optional().describe(`Query global memories when true, otherwise current project scope`)},async({query:t,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:t,limit:n,global:r,projectHash:e.projectHash})}]}),{annotations:{readOnlyHint:!0}}),y(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:a.string().describe(`Memory content — concise, decontextualised`),type:a.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:a.array(a.string()).optional().describe(`Optional tags`),global:a.boolean().optional().describe(`Save as global memory rather than project-scoped`)},async({content:e,type:t,tags:n,global:r})=>({content:[{type:`text`,text:await this.#e.saveMemory({content:e,type:t,tags:n,global:r})}]})),y(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:a.string().describe(`Memory id`),content:a.string().optional(),type:a.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:a.array(a.string()).optional()},async({id:e,content:t,type:n,tags:r})=>({content:[{type:`text`,text:await this.#e.updateMemory({id:e,content:t,type:n,tags:r})}]}))]}),n=[`Session id: ${e.sessionId}`,``,`Transcript (most recent turns):`,`---`,e.transcript,`---`,``,`Extract durable memories from this transcript following the system instructions.`].join(`
264
- `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),o=v({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:ve,mcpServers:{"membank-extraction-tools":t},allowedTools:[`mcp__membank-extraction-tools__query_memory`,`mcp__membank-extraction-tools__save_memory`,`mcp__membank-extraction-tools__update_memory`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:r}}),s=process.env.MEMBANK_EXTRACTION_DEBUG===`true`;for await(let e of o)if(s&&process.stderr.write(`[extraction debug] ${JSON.stringify(e).slice(0,600)}\n`),e.type===`result`&&e.subtype!==`success`){let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Extraction agent failed: ${e.subtype}${t}`)}let c=Date.now()-i;process.stderr.write(`membank extraction: session=${e.sessionId} duration=${c}ms\n`)}};function be(e){return new ye(e)}function xe(e,t,n,r){return e===void 0?{kind:`claim`}:e.status===`in_flight`?t.getTime()-e.startedAt.getTime()<n?{kind:`skip`,reason:`in_flight`}:{kind:`claim`}:e.status===`completed`&&e.completedAt!==null&&t.getTime()-e.completedAt.getTime()<r?{kind:`skip`,reason:`recently_completed`}:{kind:`claim`}}function Se(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var Ce=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(xe(r===void 0?void 0:{startedAt:new Date(r.started_at),completedAt:r.completed_at===null?null:new Date(r.completed_at),status:r.status},t,n.inFlightTimeoutMs??6e5,n.recentCompletionMs??6e4).kind===`skip`)return!1;let i=t.toISOString();return this.#e.db.prepare(`INSERT INTO extraction_runs (session_id, started_at, completed_at, status, error)
286
+ `);let e=this.#e.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get(),t=e?Number.parseInt(e.value,10):0;for(let[e,n]of me)t<e&&(this.#e.exec(n),this.#e.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`).run(String(e)))}get db(){return this.#e}close(){this.#e.close()}};const K=`Xenova/bge-small-en-v1.5`;var q=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function ge(){return f(u(),`.membank`,`models`)}function J(e){if(!o(e))return!1;try{return l(e).length>0}catch{return!1}}var _e=class extends h{modelPath;constructor(e){super(),this.modelPath=e??ge()}isAlreadyCached(){return J(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(J(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await g(`feature-extraction`,K,{cache_dir:this.modelPath,progress_callback:e=>{if(e.status!==`progress`||e.total==null||e.loaded==null)return;let r=e.total,i=e.loaded,a=r>0?i/r*100:0,o=Date.now(),s=o-n,c=i-t,l=0;if(s>0&&c>0){let e=c/s;l=(r-i)/e/1e3}t=i,n=o;let u={totalBytes:r,downloadedBytes:i,percentage:a,estimatedSecondsRemaining:l};this.emit(`progress`,u)}})}catch(e){throw new q(`Failed to download model`,{cause:e})}return{skipped:!1}}},ve=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??f(u(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await g(`feature-extraction`,`Xenova/bge-small-en-v1.5`,{cache_dir:this.modelCachePath,...this.onProgress!==void 0&&{progress_callback:this.onProgress}})),this.pipelineInstance}async embed(e){let t=(await(await this.getPipeline())(e,{pooling:`mean`,normalize:!0})).data;return t instanceof Float32Array?t:new Float32Array(t)}};async function ye(e,t){let n=t.now??(()=>new Date);if(!t.repo.tryClaim(e.sessionId,n(),t.config)){let n=t.repo.get(e.sessionId);return{status:`skipped`,reason:n?.status===`completed`&&n.completedAt!==null?`recently_completed`:`in_flight`}}try{let r=await t.transcripts.read(e.transcriptPath);return await t.agent.run({transcript:r,projectHash:e.projectHash,sessionId:e.sessionId}),t.repo.markCompleted(e.sessionId,n()),{status:`completed`}}catch(r){let i=r instanceof Error?r.message:String(r);return t.repo.markFailed(e.sessionId,n(),i),{status:`failed`,error:i}}}const be=[`You are a memory extractor that runs after a coding session ends. You read the session transcript and CALL save_memory for every durable fact, preference, correction, decision, or learning the user expressed, so that future sessions inherit them.`,``,`Memory types (pick the closest match):`,`- correction: the user told the assistant to stop doing something or to do it differently.`,`- preference: the user stated how they want work done (tools, style, conventions).`,`- decision: the user committed to a choice future work should respect (tech pick, architectural direction, scope cut).`,`- learning: a non-obvious fact about the codebase or tooling that future sessions would otherwise rediscover.`,`- fact: stable info about the user or their project not derivable from the code.`,``,`Bias strongly toward saving. If the user said it in plain language and it would be useful in a future session, save it. Phrasing like 'stop X', 'always Y', 'we use Z', 'don't suggest W', 'we decided', 'from now on' is a clear save signal — even when the assistant in the transcript already acknowledged it, save it so the NEXT session also knows.`,``,`Process:`,`1. Read the supplied transcript end-to-end.`,`2. Identify every distinct durable signal. List them mentally before calling tools.`,`3. Optional: call query_memory with focused search terms to avoid duplicates. If a near-duplicate exists, call update_memory instead of save_memory.`,`4. Call save_memory for each new durable signal. Phrase the content as a standalone instruction or fact — strip session framing ("in this session", "just now"). Good: "Use pnpm, not npm, for all dependency operations." Bad: "User said stop using npm."`,"5. Use `global: true` only when the fact is about the user themselves or applies across every project. Otherwise default to project scope (omit `global`).",``,`Only return without saving when the transcript truly contains no durable signal — pure greetings, time-of-day questions, abandoned tasks. Do not invent facts. If in doubt and the signal is concrete, save it.`].join(`
287
+ `);var xe=class{#e;constructor(e){this.#e=e}async run(e){let t=_({name:`membank-extraction-tools`,version:`1.0.0`,tools:[y(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:a.string().describe(`Search text`),limit:a.number().optional().describe(`Maximum results to return`),global:a.boolean().optional().describe(`Query global memories when true, otherwise current project scope`)},async({query:t,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:t,...n!==void 0&&{limit:n},...r!==void 0&&{global:r},...e.projectHash!==void 0&&{projectHash:e.projectHash}})}]}),{annotations:{readOnlyHint:!0}}),y(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:a.string().describe(`Memory content — concise, decontextualised`),type:a.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:a.array(a.string()).optional().describe(`Optional tags`),global:a.boolean().optional().describe(`Save as global memory rather than project-scoped`)},async({content:e,type:t,tags:n,global:r})=>({content:[{type:`text`,text:await this.#e.saveMemory({content:e,type:t,...n!==void 0&&{tags:n},...r!==void 0&&{global:r}})}]})),y(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:a.string().describe(`Memory id`),content:a.string().optional(),type:a.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:a.array(a.string()).optional()},async({id:e,content:t,type:n,tags:r})=>({content:[{type:`text`,text:await this.#e.updateMemory({id:e,...t!==void 0&&{content:t},...n!==void 0&&{type:n},...r!==void 0&&{tags:r}})}]}))]}),n=[`Session id: ${e.sessionId}`,``,`Transcript (most recent turns):`,`---`,e.transcript,`---`,``,`Extract durable memories from this transcript following the system instructions.`].join(`
288
+ `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),o=v({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:be,mcpServers:{"membank-extraction-tools":t},allowedTools:[`mcp__membank-extraction-tools__query_memory`,`mcp__membank-extraction-tools__save_memory`,`mcp__membank-extraction-tools__update_memory`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:r}}),s=process.env.MEMBANK_EXTRACTION_DEBUG===`true`;for await(let e of o)if(s&&process.stderr.write(`[extraction debug] ${JSON.stringify(e).slice(0,600)}\n`),e.type===`result`&&e.subtype!==`success`){let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Extraction agent failed: ${e.subtype}${t}`)}let c=Date.now()-i;process.stderr.write(`membank extraction: session=${e.sessionId} duration=${c}ms\n`)}};function Se(e){return new xe(e)}function Ce(e,t,n,r){return e===void 0?{kind:`claim`}:e.status===`in_flight`?t.getTime()-e.startedAt.getTime()<n?{kind:`skip`,reason:`in_flight`}:{kind:`claim`}:e.status===`completed`&&e.completedAt!==null&&t.getTime()-e.completedAt.getTime()<r?{kind:`skip`,reason:`recently_completed`}:{kind:`claim`}}function we(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var Te=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(Ce(r===void 0?void 0:{startedAt:new Date(r.started_at),completedAt:r.completed_at===null?null:new Date(r.completed_at),status:r.status},t,n.inFlightTimeoutMs??6e5,n.recentCompletionMs??6e4).kind===`skip`)return!1;let i=t.toISOString();return this.#e.db.prepare(`INSERT INTO extraction_runs (session_id, started_at, completed_at, status, error)
265
289
  VALUES (?, ?, NULL, 'in_flight', NULL)
266
290
  ON CONFLICT(session_id) DO UPDATE SET
267
291
  started_at = excluded.started_at,
@@ -271,11 +295,11 @@ PRAGMA foreign_keys = ON;
271
295
  SET status = 'completed', completed_at = ?, error = NULL
272
296
  WHERE session_id = ?`).run(t.toISOString(),e)}markFailed(e,t,n){this.#e.db.prepare(`UPDATE extraction_runs
273
297
  SET status = 'failed', completed_at = ?, error = ?
274
- WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:Se(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function we(e){return new Ce(e)}function Te(e){if(typeof e==`string`)return e;if(!Array.isArray(e))return``;let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push(e.text):e.type===`tool_use`&&typeof e.name==`string`?t.push(`[tool_use: ${e.name}]`):e.type===`tool_result`&&t.push(`[tool_result]`)}return t.join(`
275
- `)}var Ee=class{#e;#t;constructor(e={}){this.#e=e.maxTurns??80,this.#t=e.maxChars??6e4}async read(e){let t=(await ee(e,`utf8`)).split(`
276
- `).filter(e=>e.length>0),n=[];for(let e of t){let t;try{t=JSON.parse(e)}catch{continue}let r=t.message?.role;if(r!==`user`&&r!==`assistant`)continue;let i=Te(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
298
+ WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:we(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function Ee(e){return new Te(e)}function De(e){if(typeof e==`string`)return e;if(!Array.isArray(e))return``;let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push(e.text):e.type===`tool_use`&&typeof e.name==`string`?t.push(`[tool_use: ${e.name}]`):e.type===`tool_result`&&t.push(`[tool_result]`)}return t.join(`
299
+ `)}var Oe=class{#e;#t;constructor(e={}){this.#e=e.maxTurns??80,this.#t=e.maxChars??6e4}async read(e){let t=(await ee(e,`utf8`)).split(`
300
+ `).filter(e=>e.length>0),n=[];for(let e of t){let t;try{t=JSON.parse(e)}catch{continue}let r=t.message?.role;if(r!==`user`&&r!==`assistant`)continue;let i=De(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
277
301
 
278
- `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function De(e={}){return new Ee(e)}function Oe(e){let t=new Map;function n(e){t.has(e)||t.set(e,e);let r=t.get(e);if(r!==e){let i=n(r);return t.set(e,i),i}return e}function r(e,r){let i=n(e),a=n(r);i!==a&&t.set(a,i)}for(let{memoryId:t,conflictingMemoryId:n}of e)r(t,n);let i=new Map;for(let e of t.keys()){let t=n(e),r=i.get(t)??[];r.push(e),i.set(t,r)}return Array.from(i.entries()).map(([e,t])=>({clusterId:e,memoryIds:t}))}function q(e,t,n=w){let r=t.findById(e)?.projects[0]?.scopeHash??`0000000000000000`;return t.delete(e),n.logEvent({projectHash:r,eventType:`memory.deleted`,memoryId:e}),Promise.resolve()}async function ke(e,t,n=w){let r=[];for(let i of e)try{await q(i,t,n),r.push({id:i,status:`ok`})}catch(e){r.push({id:i,status:`error`,error:e instanceof Error?e.message:String(e)})}return r}function J(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function Ae(e,t){let{keepId:n,dropIds:r,mergedContent:i}=e,{repo:a,embedder:o,activityLogger:s=w}=t,c=a.findById(n);if(c===void 0)throw Error(`Memory not found: ${n}`);let l=r.map(e=>{let t=a.findById(e);if(t===void 0)throw Error(`Memory not found: ${e}`);return t});for(let e of l)if(e.type!==c.type)throw Error(`Type mismatch: keep memory has type "${c.type}" but drop memory ${e.id} has type "${e.type}"`);let u=[c,...l],d=[...new Set(u.flatMap(e=>e.tags))],f=u.some(e=>e.pinned),p=u.reduce((e,t)=>e+t.accessCount,0),m=await o.embed(i),h=a.overwrite(n,i,m),g=new Set(c.tags);if((d.length!==c.tags.length||d.some(e=>!g.has(e)))&&(h=a.update(n,{tags:d})),f&&!c.pinned&&(h=a.setPin(n,!0)),p>c.accessCount){let e=p-c.accessCount;for(let t=0;t<e;t++)a.incrementAccessCount(n);h=a.findById(n)??h}for(let e of l)a.delete(e.id);let[_]=a.findSimilar(m,c.type,c.projects[0]?.scopeHash);_!==void 0&&_.id!==n&&J(_.similarity)===`flag`&&a.createReviewEvent({memoryId:n,conflictingMemoryId:_.id,similarity:_.similarity,conflictContentSnapshot:i});let v=h.projects[0]?.scopeHash??`0000000000000000`;return s.logEvent({projectHash:v,eventType:`memory.updated`,memoryId:n,payload:{merged:r}}),h=a.findById(n)??h,{kept:h,dropped:r}}function je(e,t){t.resolveReviewEvents(e)}function Me(e,t){return e.map(e=>{try{return t.findById(e)===void 0?{id:e,status:`error`,error:`Memory not found: ${e}`}:(t.resolveReviewEvents(e),{id:e,status:`ok`})}catch(t){return{id:e,status:`error`,error:t instanceof Error?t.message:String(t)}}})}async function Ne(e,t){let{content:n,type:r,tags:a=[],projectScope:o,sourceHarness:s}=P.parse(e),{repo:c,embedder:l,activityLogger:u=w}=t,d=o?.hash??`0000000000000000`,f=await l.embed(n),[p]=c.findSimilar(f,r,o?.hash);if(p!==void 0){let e=J(p.similarity);if(e===`overwrite`){let e=c.overwrite(p.id,n,f);return u.logEvent({projectHash:d,eventType:`memory.updated`,memoryId:p.id}),e}if(e===`flag`){let e=c.create({id:i(),content:n,type:r,tags:a,sourceHarness:s??null,embedding:f,projectScope:o});return c.createReviewEvent({memoryId:p.id,conflictingMemoryId:e.id,similarity:p.similarity,conflictContentSnapshot:n}),u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:e.id}),u.logEvent({projectHash:d,eventType:`memory.flagged`,memoryId:p.id,payload:{conflictingMemoryId:e.id,similarity:p.similarity}}),e}}let m=c.create({id:i(),content:n,type:r,tags:a,sourceHarness:s??null,embedding:f,projectScope:o});return u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:m.id}),m}async function Pe(e,t,n){let{repo:r,embedder:i,activityLogger:a=w}=n,o=F.parse(t),s=o.content===void 0?void 0:await i.embed(o.content),c=r.update(e,o,s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e}),c}const Y=8e3;function Fe(e){return e>=Y}var X=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}findSimilar(e,n,r){let i=Buffer.from(e.buffer),a;return a=r===void 0?this.#e.db.prepare(`SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity
302
+ `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function ke(e={}){return new Oe(e)}function Ae(e){let t=new Map;function n(e){t.has(e)||t.set(e,e);let r=t.get(e);if(r!==e){let i=n(r);return t.set(e,i),i}return e}function r(e,r){let i=n(e),a=n(r);i!==a&&t.set(a,i)}for(let{memoryId:t,conflictingMemoryId:n}of e)r(t,n);let i=new Map;for(let e of t.keys()){let t=n(e),r=i.get(t)??[];r.push(e),i.set(t,r)}return Array.from(i.entries()).map(([e,t])=>({clusterId:e,memoryIds:t}))}function Y(e,t,n=w){let r=t.findById(e)?.projects[0]?.scopeHash??`0000000000000000`;return t.delete(e),n.logEvent({projectHash:r,eventType:`memory.deleted`,memoryId:e}),Promise.resolve()}async function je(e,t,n=w){let r=[];for(let i of e)try{await Y(i,t,n),r.push({id:i,status:`ok`})}catch(e){r.push({id:i,status:`error`,error:e instanceof Error?e.message:String(e)})}return r}function X(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function Me(e,t){let{keepId:n,dropIds:r,mergedContent:i}=e,{repo:a,embedder:o,activityLogger:s=w}=t,c=a.findById(n);if(c===void 0)throw Error(`Memory not found: ${n}`);let l=r.map(e=>{let t=a.findById(e);if(t===void 0)throw Error(`Memory not found: ${e}`);return t});for(let e of l)if(e.type!==c.type)throw Error(`Type mismatch: keep memory has type "${c.type}" but drop memory ${e.id} has type "${e.type}"`);let u=[c,...l],d=[...new Set(u.flatMap(e=>e.tags))],f=u.some(e=>e.pinned),p=u.reduce((e,t)=>e+t.accessCount,0),m=await o.embed(i),h=a.overwrite(n,i,m),g=new Set(c.tags);if((d.length!==c.tags.length||d.some(e=>!g.has(e)))&&(h=a.update(n,{tags:d})),f&&!c.pinned&&(h=a.setPin(n,!0)),p>c.accessCount){let e=p-c.accessCount;for(let t=0;t<e;t++)a.incrementAccessCount(n);h=a.findById(n)??h}for(let e of l)a.delete(e.id);let[_]=a.findSimilar(m,c.type,c.projects[0]?.scopeHash);_!==void 0&&_.id!==n&&X(_.similarity)===`flag`&&a.createReviewEvent({memoryId:n,conflictingMemoryId:_.id,similarity:_.similarity,conflictContentSnapshot:i});let v=h.projects[0]?.scopeHash??`0000000000000000`;return s.logEvent({projectHash:v,eventType:`memory.updated`,memoryId:n,payload:{merged:r}}),h=a.findById(n)??h,{kept:h,dropped:r}}function Ne(e,t){t.resolveReviewEvents(e)}function Pe(e,t){return e.map(e=>{try{return t.findById(e)===void 0?{id:e,status:`error`,error:`Memory not found: ${e}`}:(t.resolveReviewEvents(e),{id:e,status:`ok`})}catch(t){return{id:e,status:`error`,error:t instanceof Error?t.message:String(t)}}})}async function Fe(e,t,n){let{repo:r,embedder:i,activityLogger:a=w}=n,o=r.getVersion(e,t);if(o===void 0)throw Error(`Version ${t} not found for memory: ${e}`);let s=await i.embed(o.content),c=r.update(e,{content:o.content},s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e,payload:{revertedToVersion:t}}),c}async function Ie(e,t){let{content:n,type:r,tags:a=[],projectScope:o,sourceHarness:s}=P.parse(e),{repo:c,embedder:l,activityLogger:u=w}=t,d=o?.hash??`0000000000000000`,f=await l.embed(n),[p]=c.findSimilar(f,r,o?.hash);if(p!==void 0){let e=X(p.similarity);if(e===`overwrite`){let e=c.overwrite(p.id,n,f);return u.logEvent({projectHash:d,eventType:`memory.updated`,memoryId:p.id}),e}if(e===`flag`){let e=c.create({id:i(),content:n,type:r,tags:a,sourceHarness:s??null,embedding:f,...o!==void 0&&{projectScope:o}});return c.createReviewEvent({memoryId:p.id,conflictingMemoryId:e.id,similarity:p.similarity,conflictContentSnapshot:n}),u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:e.id}),u.logEvent({projectHash:d,eventType:`memory.flagged`,memoryId:p.id,payload:{conflictingMemoryId:e.id,similarity:p.similarity}}),e}}let m=c.create({id:i(),content:n,type:r,tags:a,sourceHarness:s??null,embedding:f,...o!==void 0&&{projectScope:o}});return u.logEvent({projectHash:d,eventType:`memory.created`,memoryId:m.id}),m}async function Le(e,t,n){let{repo:r,embedder:i,activityLogger:a=w}=n,o=F.parse(t),s=o.content===void 0?void 0:await i.embed(o.content),c=r.update(e,o,s),l=c.projects[0]?.scopeHash??`0000000000000000`;return a.logEvent({projectHash:l,eventType:`memory.updated`,memoryId:e}),c}const Z=8e3;function Re(e){return e>=Z}var ze=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}findSimilar(e,n,r){let i=Buffer.from(e.buffer),a;return a=r===void 0?this.#e.db.prepare(`SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity
279
303
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
280
304
  JOIN memory_projects mp ON mp.memory_id = m.id
281
305
  JOIN projects p ON p.id = mp.project_id
@@ -286,7 +310,7 @@ PRAGMA foreign_keys = ON;
286
310
  JOIN projects p ON p.id = mp.project_id
287
311
  WHERE m.type = ? AND p.scope_hash = ?
288
312
  ORDER BY similarity DESC LIMIT 1`).get(i,n,r),a===void 0?[]:[{id:a.id,similarity:a.similarity}]}create(e){let{id:t,content:n,type:r,tags:i,sourceHarness:a,embedding:o,projectScope:s}=e,c=new Date().toISOString(),l=Buffer.from(o.buffer);this.#e.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
289
- VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(t,n,r,JSON.stringify(i),a,c,c),this.#e.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(l,t);let u=s??{hash:`0000000000000000`,name:`global`},d=this.#t.upsertByHash(u.hash,u.name);return this.#t.addAssociation(t,d.id),z(L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(t)),this.#t.getProjectsForMemories([t]).get(t)??[])}overwrite(e,t,n){let r=new Date().toISOString(),i=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(t,r,e);let a=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e)?.rowid;a!==void 0&&this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(i,a);let o=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#r([e]);return z(o,s.get(e)??[],c.get(e)??[])}findById(e){let t=this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e);if(t===void 0)return;let n=this.#t.getProjectsForMemories([e]),r=this.#r([e]);return z(t,n.get(e)??[],r.get(e)??[])}findManyById(e){if(e.length===0)return[];let t=e.map(()=>`?`).join(`, `),n=this.#e.db.prepare(`SELECT * FROM memories WHERE id IN (${t})`).all(...e);if(n.length===0)return[];let r=n.map(e=>e.id),i=this.#t.getProjectsForMemories(r),a=this.#r(r);return n.map(e=>z(e,i.get(e.id)??[],a.get(e.id)??[]))}update(e,t,n){let{content:r,tags:i,type:a}=F.parse(t),o=this.#e.db.prepare(`SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`).get(e);if(o===void 0)throw Error(`Memory not found: ${e}`);let s=new Date().toISOString(),c=[`updated_at = ?`],l=[s];if(r!==void 0&&(c.push(`content = ?`),l.push(r)),i!==void 0&&(c.push(`tags = ?`),l.push(JSON.stringify(i))),a!==void 0&&(c.push(`type = ?`),l.push(a)),l.push(e),this.#e.db.prepare(`UPDATE memories SET ${c.join(`, `)} WHERE id = ?`).run(...l),n!==void 0){let e=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(e,o.rowid)}let u=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#r([e]);return z(u,d.get(e)??[],f.get(e)??[])}delete(e){let t=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e);t!==void 0&&this.#e.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(t.rowid),this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(e),this.#e.db.prepare(`DELETE FROM memories WHERE id = ?`).run(e)}list(e){let n=[],r=[];e?.type!==void 0&&(n.push(`m.type = ?`),r.push(e.type)),e?.pinned===!0&&n.push(`m.pinned = 1`),e?.needsReview===!0&&n.push(`EXISTS (SELECT 1 FROM memory_review_events e WHERE e.memory_id = m.id AND e.resolved_at IS NULL)`),e?.projectId===`global`?(n.push(`EXISTS (SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id WHERE mp.memory_id = m.id AND p.scope_hash = ?)`),r.push(t)):e?.projectId!==void 0&&(n.push(`m.id IN (SELECT memory_id FROM memory_projects WHERE project_id = ?)`),r.push(e.projectId));let i=n.length>0?`WHERE ${n.join(` AND `)}`:``,a=this.#e.db.prepare(`SELECT m.* FROM memories m ${i} ORDER BY m.created_at DESC`).all(...r);if(a.length===0)return[];let o=a.map(e=>e.id),s=this.#t.getProjectsForMemories(o),c=this.#r(o);return a.map(e=>z(e,s.get(e.id)??[],c.get(e.id)??[]))}listPinnedGlobal(){return this.listPinnedForProject(t)}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
313
+ VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(t,n,r,JSON.stringify(i),a,c,c),this.#e.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(l,t);let u=s??{hash:`0000000000000000`,name:`global`},d=this.#t.upsertByHash(u.hash,u.name);return this.#t.addAssociation(t,d.id),z(L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(t)),this.#t.getProjectsForMemories([t]).get(t)??[])}overwrite(e,t,n){let r=new Date().toISOString(),i=Buffer.from(n.buffer);this.#e.db.transaction(()=>{this.#r(e),this.#e.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(t,r,e)})();let a=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e)?.rowid;a!==void 0&&this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(i,a);let o=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#i([e]);return z(o,s.get(e)??[],c.get(e)??[])}findById(e){let t=this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e);if(t===void 0)return;let n=this.#t.getProjectsForMemories([e]),r=this.#i([e]);return z(t,n.get(e)??[],r.get(e)??[])}findManyById(e){if(e.length===0)return[];let t=e.map(()=>`?`).join(`, `),n=this.#e.db.prepare(`SELECT * FROM memories WHERE id IN (${t})`).all(...e);if(n.length===0)return[];let r=n.map(e=>e.id),i=this.#t.getProjectsForMemories(r),a=this.#i(r);return n.map(e=>z(e,i.get(e.id)??[],a.get(e.id)??[]))}update(e,t,n){let{content:r,tags:i,type:a}=F.parse(t),o=this.#e.db.prepare(`SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`).get(e);if(o===void 0)throw Error(`Memory not found: ${e}`);let s=new Date().toISOString(),c=[`updated_at = ?`],l=[s];if(r!==void 0&&(c.push(`content = ?`),l.push(r)),i!==void 0&&(c.push(`tags = ?`),l.push(JSON.stringify(i))),a!==void 0&&(c.push(`type = ?`),l.push(a)),l.push(e),this.#e.db.transaction(()=>{r!==void 0&&this.#r(e),this.#e.db.prepare(`UPDATE memories SET ${c.join(`, `)} WHERE id = ?`).run(...l)})(),n!==void 0){let e=Buffer.from(n.buffer);this.#e.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(e,o.rowid)}let u=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#i([e]);return z(u,d.get(e)??[],f.get(e)??[])}delete(e){let t=this.#e.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(e);t!==void 0&&this.#e.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(t.rowid),this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(e),this.#e.db.prepare(`DELETE FROM memories WHERE id = ?`).run(e)}list(e){let n=[],r=[];e?.type!==void 0&&(n.push(`m.type = ?`),r.push(e.type)),e?.pinned===!0&&n.push(`m.pinned = 1`),e?.needsReview===!0&&n.push(`EXISTS (SELECT 1 FROM memory_review_events e WHERE e.memory_id = m.id AND e.resolved_at IS NULL)`),e?.projectId===`global`?(n.push(`EXISTS (SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id WHERE mp.memory_id = m.id AND p.scope_hash = ?)`),r.push(t)):e?.projectId!==void 0&&(n.push(`m.id IN (SELECT memory_id FROM memory_projects WHERE project_id = ?)`),r.push(e.projectId));let i=n.length>0?`WHERE ${n.join(` AND `)}`:``,a=this.#e.db.prepare(`SELECT m.* FROM memories m ${i} ORDER BY m.created_at DESC`).all(...r);if(a.length===0)return[];let o=a.map(e=>e.id),s=this.#t.getProjectsForMemories(o),c=this.#i(o);return a.map(e=>z(e,s.get(e.id)??[],c.get(e.id)??[]))}listPinnedGlobal(){return this.listPinnedForProject(t)}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
290
314
  JOIN memory_projects mp ON mp.memory_id = m.id
291
315
  JOIN projects p ON p.id = mp.project_id
292
316
  WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>z(e,[]))}listFlagged(e){let{projectHash:t,limit:n,minSimilarity:r,maxSimilarity:i}=e??{},a=[`e.resolved_at IS NULL`];r!==void 0&&a.push(`e.similarity >= ?`),i!==void 0&&a.push(`e.similarity <= ?`);let o=[r,i].filter(e=>e!==void 0),s=`EXISTS (
@@ -297,7 +321,7 @@ PRAGMA foreign_keys = ON;
297
321
  ORDER BY created_at DESC ${c}`).all(...o,...l):this.#e.db.prepare(`SELECT * FROM memories
298
322
  WHERE ${s}
299
323
  AND ${this.#n()}
300
- ORDER BY created_at DESC ${c}`).all(...o,t,...l),u.length===0)return[];let d=u.map(e=>e.id),f=this.#t.getProjectsForMemories(d),p=this.#r(d,{unresolvedOnly:!0});return u.map(e=>z(e,f.get(e.id)??[],p.get(e.id)??[]))}listReviewEdges(e){return e===void 0?this.#e.db.prepare(`SELECT memory_id, conflicting_memory_id FROM memory_review_events
324
+ ORDER BY created_at DESC ${c}`).all(...o,t,...l),u.length===0)return[];let d=u.map(e=>e.id),f=this.#t.getProjectsForMemories(d),p=this.#i(d,{unresolvedOnly:!0});return u.map(e=>z(e,f.get(e.id)??[],p.get(e.id)??[]))}listReviewEdges(e){return e===void 0?this.#e.db.prepare(`SELECT memory_id, conflicting_memory_id FROM memory_review_events
301
325
  WHERE resolved_at IS NULL AND conflicting_memory_id IS NOT NULL`).all().map(e=>({memoryId:e.memory_id,conflictingMemoryId:e.conflicting_memory_id})):this.#e.db.prepare(`SELECT e.memory_id, e.conflicting_memory_id
302
326
  FROM memory_review_events e
303
327
  JOIN memories m ON m.id = e.memory_id
@@ -325,31 +349,43 @@ PRAGMA foreign_keys = ON;
325
349
  FROM memory_review_events e ${t}
326
350
  GROUP BY band`).all(...n),i=this.#e.db.prepare(`SELECT m.type, COUNT(DISTINCT e.memory_id) AS count
327
351
  FROM memory_review_events e ${t}
328
- GROUP BY m.type`).all(...n),a=this.#e.db.prepare(`SELECT COUNT(*) AS pairs FROM memory_review_events e ${t}`).get(...n)??{pairs:0},o={high:0,mid:0,low:0};for(let e of r)(e.band===`high`||e.band===`mid`||e.band===`low`)&&(o[e.band]=e.count);let s={};for(let e of i){let t=E.safeParse(e.type);t.success&&(s[t.data]=e.count)}return{pairs:a.pairs,byBand:o,byType:s}}setPin(e,t){if(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)===void 0)throw Error(`Memory not found: ${e}`);let n=new Date().toISOString();this.#e.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(+!!t,n,e);let r=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#r([e]);return z(r,i.get(e)??[],a.get(e)??[])}incrementAccessCount(e){this.#e.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(e)}exportAll(){return this.#e.db.prepare(`SELECT m.*, e.embedding FROM memories m LEFT JOIN embeddings e ON e.rowid = m.rowid ORDER BY m.created_at DESC`).all().map(e=>({id:e.id,content:e.content,type:E.parse(e.type),tags:D.parse(JSON.parse(e.tags)),sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,createdAt:e.created_at,updatedAt:e.updated_at,embedding:e.embedding===null?null:new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4)}))}importAll(e){let t=this.#e.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
352
+ GROUP BY m.type`).all(...n),a=this.#e.db.prepare(`SELECT COUNT(*) AS pairs FROM memory_review_events e ${t}`).get(...n)??{pairs:0},o={high:0,mid:0,low:0};for(let e of r)(e.band===`high`||e.band===`mid`||e.band===`low`)&&(o[e.band]=e.count);let s={};for(let e of i){let t=E.safeParse(e.type);t.success&&(s[t.data]=e.count)}return{pairs:a.pairs,byBand:o,byType:s}}setPin(e,t){if(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)===void 0)throw Error(`Memory not found: ${e}`);let n=new Date().toISOString();this.#e.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(+!!t,n,e);let r=L.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#i([e]);return z(r,i.get(e)??[],a.get(e)??[])}incrementAccessCount(e){this.#e.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(e)}exportAll(){return this.#e.db.prepare(`SELECT m.*, e.embedding FROM memories m LEFT JOIN embeddings e ON e.rowid = m.rowid ORDER BY m.created_at DESC`).all().map(e=>({id:e.id,content:e.content,type:E.parse(e.type),tags:D.parse(JSON.parse(e.tags)),sourceHarness:e.source,accessCount:e.access_count,pinned:e.pinned!==0,createdAt:e.created_at,updatedAt:e.updated_at,embedding:e.embedding===null?null:new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4)}))}importAll(e){let t=this.#e.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
329
353
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),n=this.#e.db.prepare(`INSERT OR REPLACE INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`);this.#e.db.transaction(()=>{for(let r of e)t.run(r.id,r.content,r.type,JSON.stringify(r.tags),r.sourceHarness,r.accessCount,+!!r.pinned,r.createdAt,r.updatedAt),r.embedding!==null&&n.run(Buffer.from(r.embedding.buffer,r.embedding.byteOffset,r.embedding.byteLength),r.id)})()}#n(e=`memories`){return`EXISTS (
330
354
  SELECT 1 FROM memory_projects mp JOIN projects p ON p.id = mp.project_id
331
355
  WHERE mp.memory_id = ${e}.id AND (p.scope_hash = ? OR p.scope_hash = '${t}')
332
- )`}#r(e,t){if(e.length===0)return new Map;let n=e.map(()=>`?`).join(`, `),r=t?.unresolvedOnly===!0?`AND resolved_at IS NULL`:``,i=this.#e.db.prepare(`SELECT * FROM memory_review_events
356
+ )`}listVersions(e){return this.#e.db.prepare(`SELECT * FROM memory_versions WHERE memory_id = ? ORDER BY version DESC`).all(e).map(H)}getVersion(e,t){let n=this.#e.db.prepare(`SELECT * FROM memory_versions WHERE memory_id = ? AND version = ?`).get(e,t);return n===void 0?void 0:H(n)}#r(e){let t=this.#e.db.prepare(`SELECT m.content, COALESCE(MAX(v.version), 0) + 1 AS next_version
357
+ FROM memories m
358
+ LEFT JOIN memory_versions v ON v.memory_id = m.id
359
+ WHERE m.id = ?
360
+ GROUP BY m.id`).get(e);t!==void 0&&(this.#e.db.prepare(`INSERT INTO memory_versions (memory_id, version, content) VALUES (?, ?, ?)`).run(e,t.next_version,t.content),this.#e.db.prepare(`DELETE FROM memory_versions WHERE memory_id = ? AND version <= (
361
+ SELECT MAX(version) - 10 FROM memory_versions WHERE memory_id = ?
362
+ )`).run(e,e))}#i(e,t){if(e.length===0)return new Map;let n=e.map(()=>`?`).join(`, `),r=t?.unresolvedOnly===!0?`AND resolved_at IS NULL`:``,i=this.#e.db.prepare(`SELECT * FROM memory_review_events
333
363
  WHERE memory_id IN (${n}) ${r}
334
- ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=B(j.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function Ie(e,t){return new X(e,t)}const Le=ne(te);function Z(e){return r(`sha256`).update(e).digest(`hex`).slice(0,16)}async function Re(){try{let{stdout:e}=await Le(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Z(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Z(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function ze(){try{let{stdout:e}=await Le(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Z(t)}catch{}return Z(process.cwd())}const Be=[{name:`scope-to-projects`,description:`Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.`}];async function Ve(e){let t=await Re(),n=e.getByHash(t.hash);if(n===void 0)return null;let r=n.name,i=e.countMemories(n.id);return e.rename(n.id,t.name),{migration:`scope-to-projects`,oldName:r,newName:t.name,memoryCount:i}}var He=class{#e;constructor(e){this.#e=e}upsertByHash(t,r){if(!/^[0-9a-f]{16}$/.test(t))throw Error(`Invalid scope hash "${t}": expected 16 lowercase hex characters`);let a=new Date().toISOString(),o=t===`0000000000000000`?n:i(),s=t===`0000000000000000`?e:r;return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(o,s,t,a,a),V(R.parse(this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(t)))}rename(e,t){let n=new Date().toISOString();this.#e.db.prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`).run(t,n,e);let r=this.#e.db.prepare(`SELECT * FROM projects WHERE id = ?`).get(e);if(r===void 0)throw Error(`Project not found: ${e}`);return V(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(V)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:V(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:V(t)}addAssociation(e,t){this.#e.db.prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`).run(e,t)}removeAssociation(e,t){this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`).run(e,t)}countMemories(e){return this.#e.db.prepare(`SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`).get(e)?.count??0}getProjectsForMemories(e){if(e.length===0)return new Map;let t=e.map(()=>`?`).join(`,`),n=this.#e.db.prepare(`SELECT p.*, mp.memory_id FROM projects p
364
+ ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=B(j.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function Be(e,t){return new ze(e,t)}const Ve=ne(te);function Q(e){return r(`sha256`).update(e).digest(`hex`).slice(0,16)}async function He(){try{let{stdout:e}=await Ve(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Q(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Q(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function Ue(){try{let{stdout:e}=await Ve(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Q(t)}catch{}return Q(process.cwd())}const We=[{name:`scope-to-projects`,description:`Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.`}];async function Ge(e){let t=await He(),n=e.getByHash(t.hash);if(n===void 0)return null;let r=n.name,i=e.countMemories(n.id);return e.rename(n.id,t.name),{migration:`scope-to-projects`,oldName:r,newName:t.name,memoryCount:i}}var Ke=class{#e;constructor(e){this.#e=e}upsertByHash(t,r){if(!/^[0-9a-f]{16}$/.test(t))throw Error(`Invalid scope hash "${t}": expected 16 lowercase hex characters`);let a=new Date().toISOString(),o=t===`0000000000000000`?n:i(),s=t===`0000000000000000`?e:r;return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(o,s,t,a,a),V(R.parse(this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(t)))}rename(e,t){let n=new Date().toISOString();this.#e.db.prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`).run(t,n,e);let r=this.#e.db.prepare(`SELECT * FROM projects WHERE id = ?`).get(e);if(r===void 0)throw Error(`Project not found: ${e}`);return V(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(V)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:V(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:V(t)}addAssociation(e,t){this.#e.db.prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`).run(e,t)}removeAssociation(e,t){this.#e.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`).run(e,t)}countMemories(e){return this.#e.db.prepare(`SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`).get(e)?.count??0}getProjectsForMemories(e){if(e.length===0)return new Map;let t=e.map(()=>`?`).join(`,`),n=this.#e.db.prepare(`SELECT p.*, mp.memory_id FROM projects p
335
365
  JOIN memory_projects mp ON mp.project_id = p.id
336
- WHERE mp.memory_id IN (${t})`).all(...e),r=new Map;for(let e of n){let t=r.get(e.memory_id)??[];t.push(V(e)),r.set(e.memory_id,t)}return r}};function Ue(e){return new He(e)}const We={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function Ge(e,t,n){let r=We[e.type],i=e.accessCount/(e.accessCount+10),a=1/(1+(n-new Date(e.updatedAt).getTime())/864e5),o=+!!e.pinned;return t*.4+r*.25+i*.2+a*.1+o*.05}async function Ke(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=N.parse(e),{activityLogger:s=w}=t,c=await t.embedder.embed(n),l=Buffer.from(c.buffer),u=t.adapter.findByEmbedding(l,{type:r,projectHash:i,includePinned:o}),d=Date.now(),f=u.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:Ge(n,t,d)}});f.sort((e,t)=>t.score-e.score);let p=f.slice(0,a);for(let e of p)t.repo.incrementAccessCount(e.id);return s.logEvent({projectHash:i??`0000000000000000`,eventType:`memory.queried`,payload:{resultCount:p.length,topScores:p.slice(0,3).map(e=>e.score)}}),p}var qe=class{#e;constructor(e){this.#e=e}findByEmbedding(e,n){let{type:r,projectHash:i,includePinned:a}=n,o=[],s=[e],c=``;a||o.push(`m.pinned = 0`),r!==void 0&&(o.push(`m.type = ?`),s.push(r)),i!==void 0&&(c=`JOIN memory_projects mp ON mp.memory_id = m.id JOIN projects p ON p.id = mp.project_id`,o.push(`(p.scope_hash = ? OR p.scope_hash = ?)`),s.push(i,t));let l=o.length>0?`WHERE ${o.join(` AND `)}`:``,u=`
366
+ WHERE mp.memory_id IN (${t})`).all(...e),r=new Map;for(let e of n){let t=r.get(e.memory_id)??[];t.push(V(e)),r.set(e.memory_id,t)}return r}};function qe(e){return new Ke(e)}const Je={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function Ye(e,t,n){let r=Je[e.type],i=e.accessCount/(e.accessCount+10),a=1/(1+(n-new Date(e.updatedAt).getTime())/864e5),o=+!!e.pinned;return t*.4+r*.25+i*.2+a*.1+o*.05}async function Xe(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=N.parse(e),{activityLogger:s=w}=t,c=await t.embedder.embed(n),l=Buffer.from(c.buffer),u=t.adapter.findByEmbedding(l,{...r!==void 0&&{type:r},...i!==void 0&&{projectHash:i},...o!==void 0&&{includePinned:o}}),d=Date.now(),f=u.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:Ye(n,t,d)}});f.sort((e,t)=>t.score-e.score);let p=f.slice(0,a);for(let e of p)t.repo.incrementAccessCount(e.id);return s.logEvent({projectHash:i??`0000000000000000`,eventType:`memory.queried`,payload:{resultCount:p.length,topScores:p.slice(0,3).map(e=>e.score)}}),p}var Ze=class{#e;constructor(e){this.#e=e}findByEmbedding(e,n){let{type:r,projectHash:i,includePinned:a}=n,o=[],s=[e],c=``;a||o.push(`m.pinned = 0`),r!==void 0&&(o.push(`m.type = ?`),s.push(r)),i!==void 0&&(c=`JOIN memory_projects mp ON mp.memory_id = m.id JOIN projects p ON p.id = mp.project_id`,o.push(`(p.scope_hash = ? OR p.scope_hash = ?)`),s.push(i,t));let l=o.length>0?`WHERE ${o.join(` AND `)}`:``,u=`
337
367
  SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim
338
368
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
339
369
  ${c}
340
370
  ${l}
341
- `;return this.#e.db.prepare(u).all(...s).map(e=>({...z(e,[]),cosineSim:e.cosine_sim}))}},Je=class{#e;#t;#n;#r;constructor(e,t,n,r=w){this.#e=e,this.#t=t,this.#n=n,this.#r=r}async query(e){return Ke(e,{adapter:new qe(this.#e),repo:this.#n,embedder:this.#t,activityLogger:this.#r})}};function Q(e,t){let n=t.repo.stats(e.projectHash);return e.synthesis!==void 0&&e.synthesis.length>0?{stats:n.byType,pinnedGlobal:[],pinnedProject:[],synthesis:e.synthesis}:{stats:n.byType,pinnedGlobal:t.repo.listPinnedGlobal(),pinnedProject:t.repo.listPinnedForProject(e.projectHash)}}function Ye(){return[...T]}var Xe=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Q({projectHash:e,synthesis:t},{repo:this.#e})}},Ze=class{#e;#t;#n;#r=new Set;#i=new Map;#a=!1;#o;#s=new Map;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async init(){this.#e.clearStaleInFlight(this.#t.inFlightTimeoutMs??12e4),this.#e.expireStale();let e=this.#e.getExpiredOrDirtyScopes();for(let{scope:t}of e)this.#r.add(t);this.#a=!0,await this.#l()}shutdown(){this.#a=!1,this.#o!==void 0&&(clearTimeout(this.#o),this.#o=void 0);let e=[...this.#s.values()];return e.length===0?Promise.resolve():Promise.race([Promise.allSettled(e).then(()=>void 0),new Promise(e=>setTimeout(e,5e3))])}markDirty(e){this.#r.add(e)}#c(){if(!this.#a)return;let e=this.#t.debounceMs??45e3;this.#o=setTimeout(()=>{this.#l()},e)}async#l(){let e=[...this.#r];for(let t of e){let e=this.#t.inFlightTimeoutMs??12e4,n=this.#e.getSynthesis(t);if(n?.inFlightSince!==null&&n?.inFlightSince!==void 0){if(Date.now()-new Date(n.inFlightSince).getTime()<e)continue;this.#e.clearInFlight(t)}this.#r.delete(t);let r=this.#u(t).finally(()=>{this.#s.delete(t)});this.#s.set(t,r)}this.#c()}async#u(e){this.#e.markInFlight(e);try{let t=e===`0000000000000000`?void 0:e,n=await this.#n.run(e,t),r=this.#e.computeSourceMemoryHash(e);this.#e.saveSynthesis(e,n,r),this.#i.delete(e)}catch(t){let n=(this.#i.get(e)??0)+1;this.#i.set(e,n);let r=Math.min(n,5),i=(this.#t.debounceMs??45e3)*r;process.stderr.write(`membank synthesis: error for scope=${e} failures=${n} backoff=${i}ms: ${t instanceof Error?t.message:String(t)}\n`),setTimeout(()=>{this.#r.add(e)},i),this.#e.clearInFlight(e)}}};async function Qe(e,t){let n=e===`0000000000000000`?void 0:e;t.synthRepo.markInFlight(e);try{let[r,i]=await Promise.all([t.agentRunner.run(e,n),Promise.resolve(t.synthRepo.computeSourceMemoryHash(e))]);return t.synthRepo.saveSynthesis(e,r,i),r}catch(n){throw t.synthRepo.clearInFlight(e),n}}var $e=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=_({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[y(`query_memory`,`Search memories by semantic similarity`,{query:a.string().describe(`Search text`),limit:a.number().optional().describe(`Maximum results to return`),global:a.boolean().optional().describe(`Query global memories only when true, otherwise current project scope`)},async({query:e,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:e,limit:n,global:r,projectHash:t})}]}),{annotations:{readOnlyHint:!0}}),y(`get_memory_summary`,`Returns aggregate stats: total memories, counts by type, pinned count, review queue size`,{},async()=>({content:[{type:`text`,text:await this.#e.getMemorySummary()}]}),{annotations:{readOnlyHint:!0}})]}),r=`Synthesize the memories for ${e===`0000000000000000`?`global (across all projects)`:`project scope: ${e}`}. Use get_memory_summary first to understand the overall state, then use query_memory to retrieve relevant memories (query with broad terms like "preferences", "corrections", "decisions", "key facts"). After gathering information, produce a concise synthesis of the most important things to remember about this user. Output only the synthesis text — no preamble, no metadata.`,i=Date.now(),o=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),s=v({prompt:r,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:`You are a memory synthesizer. Your job is to read the user's stored memories and produce a concise, well-structured summary of what's most important to remember about this user — their preferences, corrections, decisions, and key facts. Pinned memories are higher fidelity and should be weighted more heavily. Exclude transient or ephemeral details. Output plain text suitable for injection into an LLM context window. Be concise — target 200-400 words.`,mcpServers:{"membank-synthesis-tools":n},allowedTools:[`mcp__membank-synthesis-tools__query_memory`,`mcp__membank-synthesis-tools__get_memory_summary`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:o}}),c=``;for await(let e of s)if(e.type===`result`)if(e.subtype===`success`)c=e.result;else{let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Synthesis agent failed: ${e.subtype}${t}`)}let l=Date.now()-i;if(process.stderr.write(`membank synthesis: scope=${e} duration=${l}ms\n`),c===``)throw Error(`Synthesis agent returned empty result`);return c}};function et(e,t){return new $e(e,t)}function $(e){return I.parse({id:e.id,scope:e.scope,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,expiresAt:e.expires_at,inFlightSince:e.in_flight_since,createdAt:e.created_at,updatedAt:e.updated_at})}var tt=class{#e;constructor(e){this.#e=e}saveSynthesis(e,t,n){let r=new Date().toISOString(),a=new Date(Date.now()+720*60*60*1e3).toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses
342
- SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
343
- in_flight_since = NULL, updated_at = ?
344
- WHERE scope = ?`).run(t,n,r,a,r,e);else{let o=i();this.#e.db.prepare(`INSERT INTO syntheses
371
+ `;return this.#e.db.prepare(u).all(...s).map(e=>({...z(e,[]),cosineSim:e.cosine_sim}))}},Qe=class{#e;#t;#n;#r;constructor(e,t,n,r=w){this.#e=e,this.#t=t,this.#n=n,this.#r=r}async query(e){return Xe(e,{adapter:new Ze(this.#e),repo:this.#n,embedder:this.#t,activityLogger:this.#r})}};function $e(e,t){let n=t.repo.stats(e.projectHash);return e.synthesis!==void 0&&e.synthesis.length>0?{stats:n.byType,pinnedGlobal:[],pinnedProject:[],synthesis:e.synthesis}:{stats:n.byType,pinnedGlobal:t.repo.listPinnedGlobal(),pinnedProject:t.repo.listPinnedForProject(e.projectHash)}}function et(){return[...T]}var tt=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return $e({projectHash:e,...t!==void 0&&{synthesis:t}},{repo:this.#e})}},nt=class{#e;#t;#n;#r=new Set;#i=new Map;#a=!1;#o;#s=new Map;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async init(){this.#e.clearStaleInFlight(this.#t.inFlightTimeoutMs??12e4),this.#e.expireStale();let e=this.#e.getExpiredOrDirtyScopes();for(let{scope:t}of e)this.#r.add(t);this.#a=!0,await this.#l()}shutdown(){this.#a=!1,this.#o!==void 0&&(clearTimeout(this.#o),this.#o=void 0);let e=[...this.#s.values()];return e.length===0?Promise.resolve():Promise.race([Promise.allSettled(e).then(()=>void 0),new Promise(e=>setTimeout(e,5e3))])}markDirty(e){this.#r.add(e)}#c(){if(!this.#a)return;let e=this.#t.debounceMs??45e3;this.#o=setTimeout(()=>{this.#l()},e)}async#l(){let e=[...this.#r];for(let t of e){let e=this.#t.inFlightTimeoutMs??12e4,n=this.#e.getSynthesis(t);if(n?.inFlightSince!==null&&n?.inFlightSince!==void 0){if(Date.now()-new Date(n.inFlightSince).getTime()<e)continue;this.#e.clearInFlight(t)}this.#r.delete(t);let r=this.#u(t).finally(()=>{this.#s.delete(t)});this.#s.set(t,r)}this.#c()}async#u(e){this.#e.markInFlight(e);try{let t=e===`0000000000000000`?void 0:e,n=await this.#n.run(e,t),r=this.#e.computeSourceMemoryHash(e);this.#e.saveSynthesis(e,n,r),this.#i.delete(e)}catch(t){let n=(this.#i.get(e)??0)+1;this.#i.set(e,n);let r=Math.min(n,5),i=(this.#t.debounceMs??45e3)*r;process.stderr.write(`membank synthesis: error for scope=${e} failures=${n} backoff=${i}ms: ${t instanceof Error?t.message:String(t)}\n`),setTimeout(()=>{this.#r.add(e)},i),this.#e.clearInFlight(e)}}};function rt(e,t,n){let r=n.getVersion(e,t);if(r===void 0)throw Error(`Version ${t} not found for scope: ${e}`);return n.saveSynthesis(e,r.content,r.sourceMemoryHash)}async function it(e,t){let n=e===`0000000000000000`?void 0:e;t.synthRepo.markInFlight(e);try{let[r,i]=await Promise.all([t.agentRunner.run(e,n),Promise.resolve(t.synthRepo.computeSourceMemoryHash(e))]);return t.synthRepo.saveSynthesis(e,r,i),r}catch(n){throw t.synthRepo.clearInFlight(e),n}}var at=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=_({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[y(`query_memory`,`Search memories by semantic similarity`,{query:a.string().describe(`Search text`),limit:a.number().optional().describe(`Maximum results to return`),global:a.boolean().optional().describe(`Query global memories only when true, otherwise current project scope`)},async({query:e,limit:n,global:r})=>({content:[{type:`text`,text:await this.#e.queryMemory({query:e,...n!==void 0&&{limit:n},...r!==void 0&&{global:r},...t!==void 0&&{projectHash:t}})}]}),{annotations:{readOnlyHint:!0}}),y(`get_memory_summary`,`Returns aggregate stats: total memories, counts by type, pinned count, review queue size`,{},async()=>({content:[{type:`text`,text:await this.#e.getMemorySummary()}]}),{annotations:{readOnlyHint:!0}})]}),r=`Synthesize the memories for ${e===`0000000000000000`?`global (across all projects)`:`project scope: ${e}`}. Use get_memory_summary first to understand the overall state, then use query_memory to retrieve relevant memories (query with broad terms like "preferences", "corrections", "decisions", "key facts"). After gathering information, produce a concise synthesis of the most important things to remember about this user. Output only the synthesis text — no preamble, no metadata.`,i=Date.now(),o=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),s=v({prompt:r,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:`You are a memory synthesizer. Your job is to read the user's stored memories and produce a concise, well-structured summary of what's most important to remember about this user — their preferences, corrections, decisions, and key facts. Pinned memories are higher fidelity and should be weighted more heavily. Exclude transient or ephemeral details. Output plain text suitable for injection into an LLM context window. Be concise — target 200-400 words.`,mcpServers:{"membank-synthesis-tools":n},allowedTools:[`mcp__membank-synthesis-tools__query_memory`,`mcp__membank-synthesis-tools__get_memory_summary`],disallowedTools:[`mcp__membank__*`],settingSources:[],permissionMode:`bypassPermissions`,env:o}}),c=``;for await(let e of s)if(e.type===`result`)if(e.subtype===`success`)c=e.result;else{let t=`errors`in e&&Array.isArray(e.errors)?`: ${e.errors.join(`; `)}`:``;throw Error(`Synthesis agent failed: ${e.subtype}${t}`)}let l=Date.now()-i;if(process.stderr.write(`membank synthesis: scope=${e} duration=${l}ms\n`),c===``)throw Error(`Synthesis agent returned empty result`);return c}};function ot(e,t){return new at(e,t)}function st(e){return I.parse({id:e.id,scope:e.scope,content:e.content,sourceMemoryHash:e.source_memory_hash,synthesizedAt:e.synthesized_at,expiresAt:e.expires_at,inFlightSince:e.in_flight_since,createdAt:e.created_at,updatedAt:e.updated_at})}function $(e){return e.content===`pending`&&e.source_memory_hash===``}var ct=class{#e;constructor(e){this.#e=e}saveSynthesis(e,t,n){let r=new Date().toISOString(),a=new Date(Date.now()+720*60*60*1e3).toISOString(),{id:o,createdAt:s}=this.#e.db.transaction(()=>{let o=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);if(o!==void 0)return $(o)||this.#t(e),this.#e.db.prepare(`UPDATE syntheses
372
+ SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
373
+ in_flight_since = NULL, updated_at = ?
374
+ WHERE scope = ?`).run(t,n,r,a,r,e),{id:o.id,createdAt:o.created_at};let s=i();return this.#e.db.prepare(`INSERT INTO syntheses
345
375
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
346
376
  in_flight_since, created_at, updated_at)
347
- VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`).run(o,e,t,n,r,a,r,r)}let o=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);if(o===void 0)throw Error(`Failed to save synthesis for scope: ${e}`);return $(o)}getSynthesis(e){let t=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);return t===void 0?void 0:$(t)}listAll(){return this.#e.db.prepare(`SELECT * FROM syntheses ORDER BY scope`).all().map($)}markInFlight(e){let t=new Date().toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = ?, updated_at = ? WHERE scope = ?`).run(t,t,e);else{let n=i(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
377
+ VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`).run(s,e,t,n,r,a,r,r),{id:s,createdAt:r}})();return I.parse({id:o,scope:e,content:t,sourceMemoryHash:n,synthesizedAt:r,expiresAt:a,inFlightSince:null,createdAt:s,updatedAt:r})}listVersions(e){return this.#e.db.prepare(`SELECT * FROM synthesis_versions WHERE scope = ? ORDER BY version DESC`).all(e).map(U)}getVersion(e,t){let n=this.#e.db.prepare(`SELECT * FROM synthesis_versions WHERE scope = ? AND version = ?`).get(e,t);return n===void 0?void 0:U(n)}#t(e){let t=this.#e.db.prepare(`SELECT s.content, s.source_memory_hash, s.synthesized_at,
378
+ COALESCE(MAX(v.version), 0) + 1 AS next_version
379
+ FROM syntheses s
380
+ LEFT JOIN synthesis_versions v ON v.scope = s.scope
381
+ WHERE s.scope = ?
382
+ GROUP BY s.scope`).get(e);t!==void 0&&(this.#e.db.prepare(`INSERT INTO synthesis_versions (scope, version, content, source_memory_hash, synthesized_at)
383
+ VALUES (?, ?, ?, ?, ?)`).run(e,t.next_version,t.content,t.source_memory_hash,t.synthesized_at),this.#e.db.prepare(`DELETE FROM synthesis_versions WHERE scope = ? AND version <= ?`).run(e,t.next_version-5))}getSynthesis(e){let t=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(e);return t===void 0?void 0:st(t)}listAll(){return this.#e.db.prepare(`SELECT * FROM syntheses ORDER BY scope`).all().map(st)}markInFlight(e){let t=new Date().toISOString();if(this.#e.db.prepare(`SELECT id FROM syntheses WHERE scope = ?`).get(e)!==void 0)this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = ?, updated_at = ? WHERE scope = ?`).run(t,t,e);else{let n=i(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
348
384
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
349
385
  in_flight_since, created_at, updated_at)
350
386
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(n,e,`pending`,``,t,r,t,t,t)}}clearInFlight(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = NULL, updated_at = ? WHERE scope = ?`).run(t,e)}clearStaleInFlight(e){let t=new Date(Date.now()-e).toISOString(),n=new Date().toISOString();this.#e.db.prepare(`UPDATE syntheses SET in_flight_since = NULL, updated_at = ? WHERE in_flight_since IS NOT NULL AND in_flight_since < ?`).run(n,t)}computeSourceMemoryHash(e){let t=this.#e.db.prepare(`SELECT m.content FROM memories m
351
387
  JOIN memory_projects mp ON mp.memory_id = m.id
352
388
  JOIN projects p ON p.id = mp.project_id
353
389
  WHERE p.scope_hash = ?
354
- ORDER BY m.id`).all(e);return r(`sha256`).update(JSON.stringify(t.map(e=>e.content))).digest(`hex`)}getExpiredOrDirtyScopes(){let e=this.getAllActiveScopes(),t=new Date().toISOString(),n=[];for(let r of e){let e=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(r);if(e===void 0||e.content===`pending`&&e.source_memory_hash===``){n.push({scope:r,reason:`missing`});continue}if(e.expires_at<=t){n.push({scope:r,reason:`expired`});continue}this.computeSourceMemoryHash(r)!==e.source_memory_hash&&n.push({scope:r,reason:`dirty`})}return n}getAllActiveScopes(){return this.#e.db.prepare(`SELECT DISTINCT scope_hash FROM projects`).all().map(e=>e.scope_hash)}expireStale(){let e=new Date().toISOString();this.#e.db.prepare(`DELETE FROM syntheses WHERE expires_at < ?`).run(e)}};function nt(e){return new tt(e)}export{b as ACTIVITY_EVENT_TYPE_VALUES,x as ActivityEventTypeSchema,U as DatabaseError,pe as DatabaseManager,ge as EmbeddingService,n as GLOBAL_PROJECT_ID,e as GLOBAL_PROJECT_NAME,t as GLOBAL_SCOPE_HASH,T as MEMORY_TYPE_VALUES,Be as MIGRATIONS,W as MODEL_NAME,H as MembankError,F as MemoryPatchSchema,L as MemoryRowSchema,M as MemorySchema,E as MemoryTypeSchema,G as ModelDownloadError,he as ModelDownloader,Y as PIN_BUDGET_THRESHOLD,R as ProjectRowSchema,O as ProjectSchema,Je as QueryEngine,N as QueryOptionsSchema,ie as RETENTION_DAYS,j as ReviewEventRowSchema,A as ReviewEventSchema,k as ReviewReasonSchema,P as SaveOptionsSchema,Xe as SessionContextBuilder,ue as SessionContextSchema,X as SqliteMemoryRepository,Ze as SynthesisEngine,I as SynthesisSchema,D as TagsJsonSchema,Oe as clusterFlagged,se as createActivityLogger,oe as createActivityRepository,De as createClaudeCodeTranscriptReader,be as createExtractionAgentRunner,we as createExtractionRunRepository,Ie as createMemoryRepository,Ue as createProjectRepository,et as createSynthesisAgentRunner,nt as createSynthesisRepository,ke as deleteManyMemories,q as deleteMemory,Q as getSessionContext,Fe as isOverBudget,le as isSynthesisEnabled,re as listEvents,Ye as listMemoryTypes,S as logEvent,Ae as mergeMemories,w as noopActivityLogger,Ke as queryMemories,Re as resolveProject,je as resolveReview,Me as resolveReviewMany,ze as resolveScope,z as rowToMemory,V as rowToProject,_e as runExtraction,Ve as runScopeToProjectsMigration,Qe as runSynthesis,Ne as saveMemory,Pe as updateMemory};
390
+ ORDER BY m.id`).all(e);return r(`sha256`).update(JSON.stringify(t.map(e=>e.content))).digest(`hex`)}getExpiredOrDirtyScopes(){let e=this.getAllActiveScopes(),t=new Date().toISOString(),n=[];for(let r of e){let e=this.#e.db.prepare(`SELECT * FROM syntheses WHERE scope = ?`).get(r);if(e===void 0||$(e)){n.push({scope:r,reason:`missing`});continue}if(e.expires_at<=t){n.push({scope:r,reason:`expired`});continue}this.computeSourceMemoryHash(r)!==e.source_memory_hash&&n.push({scope:r,reason:`dirty`})}return n}getAllActiveScopes(){return this.#e.db.prepare(`SELECT DISTINCT scope_hash FROM projects`).all().map(e=>e.scope_hash)}expireStale(){let e=new Date().toISOString();this.#e.db.prepare(`DELETE FROM syntheses WHERE expires_at < ?`).run(e)}};function lt(e){return new ct(e)}export{b as ACTIVITY_EVENT_TYPE_VALUES,x as ActivityEventTypeSchema,G as DatabaseError,he as DatabaseManager,ve as EmbeddingService,n as GLOBAL_PROJECT_ID,e as GLOBAL_PROJECT_NAME,t as GLOBAL_SCOPE_HASH,T as MEMORY_TYPE_VALUES,We as MIGRATIONS,K as MODEL_NAME,W as MembankError,F as MemoryPatchSchema,L as MemoryRowSchema,M as MemorySchema,E as MemoryTypeSchema,de as MemoryVersionRowSchema,q as ModelDownloadError,_e as ModelDownloader,Z as PIN_BUDGET_THRESHOLD,R as ProjectRowSchema,O as ProjectSchema,Qe as QueryEngine,N as QueryOptionsSchema,ie as RETENTION_DAYS,j as ReviewEventRowSchema,A as ReviewEventSchema,k as ReviewReasonSchema,P as SaveOptionsSchema,tt as SessionContextBuilder,ue as SessionContextSchema,ze as SqliteMemoryRepository,nt as SynthesisEngine,I as SynthesisSchema,fe as SynthesisVersionRowSchema,D as TagsJsonSchema,Ae as clusterFlagged,se as createActivityLogger,oe as createActivityRepository,ke as createClaudeCodeTranscriptReader,Se as createExtractionAgentRunner,Ee as createExtractionRunRepository,Be as createMemoryRepository,qe as createProjectRepository,ot as createSynthesisAgentRunner,lt as createSynthesisRepository,je as deleteManyMemories,Y as deleteMemory,$e as getSessionContext,Re as isOverBudget,le as isSynthesisEnabled,re as listEvents,et as listMemoryTypes,S as logEvent,Me as mergeMemories,w as noopActivityLogger,Xe as queryMemories,He as resolveProject,Ne as resolveReview,Pe as resolveReviewMany,Ue as resolveScope,Fe as revertMemory,rt as revertSynthesis,z as rowToMemory,V as rowToProject,ye as runExtraction,Ge as runScopeToProjectsMigration,it as runSynthesis,Ie as saveMemory,Le as updateMemory};
355
391
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@membank/core",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",