@membank/core 0.10.0 → 0.11.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/index.cjs CHANGED
@@ -1,4 +1,4 @@
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));let c=require(`node:fs`),l=require(`node:os`),u=require(`node:path`),d=require(`zod`),f=require(`better-sqlite3`);f=s(f,1);let p=require(`sqlite-vec`);p=s(p,1);let ee=require(`node:events`),m=require(`@huggingface/transformers`),h=require(`node:crypto`),te=require(`node:child_process`),ne=require(`node:util`),g=require(`@anthropic-ai/claude-agent-sdk`);function re(){let e=(0,u.join)((0,l.homedir)(),`.membank`,`config.json`);try{let t=(0,c.readFileSync)(e,`utf8`);return JSON.parse(t)}catch{return null}}function ie(){return re()?.synthesis?.enabled===!0}const _=[`correction`,`preference`,`decision`,`learning`,`fact`],v=d.z.enum(_),y=d.z.array(d.z.string()),b=d.z.object({id:d.z.string(),name:d.z.string(),scopeHash:d.z.string(),createdAt:d.z.string(),updatedAt:d.z.string()}),x=d.z.enum([`similarity_dedup`]),S=d.z.object({id:d.z.string(),memoryId:d.z.string(),conflictingMemoryId:d.z.string().nullable(),similarity:d.z.number(),conflictContentSnapshot:d.z.string(),reason:x,createdAt:d.z.string(),resolvedAt:d.z.string().nullable()}),C=d.z.object({id:d.z.string(),memory_id:d.z.string(),conflicting_memory_id:d.z.string().nullable(),similarity:d.z.number(),conflict_content_snapshot:d.z.string(),reason:x,created_at:d.z.string(),resolved_at:d.z.string().nullable()}),w=d.z.object({id:d.z.string(),content:d.z.string(),type:v,tags:d.z.array(d.z.string()),projects:d.z.array(b),sourceHarness:d.z.string().nullable(),accessCount:d.z.number().int().nonnegative(),pinned:d.z.boolean(),reviewEvents:d.z.array(S),createdAt:d.z.string(),updatedAt:d.z.string()}),T=d.z.object({query:d.z.string().min(1),type:v.optional(),projectHash:d.z.string().optional(),limit:d.z.number().int().positive().optional(),includePinned:d.z.boolean().optional()}),E=d.z.object({content:d.z.string().min(1),type:v,tags:d.z.array(d.z.string()).optional(),projectScope:d.z.object({hash:d.z.string(),name:d.z.string()}).optional(),sourceHarness:d.z.string().optional()}),D=d.z.object({content:d.z.string().min(1).optional(),tags:d.z.array(d.z.string()).optional(),type:v.optional()}),O=d.z.object({id:d.z.string(),scope:d.z.string(),content:d.z.string(),sourceMemoryHash:d.z.string(),synthesizedAt:d.z.string(),expiresAt:d.z.string(),inFlightSince:d.z.string().nullable(),createdAt:d.z.string(),updatedAt:d.z.string()}),ae=d.z.object({stats:d.z.record(v,d.z.number()),pinnedGlobal:d.z.array(w),pinnedProject:d.z.array(w),synthesis:d.z.string().optional()}),k=d.z.object({id:d.z.string(),content:d.z.string(),type:d.z.string(),tags:d.z.string(),source:d.z.string().nullable(),access_count:d.z.number(),pinned:d.z.number(),created_at:d.z.string(),updated_at:d.z.string()}),A=d.z.object({id:d.z.string(),name:d.z.string(),scope_hash:d.z.string(),created_at:d.z.string(),updated_at:d.z.string()});function j(e,t,n=[]){return{id:e.id,content:e.content,type:v.parse(e.type),tags:y.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 M(e){let t=C.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 N(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var P=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},F=class extends P{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const oe=(0,u.join)((0,l.homedir)(),`.membank`,`memory.db`),se=[[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));let c=require(`node:fs`),l=require(`node:os`),u=require(`node:path`),d=require(`zod`),f=require(`better-sqlite3`);f=s(f,1);let p=require(`sqlite-vec`);p=s(p,1);let ee=require(`node:events`),m=require(`@huggingface/transformers`),h=require(`@anthropic-ai/claude-agent-sdk`),te=require(`node:fs/promises`),g=require(`node:crypto`),_=require(`node:child_process`),ne=require(`node:util`);function re(){let e=(0,u.join)((0,l.homedir)(),`.membank`,`config.json`);try{let t=(0,c.readFileSync)(e,`utf8`);return JSON.parse(t)}catch{return null}}function ie(){return re()?.synthesis?.enabled===!0}const v=[`correction`,`preference`,`decision`,`learning`,`fact`],y=d.z.enum(v),b=d.z.array(d.z.string()),x=d.z.object({id:d.z.string(),name:d.z.string(),scopeHash:d.z.string(),createdAt:d.z.string(),updatedAt:d.z.string()}),S=d.z.enum([`similarity_dedup`]),C=d.z.object({id:d.z.string(),memoryId:d.z.string(),conflictingMemoryId:d.z.string().nullable(),similarity:d.z.number(),conflictContentSnapshot:d.z.string(),reason:S,createdAt:d.z.string(),resolvedAt:d.z.string().nullable()}),w=d.z.object({id:d.z.string(),memory_id:d.z.string(),conflicting_memory_id:d.z.string().nullable(),similarity:d.z.number(),conflict_content_snapshot:d.z.string(),reason:S,created_at:d.z.string(),resolved_at:d.z.string().nullable()}),T=d.z.object({id:d.z.string(),content:d.z.string(),type:y,tags:d.z.array(d.z.string()),projects:d.z.array(x),sourceHarness:d.z.string().nullable(),accessCount:d.z.number().int().nonnegative(),pinned:d.z.boolean(),reviewEvents:d.z.array(C),createdAt:d.z.string(),updatedAt:d.z.string()}),E=d.z.object({query:d.z.string().min(1),type:y.optional(),projectHash:d.z.string().optional(),limit:d.z.number().int().positive().optional(),includePinned:d.z.boolean().optional()}),D=d.z.object({content:d.z.string().min(1),type:y,tags:d.z.array(d.z.string()).optional(),projectScope:d.z.object({hash:d.z.string(),name:d.z.string()}).optional(),sourceHarness:d.z.string().optional()}),O=d.z.object({content:d.z.string().min(1).optional(),tags:d.z.array(d.z.string()).optional(),type:y.optional()}),k=d.z.object({id:d.z.string(),scope:d.z.string(),content:d.z.string(),sourceMemoryHash:d.z.string(),synthesizedAt:d.z.string(),expiresAt:d.z.string(),inFlightSince:d.z.string().nullable(),createdAt:d.z.string(),updatedAt:d.z.string()}),ae=d.z.object({stats:d.z.record(y,d.z.number()),pinnedGlobal:d.z.array(T),pinnedProject:d.z.array(T),synthesis:d.z.string().optional()}),A=d.z.object({id:d.z.string(),content:d.z.string(),type:d.z.string(),tags:d.z.string(),source:d.z.string().nullable(),access_count:d.z.number(),pinned:d.z.number(),created_at:d.z.string(),updated_at:d.z.string()}),j=d.z.object({id:d.z.string(),name:d.z.string(),scope_hash:d.z.string(),created_at:d.z.string(),updated_at:d.z.string()});function M(e,t,n=[]){return{id:e.id,content:e.content,type:y.parse(e.type),tags:b.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 N(e){let t=w.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 P(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var F=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},I=class extends F{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const oe=(0,u.join)((0,l.homedir)(),`.membank`,`memory.db`),se=[[1,`
2
2
  CREATE TABLE IF NOT EXISTS memories (
3
3
  id TEXT PRIMARY KEY,
4
4
  content TEXT NOT NULL,
@@ -143,12 +143,39 @@ ALTER TABLE projects_new RENAME TO projects;
143
143
  COMMIT;
144
144
 
145
145
  PRAGMA foreign_keys = ON;
146
- `]];var ce=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??oe;(0,c.mkdirSync)((0,u.dirname)(n),{recursive:!0});let r=new f.default(n);return e.#n(r,p.load)}static openInMemory(){return e.#t(p.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new f.default(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new F(`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(`
146
+ `],[6,`
147
+ CREATE TABLE IF NOT EXISTS extraction_runs (
148
+ session_id TEXT PRIMARY KEY,
149
+ started_at TEXT NOT NULL,
150
+ completed_at TEXT,
151
+ status TEXT NOT NULL CHECK(status IN ('in_flight', 'completed', 'failed')),
152
+ error TEXT
153
+ );
154
+
155
+ CREATE INDEX IF NOT EXISTS idx_extraction_runs_status
156
+ ON extraction_runs(status) WHERE status = 'in_flight';
157
+ `]];var ce=class e{#e;constructor(e){this.#e=e}static open(t){let n=t??oe;(0,c.mkdirSync)((0,u.dirname)(n),{recursive:!0});let r=new f.default(n);return e.#n(r,p.load)}static openInMemory(){return e.#t(p.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new f.default(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new I(`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(`
147
158
  CREATE TABLE IF NOT EXISTS meta (
148
159
  key TEXT PRIMARY KEY,
149
160
  value TEXT NOT NULL
150
161
  );
151
- `);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 se)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 I=`Xenova/bge-small-en-v1.5`;var L=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function le(){return(0,u.join)((0,l.homedir)(),`.membank`,`models`)}function R(e){if(!(0,c.existsSync)(e))return!1;try{return(0,c.readdirSync)(e).length>0}catch{return!1}}var z=class extends ee.EventEmitter{modelPath;constructor(e){super(),this.modelPath=e??le()}isAlreadyCached(){return R(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(R(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await(0,m.pipeline)(`feature-extraction`,I,{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 L(`Failed to download model`,{cause:e})}return{skipped:!1}}},B=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??(0,u.join)((0,l.homedir)(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await(0,m.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)}};function V(e,t){return t.delete(e),Promise.resolve()}function H(e,t){t.resolveReviewEvents(e)}function U(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function W(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=E.parse(e),{repo:s,embedder:c}=t,l=await c.embed(n),[u]=s.findSimilar(l,r,a?.hash);if(u!==void 0){let e=U(u.similarity);if(e===`overwrite`)return s.overwrite(u.id,n,l);if(e===`flag`){let e=s.create({id:(0,h.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a});return s.createReviewEvent({memoryId:u.id,conflictingMemoryId:e.id,similarity:u.similarity,conflictContentSnapshot:n}),e}}return s.create({id:(0,h.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a})}async function ue(e,t,n){let{repo:r,embedder:i}=n,a=D.parse(t),o=a.content===void 0?void 0:await i.embed(a.content);return r.update(e,a,o)}const G=8e3;function de(e){return e>=G}var K=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
162
+ `);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 se)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 L=`Xenova/bge-small-en-v1.5`;var R=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function le(){return(0,u.join)((0,l.homedir)(),`.membank`,`models`)}function z(e){if(!(0,c.existsSync)(e))return!1;try{return(0,c.readdirSync)(e).length>0}catch{return!1}}var B=class extends ee.EventEmitter{modelPath;constructor(e){super(),this.modelPath=e??le()}isAlreadyCached(){return z(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(z(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await(0,m.pipeline)(`feature-extraction`,L,{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 R(`Failed to download model`,{cause:e})}return{skipped:!1}}},V=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??(0,u.join)((0,l.homedir)(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await(0,m.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 H(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 U=[`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(`
163
+ `);var W=class{#e;constructor(e){this.#e=e}async run(e){let t=(0,h.createSdkMcpServer)({name:`membank-extraction-tools`,version:`1.0.0`,tools:[(0,h.tool)(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:d.z.string().describe(`Search text`),limit:d.z.number().optional().describe(`Maximum results to return`),global:d.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,h.tool)(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:d.z.string().describe(`Memory content — concise, decontextualised`),type:d.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:d.z.array(d.z.string()).optional().describe(`Optional tags`),global:d.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,h.tool)(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:d.z.string().describe(`Memory id`),content:d.z.string().optional(),type:d.z.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:d.z.array(d.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(`
164
+ `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),a=(0,h.query)({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:U,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 ue(e){return new W(e)}function de(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 fe(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var pe=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(de(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)
165
+ VALUES (?, ?, NULL, 'in_flight', NULL)
166
+ ON CONFLICT(session_id) DO UPDATE SET
167
+ started_at = excluded.started_at,
168
+ completed_at = NULL,
169
+ status = 'in_flight',
170
+ error = NULL`).run(e,i),!0}markCompleted(e,t){this.#e.db.prepare(`UPDATE extraction_runs
171
+ SET status = 'completed', completed_at = ?, error = NULL
172
+ WHERE session_id = ?`).run(t.toISOString(),e)}markFailed(e,t,n){this.#e.db.prepare(`UPDATE extraction_runs
173
+ SET status = 'failed', completed_at = ?, error = ?
174
+ WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:fe(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function me(e){return new pe(e)}function he(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(`
175
+ `)}var ge=class{#e;#t;constructor(e={}){this.#e=e.maxTurns??80,this.#t=e.maxChars??6e4}async read(e){let t=(await(0,te.readFile)(e,`utf8`)).split(`
176
+ `).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=he(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
177
+
178
+ `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function _e(e={}){return new ge(e)}function ve(e,t){return t.delete(e),Promise.resolve()}function ye(e,t){t.resolveReviewEvents(e)}function be(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function xe(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=D.parse(e),{repo:s,embedder:c}=t,l=await c.embed(n),[u]=s.findSimilar(l,r,a?.hash);if(u!==void 0){let e=be(u.similarity);if(e===`overwrite`)return s.overwrite(u.id,n,l);if(e===`flag`){let e=s.create({id:(0,g.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a});return s.createReviewEvent({memoryId:u.id,conflictingMemoryId:e.id,similarity:u.similarity,conflictContentSnapshot:n}),e}}return s.create({id:(0,g.randomUUID)(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a})}async function Se(e,t,n){let{repo:r,embedder:i}=n,a=O.parse(t),o=a.content===void 0?void 0:await i.embed(a.content);return r.update(e,a,o)}const G=8e3;function Ce(e){return e>=G}var K=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
152
179
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
153
180
  WHERE m.type = ?
154
181
  AND m.id NOT IN (SELECT memory_id FROM memory_projects)
@@ -158,35 +185,35 @@ PRAGMA foreign_keys = ON;
158
185
  JOIN projects p ON p.id = mp.project_id
159
186
  WHERE m.type = ? AND p.scope_hash = ?
160
187
  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);if(this.#e.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
161
- 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),s!==void 0){let e=this.#t.upsertByHash(s.hash,s.name);this.#t.addAssociation(t,e.id)}return j(k.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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#n([e]);return j(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.#n([e]);return j(t,n.get(e)??[],r.get(e)??[])}update(e,t,n){let{content:r,tags:i,type:a}=D.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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#n([e]);return j(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(`m.id NOT IN (SELECT memory_id FROM memory_projects)`):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.#n(a);return i.map(e=>j(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.#e.db.prepare(`SELECT * FROM memories
188
+ 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),s!==void 0){let e=this.#t.upsertByHash(s.hash,s.name);this.#t.addAssociation(t,e.id)}return M(A.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=A.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#n([e]);return M(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.#n([e]);return M(t,n.get(e)??[],r.get(e)??[])}update(e,t,n){let{content:r,tags:i,type:a}=O.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=A.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#n([e]);return M(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(`m.id NOT IN (SELECT memory_id FROM memory_projects)`):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.#n(a);return i.map(e=>M(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.#e.db.prepare(`SELECT * FROM memories
162
189
  WHERE id NOT IN (SELECT memory_id FROM memory_projects)
163
- AND pinned = 1`).all().map(e=>j(e,[]))}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
190
+ AND pinned = 1`).all().map(e=>M(e,[]))}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
164
191
  JOIN memory_projects mp ON mp.memory_id = m.id
165
192
  JOIN projects p ON p.id = mp.project_id
166
- WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>j(e,[]))}listFlagged(){let e=this.#e.db.prepare(`SELECT * FROM memories
193
+ WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>M(e,[]))}listFlagged(){let e=this.#e.db.prepare(`SELECT * FROM memories
167
194
  WHERE EXISTS (
168
195
  SELECT 1 FROM memory_review_events e
169
196
  WHERE e.memory_id = memories.id AND e.resolved_at IS NULL
170
197
  )
171
- ORDER BY created_at DESC`).all();if(e.length===0)return[];let t=e.map(e=>e.id),n=this.#t.getProjectsForMemories(t),r=this.#n(t,{unresolvedOnly:!0});return e.map(e=>j(e,n.get(e.id)??[],r.get(e.id)??[]))}listReviewEvents(e,t){let n=t?.unresolvedOnly===!0?`WHERE memory_id = ? AND resolved_at IS NULL`:`WHERE memory_id = ?`;return this.#e.db.prepare(`SELECT * FROM memory_review_events ${n} ORDER BY created_at DESC`).all(e).map(e=>M(C.parse(e)))}createReviewEvent(e){let t=new Date().toISOString();this.#e.db.prepare(`INSERT INTO memory_review_events
198
+ ORDER BY created_at DESC`).all();if(e.length===0)return[];let t=e.map(e=>e.id),n=this.#t.getProjectsForMemories(t),r=this.#n(t,{unresolvedOnly:!0});return e.map(e=>M(e,n.get(e.id)??[],r.get(e.id)??[]))}listReviewEvents(e,t){let n=t?.unresolvedOnly===!0?`WHERE memory_id = ? AND resolved_at IS NULL`:`WHERE memory_id = ?`;return this.#e.db.prepare(`SELECT * FROM memory_review_events ${n} ORDER BY created_at DESC`).all(e).map(e=>N(w.parse(e)))}createReviewEvent(e){let t=new Date().toISOString();this.#e.db.prepare(`INSERT INTO memory_review_events
172
199
  (id, memory_id, conflicting_memory_id, similarity, conflict_content_snapshot, reason, created_at)
173
- VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run((0,h.randomUUID)(),e.memoryId,e.conflictingMemoryId,e.similarity,e.conflictContentSnapshot,t)}resolveReviewEvents(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(t,e)}getPinnedCharCount(){return(this.#e.db.prepare(`SELECT COALESCE(SUM(LENGTH(content)), 0) as total FROM memories WHERE pinned = 1`).get()??{total:0}).total}stats(){let e=Object.fromEntries(_.map(e=>[e,0])),t=this.#e.db.prepare(`SELECT type, COUNT(*) as count FROM memories GROUP BY type`).all();for(let n of t){let t=v.safeParse(n.type);t.success&&(e[t.data]=n.count)}let n=this.#e.db.prepare(`SELECT COUNT(*) as total, SUM(pinned) as pinned FROM memories`).get()??{total:0,pinned:0},r=this.#e.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get()??{needsReview:0};return{byType:e,total:n.total,pinned:n.pinned??0,needsReview:r.needsReview,pinBudgetChars:this.getPinnedCharCount()}}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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#n([e]);return j(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:v.parse(e.type),tags:y.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)
200
+ VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run((0,g.randomUUID)(),e.memoryId,e.conflictingMemoryId,e.similarity,e.conflictContentSnapshot,t)}resolveReviewEvents(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(t,e)}getPinnedCharCount(){return(this.#e.db.prepare(`SELECT COALESCE(SUM(LENGTH(content)), 0) as total FROM memories WHERE pinned = 1`).get()??{total:0}).total}stats(){let e=Object.fromEntries(v.map(e=>[e,0])),t=this.#e.db.prepare(`SELECT type, COUNT(*) as count FROM memories GROUP BY type`).all();for(let n of t){let t=y.safeParse(n.type);t.success&&(e[t.data]=n.count)}let n=this.#e.db.prepare(`SELECT COUNT(*) as total, SUM(pinned) as pinned FROM memories`).get()??{total:0,pinned:0},r=this.#e.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get()??{needsReview:0};return{byType:e,total:n.total,pinned:n.pinned??0,needsReview:r.needsReview,pinBudgetChars:this.getPinnedCharCount()}}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=A.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#n([e]);return M(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:y.parse(e.type),tags:b.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)
174
201
  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,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
175
202
  WHERE memory_id IN (${n}) ${r}
176
- ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=M(C.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function fe(e,t){return new K(e,t)}const q=(0,ne.promisify)(te.execFile);function J(e){return(0,h.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}async function Y(){try{let{stdout:e}=await q(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=J(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=J(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function pe(){try{let{stdout:e}=await q(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return J(t)}catch{}return J(process.cwd())}const me=[{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 he(e){let t=await Y(),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 ge=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=(0,h.randomUUID)();return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,t,e,n,n),N(A.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 N(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(N)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:N(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:N(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
203
+ ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=N(w.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function we(e,t){return new K(e,t)}const q=(0,ne.promisify)(_.execFile);function J(e){return(0,g.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}async function Y(){try{let{stdout:e}=await q(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=J(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=J(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function Te(){try{let{stdout:e}=await q(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return J(t)}catch{}return J(process.cwd())}const Ee=[{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 De(e){let t=await Y(),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 Oe=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=(0,g.randomUUID)();return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,t,e,n,n),P(j.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 P(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(P)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:P(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:P(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
177
204
  JOIN memory_projects mp ON mp.project_id = p.id
178
- 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(N(e)),r.set(e.memory_id,t)}return r}};function _e(e){return new ge(e)}const ve={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function ye(e,t,n){let r=ve[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 X(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=T.parse(e),s=await t.embedder.embed(n),c=Buffer.from(s.buffer),l=t.adapter.findByEmbedding(c,{type:r,projectHash:i,includePinned:o}),u=Date.now(),d=l.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:ye(n,t,u)}});d.sort((e,t)=>t.score-e.score);let f=d.slice(0,a);for(let e of f)t.repo.incrementAccessCount(e.id);return f}var be=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=`LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id`,a.push(`p.scope_hash = ?`),o.push(r));let c=a.length>0?`WHERE ${a.join(` AND `)}`:``,l=`
205
+ 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(P(e)),r.set(e.memory_id,t)}return r}};function ke(e){return new Oe(e)}const Ae={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function X(e,t,n){let r=Ae[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 Z(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=E.parse(e),s=await t.embedder.embed(n),c=Buffer.from(s.buffer),l=t.adapter.findByEmbedding(c,{type:r,projectHash:i,includePinned:o}),u=Date.now(),d=l.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:X(n,t,u)}});d.sort((e,t)=>t.score-e.score);let f=d.slice(0,a);for(let e of f)t.repo.incrementAccessCount(e.id);return f}var je=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=`LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id`,a.push(`p.scope_hash = ?`),o.push(r));let c=a.length>0?`WHERE ${a.join(` AND `)}`:``,l=`
179
206
  SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim
180
207
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
181
208
  ${s}
182
209
  ${c}
183
- `;return this.#e.db.prepare(l).all(...o).map(e=>({...j(e,[]),cosineSim:e.cosine_sim}))}},xe=class{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async query(e){return X(e,{adapter:new be(this.#e),repo:this.#n,embedder:this.#t})}};function Z(e,t){let n=t.repo.stats();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 Se(){return[..._]}var Ce=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Z({projectHash:e,synthesis:t},{repo:this.#e})}},we=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===`global`?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 Q(e,t){let n=e===`global`?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 Te=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=(0,g.createSdkMcpServer)({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[(0,g.tool)(`query_memory`,`Search memories by semantic similarity`,{query:d.z.string().describe(`Search text`),limit:d.z.number().optional().describe(`Maximum results to return`),global:d.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,g.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===`global`?`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,g.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:[`query_memory`,`get_memory_summary`],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 Ee(e,t){return new Te(e,t)}function $(e){return O.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 De=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
210
+ `;return this.#e.db.prepare(l).all(...o).map(e=>({...M(e,[]),cosineSim:e.cosine_sim}))}},Me=class{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async query(e){return Z(e,{adapter:new je(this.#e),repo:this.#n,embedder:this.#t})}};function Q(e,t){let n=t.repo.stats();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 Ne(){return[...v]}var Pe=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Q({projectHash:e,synthesis:t},{repo:this.#e})}},Fe=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===`global`?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 Ie(e,t){let n=e===`global`?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 Le=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=(0,h.createSdkMcpServer)({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[(0,h.tool)(`query_memory`,`Search memories by semantic similarity`,{query:d.z.string().describe(`Search text`),limit:d.z.number().optional().describe(`Maximum results to return`),global:d.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,h.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===`global`?`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,h.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 Re(e,t){return new Le(e,t)}function $(e){return k.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 ze=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
184
211
  SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
185
212
  in_flight_since = NULL, updated_at = ?
186
- WHERE scope = ?`).run(t,n,r,i,r,e);else{let a=(0,h.randomUUID)();this.#e.db.prepare(`INSERT INTO syntheses
213
+ WHERE scope = ?`).run(t,n,r,i,r,e);else{let a=(0,g.randomUUID)();this.#e.db.prepare(`INSERT INTO syntheses
187
214
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
188
215
  in_flight_since, created_at, updated_at)
189
- 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,h.randomUUID)(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
216
+ 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,g.randomUUID)(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
190
217
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
191
218
  in_flight_since, created_at, updated_at)
192
219
  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;return t=e===`global`?this.#e.db.prepare(`SELECT content FROM memories
@@ -195,4 +222,4 @@ PRAGMA foreign_keys = ON;
195
222
  JOIN memory_projects mp ON mp.memory_id = m.id
196
223
  JOIN projects p ON p.id = mp.project_id
197
224
  WHERE p.scope_hash = ?
198
- ORDER BY m.id`).all(e),(0,h.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[`global`,...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 Oe(e){return new De(e)}exports.DatabaseError=F,exports.DatabaseManager=ce,exports.EmbeddingService=B,exports.MEMORY_TYPE_VALUES=_,exports.MIGRATIONS=me,exports.MODEL_NAME=I,exports.MembankError=P,exports.MemoryPatchSchema=D,exports.MemoryRowSchema=k,exports.MemorySchema=w,exports.MemoryTypeSchema=v,exports.ModelDownloadError=L,exports.ModelDownloader=z,exports.PIN_BUDGET_THRESHOLD=G,exports.ProjectRowSchema=A,exports.ProjectSchema=b,exports.QueryEngine=xe,exports.QueryOptionsSchema=T,exports.ReviewEventRowSchema=C,exports.ReviewEventSchema=S,exports.ReviewReasonSchema=x,exports.SaveOptionsSchema=E,exports.SessionContextBuilder=Ce,exports.SessionContextSchema=ae,exports.SqliteMemoryRepository=K,exports.SynthesisEngine=we,exports.SynthesisSchema=O,exports.TagsJsonSchema=y,exports.createMemoryRepository=fe,exports.createProjectRepository=_e,exports.createSynthesisAgentRunner=Ee,exports.createSynthesisRepository=Oe,exports.deleteMemory=V,exports.getSessionContext=Z,exports.isOverBudget=de,exports.isSynthesisEnabled=ie,exports.listMemoryTypes=Se,exports.queryMemories=X,exports.resolveProject=Y,exports.resolveReview=H,exports.resolveScope=pe,exports.rowToMemory=j,exports.rowToProject=N,exports.runScopeToProjectsMigration=he,exports.runSynthesis=Q,exports.saveMemory=W,exports.updateMemory=ue;
225
+ ORDER BY m.id`).all(e),(0,g.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[`global`,...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 Be(e){return new ze(e)}exports.DatabaseError=I,exports.DatabaseManager=ce,exports.EmbeddingService=V,exports.MEMORY_TYPE_VALUES=v,exports.MIGRATIONS=Ee,exports.MODEL_NAME=L,exports.MembankError=F,exports.MemoryPatchSchema=O,exports.MemoryRowSchema=A,exports.MemorySchema=T,exports.MemoryTypeSchema=y,exports.ModelDownloadError=R,exports.ModelDownloader=B,exports.PIN_BUDGET_THRESHOLD=G,exports.ProjectRowSchema=j,exports.ProjectSchema=x,exports.QueryEngine=Me,exports.QueryOptionsSchema=E,exports.ReviewEventRowSchema=w,exports.ReviewEventSchema=C,exports.ReviewReasonSchema=S,exports.SaveOptionsSchema=D,exports.SessionContextBuilder=Pe,exports.SessionContextSchema=ae,exports.SqliteMemoryRepository=K,exports.SynthesisEngine=Fe,exports.SynthesisSchema=k,exports.TagsJsonSchema=b,exports.createClaudeCodeTranscriptReader=_e,exports.createExtractionAgentRunner=ue,exports.createExtractionRunRepository=me,exports.createMemoryRepository=we,exports.createProjectRepository=ke,exports.createSynthesisAgentRunner=Re,exports.createSynthesisRepository=Be,exports.deleteMemory=ve,exports.getSessionContext=Q,exports.isOverBudget=Ce,exports.isSynthesisEnabled=ie,exports.listMemoryTypes=Ne,exports.queryMemories=Z,exports.resolveProject=Y,exports.resolveReview=ye,exports.resolveScope=Te,exports.rowToMemory=M,exports.rowToProject=P,exports.runExtraction=H,exports.runScopeToProjectsMigration=De,exports.runSynthesis=Ie,exports.saveMemory=xe,exports.updateMemory=Se;
package/dist/index.d.cts CHANGED
@@ -385,6 +385,96 @@ declare class EmbeddingService implements Embedder {
385
385
  embed(text: string): Promise<Float32Array>;
386
386
  }
387
387
  //#endregion
388
+ //#region src/extraction/ports.d.ts
389
+ interface ExtractionConfig {
390
+ /** Window after a run starts during which a duplicate run for the same session_id is skipped. */
391
+ inFlightTimeoutMs?: number;
392
+ /** Window after a successful run during which a repeated run for the same session_id is skipped. */
393
+ recentCompletionMs?: number;
394
+ }
395
+ interface ExtractionRunRecord {
396
+ sessionId: string;
397
+ startedAt: string;
398
+ completedAt: string | null;
399
+ status: "in_flight" | "completed" | "failed";
400
+ error: string | null;
401
+ }
402
+ interface ExtractionRunRepository {
403
+ /** Atomic claim: returns true if the caller should proceed, false if already in flight or recently completed. */
404
+ tryClaim(sessionId: string, now: Date, config: ExtractionConfig): boolean;
405
+ markCompleted(sessionId: string, now: Date): void;
406
+ markFailed(sessionId: string, now: Date, error: string): void;
407
+ get(sessionId: string): ExtractionRunRecord | undefined;
408
+ }
409
+ interface TranscriptReader {
410
+ /** Returns the recent transcript content (plain text) for the agent to inspect. */
411
+ read(transcriptPath: string): Promise<string>;
412
+ }
413
+ interface ExtractionAgentRunner {
414
+ /** Runs the extraction agent over the supplied transcript text and project hash. */
415
+ run(args: {
416
+ transcript: string;
417
+ projectHash: string;
418
+ sessionId: string;
419
+ }): Promise<void>;
420
+ }
421
+ interface ExtractionTools {
422
+ queryMemory: (args: {
423
+ query: string;
424
+ limit?: number;
425
+ global?: boolean;
426
+ projectHash?: string;
427
+ }) => Promise<string>;
428
+ saveMemory: (args: {
429
+ content: string;
430
+ type: string;
431
+ tags?: string[];
432
+ global?: boolean;
433
+ }) => Promise<string>;
434
+ updateMemory: (args: {
435
+ id: string;
436
+ content?: string;
437
+ type?: string;
438
+ tags?: string[];
439
+ }) => Promise<string>;
440
+ }
441
+ //#endregion
442
+ //#region src/extraction/application/run-extraction.d.ts
443
+ interface RunExtractionInput {
444
+ sessionId: string;
445
+ transcriptPath: string;
446
+ projectHash: string;
447
+ }
448
+ type RunExtractionResult = {
449
+ status: "completed";
450
+ } | {
451
+ status: "skipped";
452
+ reason: "in_flight" | "recently_completed";
453
+ } | {
454
+ status: "failed";
455
+ error: string;
456
+ };
457
+ declare function runExtraction(input: RunExtractionInput, deps: {
458
+ repo: ExtractionRunRepository;
459
+ transcripts: TranscriptReader;
460
+ agent: ExtractionAgentRunner;
461
+ config: ExtractionConfig;
462
+ now?: () => Date;
463
+ }): Promise<RunExtractionResult>;
464
+ //#endregion
465
+ //#region src/extraction/infrastructure/claude-agent-runner.d.ts
466
+ declare function createExtractionAgentRunner(tools: ExtractionTools): ExtractionAgentRunner;
467
+ //#endregion
468
+ //#region src/extraction/infrastructure/sqlite-extraction-run-repository.d.ts
469
+ declare function createExtractionRunRepository(db: DatabaseManager): ExtractionRunRepository;
470
+ //#endregion
471
+ //#region src/extraction/infrastructure/transcript-reader.d.ts
472
+ interface TranscriptReaderOptions {
473
+ maxTurns?: number;
474
+ maxChars?: number;
475
+ }
476
+ declare function createClaudeCodeTranscriptReader(opts?: TranscriptReaderOptions): TranscriptReader;
477
+ //#endregion
388
478
  //#region src/memory/application/delete-memory.d.ts
389
479
  declare function deleteMemory(id: string, repo: MemoryRepository): Promise<void>;
390
480
  //#endregion
@@ -585,5 +675,5 @@ declare function createSynthesisAgentRunner(tools: SynthesisTools, config: Synth
585
675
  //#region src/synthesis/infrastructure/sqlite-synthesis-repository.d.ts
586
676
  declare function createSynthesisRepository(db: DatabaseManager): SynthesisRepository;
587
677
  //#endregion
588
- export { type AgentRunner, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, ReviewReason, ReviewReasonSchema, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, TagsJsonSchema, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listMemoryTypes, queryMemories, resolveProject, resolveReview, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
678
+ export { type AgentRunner, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, 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, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listMemoryTypes, queryMemories, resolveProject, resolveReview, resolveScope, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
589
679
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -385,6 +385,96 @@ declare class EmbeddingService implements Embedder {
385
385
  embed(text: string): Promise<Float32Array>;
386
386
  }
387
387
  //#endregion
388
+ //#region src/extraction/ports.d.ts
389
+ interface ExtractionConfig {
390
+ /** Window after a run starts during which a duplicate run for the same session_id is skipped. */
391
+ inFlightTimeoutMs?: number;
392
+ /** Window after a successful run during which a repeated run for the same session_id is skipped. */
393
+ recentCompletionMs?: number;
394
+ }
395
+ interface ExtractionRunRecord {
396
+ sessionId: string;
397
+ startedAt: string;
398
+ completedAt: string | null;
399
+ status: "in_flight" | "completed" | "failed";
400
+ error: string | null;
401
+ }
402
+ interface ExtractionRunRepository {
403
+ /** Atomic claim: returns true if the caller should proceed, false if already in flight or recently completed. */
404
+ tryClaim(sessionId: string, now: Date, config: ExtractionConfig): boolean;
405
+ markCompleted(sessionId: string, now: Date): void;
406
+ markFailed(sessionId: string, now: Date, error: string): void;
407
+ get(sessionId: string): ExtractionRunRecord | undefined;
408
+ }
409
+ interface TranscriptReader {
410
+ /** Returns the recent transcript content (plain text) for the agent to inspect. */
411
+ read(transcriptPath: string): Promise<string>;
412
+ }
413
+ interface ExtractionAgentRunner {
414
+ /** Runs the extraction agent over the supplied transcript text and project hash. */
415
+ run(args: {
416
+ transcript: string;
417
+ projectHash: string;
418
+ sessionId: string;
419
+ }): Promise<void>;
420
+ }
421
+ interface ExtractionTools {
422
+ queryMemory: (args: {
423
+ query: string;
424
+ limit?: number;
425
+ global?: boolean;
426
+ projectHash?: string;
427
+ }) => Promise<string>;
428
+ saveMemory: (args: {
429
+ content: string;
430
+ type: string;
431
+ tags?: string[];
432
+ global?: boolean;
433
+ }) => Promise<string>;
434
+ updateMemory: (args: {
435
+ id: string;
436
+ content?: string;
437
+ type?: string;
438
+ tags?: string[];
439
+ }) => Promise<string>;
440
+ }
441
+ //#endregion
442
+ //#region src/extraction/application/run-extraction.d.ts
443
+ interface RunExtractionInput {
444
+ sessionId: string;
445
+ transcriptPath: string;
446
+ projectHash: string;
447
+ }
448
+ type RunExtractionResult = {
449
+ status: "completed";
450
+ } | {
451
+ status: "skipped";
452
+ reason: "in_flight" | "recently_completed";
453
+ } | {
454
+ status: "failed";
455
+ error: string;
456
+ };
457
+ declare function runExtraction(input: RunExtractionInput, deps: {
458
+ repo: ExtractionRunRepository;
459
+ transcripts: TranscriptReader;
460
+ agent: ExtractionAgentRunner;
461
+ config: ExtractionConfig;
462
+ now?: () => Date;
463
+ }): Promise<RunExtractionResult>;
464
+ //#endregion
465
+ //#region src/extraction/infrastructure/claude-agent-runner.d.ts
466
+ declare function createExtractionAgentRunner(tools: ExtractionTools): ExtractionAgentRunner;
467
+ //#endregion
468
+ //#region src/extraction/infrastructure/sqlite-extraction-run-repository.d.ts
469
+ declare function createExtractionRunRepository(db: DatabaseManager): ExtractionRunRepository;
470
+ //#endregion
471
+ //#region src/extraction/infrastructure/transcript-reader.d.ts
472
+ interface TranscriptReaderOptions {
473
+ maxTurns?: number;
474
+ maxChars?: number;
475
+ }
476
+ declare function createClaudeCodeTranscriptReader(opts?: TranscriptReaderOptions): TranscriptReader;
477
+ //#endregion
388
478
  //#region src/memory/application/delete-memory.d.ts
389
479
  declare function deleteMemory(id: string, repo: MemoryRepository): Promise<void>;
390
480
  //#endregion
@@ -585,5 +675,5 @@ declare function createSynthesisAgentRunner(tools: SynthesisTools, config: Synth
585
675
  //#region src/synthesis/infrastructure/sqlite-synthesis-repository.d.ts
586
676
  declare function createSynthesisRepository(db: DatabaseManager): SynthesisRepository;
587
677
  //#endregion
588
- export { type AgentRunner, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, ReviewReason, ReviewReasonSchema, type SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, type ScoredMemory, SessionContext, SessionContextBuilder, SessionContextSchema, type SimilarMemoryResult, SqliteMemoryRepository, type StatsResult, Synthesis, type SynthesisConfig, SynthesisEngine, type SynthesisRepository, SynthesisSchema, type SynthesisTools, TagsJsonSchema, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listMemoryTypes, queryMemories, resolveProject, resolveReview, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
678
+ export { type AgentRunner, type CreateMemoryOpts, type CreateReviewEventOpts, DatabaseError, DatabaseManager, type DownloadProgress, type DownloadResult, type Embedder, EmbeddingService, type ExtractionAgentRunner, type ExtractionConfig, type ExtractionRunRecord, type ExtractionRunRepository, type ExtractionTools, MEMORY_TYPE_VALUES, MIGRATIONS, MODEL_NAME, MembankError, type Memory, type MemoryExportRecord, type MemoryPatch, MemoryPatchSchema, type MemoryRepository, type MemoryRow, MemoryRowSchema, MemorySchema, type MemoryType, MemoryTypeSchema, MigrationMeta, ModelDownloadError, ModelDownloader, PIN_BUDGET_THRESHOLD, type ProgressCallback, Project, type ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, type Querier, type QueryAdapter, QueryEngine, QueryOptions, QueryOptionsSchema, type ReviewEvent, type ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, 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, createClaudeCodeTranscriptReader, createExtractionAgentRunner, createExtractionRunRepository, createMemoryRepository, createProjectRepository, createSynthesisAgentRunner, createSynthesisRepository, deleteMemory, getSessionContext, isOverBudget, isSynthesisEnabled, listMemoryTypes, queryMemories, resolveProject, resolveReview, resolveScope, rowToMemory, rowToProject, runExtraction, runScopeToProjectsMigration, runSynthesis, saveMemory, updateMemory };
589
679
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{existsSync as e,mkdirSync as t,readFileSync as n,readdirSync as r}from"node:fs";import{homedir as i}from"node:os";import{dirname as a,join as o}from"node:path";import{z as s}from"zod";import c from"better-sqlite3";import*as l from"sqlite-vec";import{EventEmitter as u}from"node:events";import{pipeline as d}from"@huggingface/transformers";import{createHash as f,randomUUID as p}from"node:crypto";import{execFile as ee}from"node:child_process";import{promisify as te}from"node:util";import{createSdkMcpServer as m,query as ne,tool as h}from"@anthropic-ai/claude-agent-sdk";function re(){let e=o(i(),`.membank`,`config.json`);try{let t=n(e,`utf8`);return JSON.parse(t)}catch{return null}}function ie(){return re()?.synthesis?.enabled===!0}const g=[`correction`,`preference`,`decision`,`learning`,`fact`],_=s.enum(g),v=s.array(s.string()),y=s.object({id:s.string(),name:s.string(),scopeHash:s.string(),createdAt:s.string(),updatedAt:s.string()}),b=s.enum([`similarity_dedup`]),x=s.object({id:s.string(),memoryId:s.string(),conflictingMemoryId:s.string().nullable(),similarity:s.number(),conflictContentSnapshot:s.string(),reason:b,createdAt:s.string(),resolvedAt:s.string().nullable()}),S=s.object({id:s.string(),memory_id:s.string(),conflicting_memory_id:s.string().nullable(),similarity:s.number(),conflict_content_snapshot:s.string(),reason:b,created_at:s.string(),resolved_at:s.string().nullable()}),C=s.object({id:s.string(),content:s.string(),type:_,tags:s.array(s.string()),projects:s.array(y),sourceHarness:s.string().nullable(),accessCount:s.number().int().nonnegative(),pinned:s.boolean(),reviewEvents:s.array(x),createdAt:s.string(),updatedAt:s.string()}),w=s.object({query:s.string().min(1),type:_.optional(),projectHash:s.string().optional(),limit:s.number().int().positive().optional(),includePinned:s.boolean().optional()}),T=s.object({content:s.string().min(1),type:_,tags:s.array(s.string()).optional(),projectScope:s.object({hash:s.string(),name:s.string()}).optional(),sourceHarness:s.string().optional()}),E=s.object({content:s.string().min(1).optional(),tags:s.array(s.string()).optional(),type:_.optional()}),D=s.object({id:s.string(),scope:s.string(),content:s.string(),sourceMemoryHash:s.string(),synthesizedAt:s.string(),expiresAt:s.string(),inFlightSince:s.string().nullable(),createdAt:s.string(),updatedAt:s.string()}),ae=s.object({stats:s.record(_,s.number()),pinnedGlobal:s.array(C),pinnedProject:s.array(C),synthesis:s.string().optional()}),O=s.object({id:s.string(),content:s.string(),type:s.string(),tags:s.string(),source:s.string().nullable(),access_count:s.number(),pinned:s.number(),created_at:s.string(),updated_at:s.string()}),k=s.object({id:s.string(),name:s.string(),scope_hash:s.string(),created_at:s.string(),updated_at:s.string()});function A(e,t,n=[]){return{id:e.id,content:e.content,type:_.parse(e.type),tags:v.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 j(e){let t=S.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 M(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var N=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},P=class extends N{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const oe=o(i(),`.membank`,`memory.db`),F=[[1,`
1
+ import{existsSync as e,mkdirSync as t,readFileSync as n,readdirSync as r}from"node:fs";import{homedir as i}from"node:os";import{dirname as a,join as o}from"node:path";import{z as s}from"zod";import c from"better-sqlite3";import*as l from"sqlite-vec";import{EventEmitter as u}from"node:events";import{pipeline as d}from"@huggingface/transformers";import{createSdkMcpServer as f,query as p,tool as m}from"@anthropic-ai/claude-agent-sdk";import{readFile as ee}from"node:fs/promises";import{createHash as h,randomUUID as g}from"node:crypto";import{execFile as te}from"node:child_process";import{promisify as ne}from"node:util";function re(){let e=o(i(),`.membank`,`config.json`);try{let t=n(e,`utf8`);return JSON.parse(t)}catch{return null}}function ie(){return re()?.synthesis?.enabled===!0}const _=[`correction`,`preference`,`decision`,`learning`,`fact`],v=s.enum(_),y=s.array(s.string()),b=s.object({id:s.string(),name:s.string(),scopeHash:s.string(),createdAt:s.string(),updatedAt:s.string()}),x=s.enum([`similarity_dedup`]),S=s.object({id:s.string(),memoryId:s.string(),conflictingMemoryId:s.string().nullable(),similarity:s.number(),conflictContentSnapshot:s.string(),reason:x,createdAt:s.string(),resolvedAt:s.string().nullable()}),C=s.object({id:s.string(),memory_id:s.string(),conflicting_memory_id:s.string().nullable(),similarity:s.number(),conflict_content_snapshot:s.string(),reason:x,created_at:s.string(),resolved_at:s.string().nullable()}),w=s.object({id:s.string(),content:s.string(),type:v,tags:s.array(s.string()),projects:s.array(b),sourceHarness:s.string().nullable(),accessCount:s.number().int().nonnegative(),pinned:s.boolean(),reviewEvents:s.array(S),createdAt:s.string(),updatedAt:s.string()}),T=s.object({query:s.string().min(1),type:v.optional(),projectHash:s.string().optional(),limit:s.number().int().positive().optional(),includePinned:s.boolean().optional()}),E=s.object({content:s.string().min(1),type:v,tags:s.array(s.string()).optional(),projectScope:s.object({hash:s.string(),name:s.string()}).optional(),sourceHarness:s.string().optional()}),D=s.object({content:s.string().min(1).optional(),tags:s.array(s.string()).optional(),type:v.optional()}),O=s.object({id:s.string(),scope:s.string(),content:s.string(),sourceMemoryHash:s.string(),synthesizedAt:s.string(),expiresAt:s.string(),inFlightSince:s.string().nullable(),createdAt:s.string(),updatedAt:s.string()}),ae=s.object({stats:s.record(v,s.number()),pinnedGlobal:s.array(w),pinnedProject:s.array(w),synthesis:s.string().optional()}),k=s.object({id:s.string(),content:s.string(),type:s.string(),tags:s.string(),source:s.string().nullable(),access_count:s.number(),pinned:s.number(),created_at:s.string(),updated_at:s.string()}),A=s.object({id:s.string(),name:s.string(),scope_hash:s.string(),created_at:s.string(),updated_at:s.string()});function j(e,t,n=[]){return{id:e.id,content:e.content,type:v.parse(e.type),tags:y.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 M(e){let t=C.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 N(e){return{id:e.id,name:e.name,scopeHash:e.scope_hash,createdAt:e.created_at,updatedAt:e.updated_at}}var P=class extends Error{constructor(e,t){super(e,t),this.name=`MembankError`}},F=class extends P{constructor(e,t){super(e,t),this.name=`DatabaseError`}};const oe=o(i(),`.membank`,`memory.db`),se=[[1,`
2
2
  CREATE TABLE IF NOT EXISTS memories (
3
3
  id TEXT PRIMARY KEY,
4
4
  content TEXT NOT NULL,
@@ -143,12 +143,39 @@ ALTER TABLE projects_new RENAME TO projects;
143
143
  COMMIT;
144
144
 
145
145
  PRAGMA foreign_keys = ON;
146
- `]];var se=class e{#e;constructor(e){this.#e=e}static open(n){let r=n??oe;t(a(r),{recursive:!0});let i=new c(r);return e.#n(i,l.load)}static openInMemory(){return e.#t(l.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new c(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new P(`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(`
146
+ `],[6,`
147
+ CREATE TABLE IF NOT EXISTS extraction_runs (
148
+ session_id TEXT PRIMARY KEY,
149
+ started_at TEXT NOT NULL,
150
+ completed_at TEXT,
151
+ status TEXT NOT NULL CHECK(status IN ('in_flight', 'completed', 'failed')),
152
+ error TEXT
153
+ );
154
+
155
+ CREATE INDEX IF NOT EXISTS idx_extraction_runs_status
156
+ ON extraction_runs(status) WHERE status = 'in_flight';
157
+ `]];var ce=class e{#e;constructor(e){this.#e=e}static open(n){let r=n??oe;t(a(r),{recursive:!0});let i=new c(r);return e.#n(i,l.load)}static openInMemory(){return e.#t(l.load)}static _openInMemoryWithLoader(t){return e.#t(t)}static#t(t){let n=new c(`:memory:`);return e.#n(n,t)}static#n(t,n){try{n(t)}catch(e){throw new F(`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(`
147
158
  CREATE TABLE IF NOT EXISTS meta (
148
159
  key TEXT PRIMARY KEY,
149
160
  value TEXT NOT NULL
150
161
  );
151
- `);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 F)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 I=`Xenova/bge-small-en-v1.5`;var L=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function ce(){return o(i(),`.membank`,`models`)}function R(t){if(!e(t))return!1;try{return r(t).length>0}catch{return!1}}var z=class extends u{modelPath;constructor(e){super(),this.modelPath=e??ce()}isAlreadyCached(){return R(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(R(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await d(`feature-extraction`,I,{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 L(`Failed to download model`,{cause:e})}return{skipped:!1}}},B=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??o(i(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await d(`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)}};function V(e,t){return t.delete(e),Promise.resolve()}function H(e,t){t.resolveReviewEvents(e)}function U(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function W(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=T.parse(e),{repo:s,embedder:c}=t,l=await c.embed(n),[u]=s.findSimilar(l,r,a?.hash);if(u!==void 0){let e=U(u.similarity);if(e===`overwrite`)return s.overwrite(u.id,n,l);if(e===`flag`){let e=s.create({id:p(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a});return s.createReviewEvent({memoryId:u.id,conflictingMemoryId:e.id,similarity:u.similarity,conflictContentSnapshot:n}),e}}return s.create({id:p(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a})}async function G(e,t,n){let{repo:r,embedder:i}=n,a=E.parse(t),o=a.content===void 0?void 0:await i.embed(a.content);return r.update(e,a,o)}const K=8e3;function le(e){return e>=K}var q=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
162
+ `);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 se)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 I=`Xenova/bge-small-en-v1.5`;var L=class extends Error{constructor(e,t){super(e,t),this.name=`ModelDownloadError`}};function le(){return o(i(),`.membank`,`models`)}function R(t){if(!e(t))return!1;try{return r(t).length>0}catch{return!1}}var z=class extends u{modelPath;constructor(e){super(),this.modelPath=e??le()}isAlreadyCached(){return R(this.modelPath)}get cachePath(){return this.modelPath}async download(){if(R(this.modelPath))return{skipped:!0};let e=Date.now(),t=0,n=e;try{await d(`feature-extraction`,I,{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 L(`Failed to download model`,{cause:e})}return{skipped:!1}}},B=class{modelCachePath;onProgress;pipelineInstance=null;constructor(e,t){this.modelCachePath=e??o(i(),`.membank`,`models`),this.onProgress=t}async getPipeline(){return this.pipelineInstance===null&&(this.pipelineInstance=await d(`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 V(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 H=[`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(`
163
+ `);var U=class{#e;constructor(e){this.#e=e}async run(e){let t=f({name:`membank-extraction-tools`,version:`1.0.0`,tools:[m(`query_memory`,`Search memories by semantic similarity to check for existing entries before saving.`,{query:s.string().describe(`Search text`),limit:s.number().optional().describe(`Maximum results to return`),global:s.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}}),m(`save_memory`,`Persist a new memory. The system handles dedup automatically.`,{content:s.string().describe(`Memory content — concise, decontextualised`),type:s.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).describe(`Memory type`),tags:s.array(s.string()).optional().describe(`Optional tags`),global:s.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})}]})),m(`update_memory`,`Refine an existing memory by id rather than creating a near-duplicate.`,{id:s.string().describe(`Memory id`),content:s.string().optional(),type:s.enum([`correction`,`preference`,`decision`,`learning`,`fact`]).optional(),tags:s.array(s.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(`
164
+ `),r=Object.fromEntries(Object.entries(process.env).filter(e=>e[1]!==void 0)),i=Date.now(),a=p({prompt:n,options:{model:`claude-haiku-4-5-20251001`,systemPrompt:H,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 c=Date.now()-i;process.stderr.write(`membank extraction: session=${e.sessionId} duration=${c}ms\n`)}};function W(e){return new U(e)}function ue(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 de(e){return{sessionId:e.session_id,startedAt:e.started_at,completedAt:e.completed_at,status:e.status,error:e.error}}var fe=class{#e;constructor(e){this.#e=e}tryClaim(e,t,n){let r=this.#t(e);if(ue(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)
165
+ VALUES (?, ?, NULL, 'in_flight', NULL)
166
+ ON CONFLICT(session_id) DO UPDATE SET
167
+ started_at = excluded.started_at,
168
+ completed_at = NULL,
169
+ status = 'in_flight',
170
+ error = NULL`).run(e,i),!0}markCompleted(e,t){this.#e.db.prepare(`UPDATE extraction_runs
171
+ SET status = 'completed', completed_at = ?, error = NULL
172
+ WHERE session_id = ?`).run(t.toISOString(),e)}markFailed(e,t,n){this.#e.db.prepare(`UPDATE extraction_runs
173
+ SET status = 'failed', completed_at = ?, error = ?
174
+ WHERE session_id = ?`).run(t.toISOString(),n,e)}get(e){let t=this.#t(e);return t===void 0?void 0:de(t)}#t(e){return this.#e.db.prepare(`SELECT * FROM extraction_runs WHERE session_id = ?`).get(e)}};function pe(e){return new fe(e)}function me(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(`
175
+ `)}var he=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(`
176
+ `).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=me(t.message?.content).trim();i.length!==0&&n.push(`${r}: ${i}`)}let r=n.slice(-this.#e).join(`
177
+
178
+ `);return r.length<=this.#t?r:r.slice(r.length-this.#t)}};function ge(e={}){return new he(e)}function _e(e,t){return t.delete(e),Promise.resolve()}function ve(e,t){t.resolveReviewEvents(e)}function G(e){return e>.92?`overwrite`:e>=.75?`flag`:`none`}async function ye(e,t){let{content:n,type:r,tags:i=[],projectScope:a,sourceHarness:o}=E.parse(e),{repo:s,embedder:c}=t,l=await c.embed(n),[u]=s.findSimilar(l,r,a?.hash);if(u!==void 0){let e=G(u.similarity);if(e===`overwrite`)return s.overwrite(u.id,n,l);if(e===`flag`){let e=s.create({id:g(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a});return s.createReviewEvent({memoryId:u.id,conflictingMemoryId:e.id,similarity:u.similarity,conflictContentSnapshot:n}),e}}return s.create({id:g(),content:n,type:r,tags:i,sourceHarness:o??null,embedding:l,projectScope:a})}async function be(e,t,n){let{repo:r,embedder:i}=n,a=D.parse(t),o=a.content===void 0?void 0:await i.embed(a.content);return r.update(e,a,o)}const K=8e3;function xe(e){return e>=K}var q=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
152
179
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
153
180
  WHERE m.type = ?
154
181
  AND m.id NOT IN (SELECT memory_id FROM memory_projects)
@@ -158,35 +185,35 @@ PRAGMA foreign_keys = ON;
158
185
  JOIN projects p ON p.id = mp.project_id
159
186
  WHERE m.type = ? AND p.scope_hash = ?
160
187
  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);if(this.#e.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
161
- 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),s!==void 0){let e=this.#t.upsertByHash(s.hash,s.name);this.#t.addAssociation(t,e.id)}return A(O.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=O.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#n([e]);return A(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.#n([e]);return A(t,n.get(e)??[],r.get(e)??[])}update(e,t,n){let{content:r,tags:i,type:a}=E.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=O.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#n([e]);return A(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(`m.id NOT IN (SELECT memory_id FROM memory_projects)`):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.#n(a);return i.map(e=>A(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.#e.db.prepare(`SELECT * FROM memories
188
+ 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),s!==void 0){let e=this.#t.upsertByHash(s.hash,s.name);this.#t.addAssociation(t,e.id)}return j(k.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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),s=this.#t.getProjectsForMemories([e]),c=this.#n([e]);return j(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.#n([e]);return j(t,n.get(e)??[],r.get(e)??[])}update(e,t,n){let{content:r,tags:i,type:a}=D.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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),d=this.#t.getProjectsForMemories([e]),f=this.#n([e]);return j(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(`m.id NOT IN (SELECT memory_id FROM memory_projects)`):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.#n(a);return i.map(e=>j(e,o.get(e.id)??[],s.get(e.id)??[]))}listPinnedGlobal(){return this.#e.db.prepare(`SELECT * FROM memories
162
189
  WHERE id NOT IN (SELECT memory_id FROM memory_projects)
163
- AND pinned = 1`).all().map(e=>A(e,[]))}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
190
+ AND pinned = 1`).all().map(e=>j(e,[]))}listPinnedForProject(e){return this.#e.db.prepare(`SELECT m.* FROM memories m
164
191
  JOIN memory_projects mp ON mp.memory_id = m.id
165
192
  JOIN projects p ON p.id = mp.project_id
166
- WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>A(e,[]))}listFlagged(){let e=this.#e.db.prepare(`SELECT * FROM memories
193
+ WHERE p.scope_hash = ? AND m.pinned = 1`).all(e).map(e=>j(e,[]))}listFlagged(){let e=this.#e.db.prepare(`SELECT * FROM memories
167
194
  WHERE EXISTS (
168
195
  SELECT 1 FROM memory_review_events e
169
196
  WHERE e.memory_id = memories.id AND e.resolved_at IS NULL
170
197
  )
171
- ORDER BY created_at DESC`).all();if(e.length===0)return[];let t=e.map(e=>e.id),n=this.#t.getProjectsForMemories(t),r=this.#n(t,{unresolvedOnly:!0});return e.map(e=>A(e,n.get(e.id)??[],r.get(e.id)??[]))}listReviewEvents(e,t){let n=t?.unresolvedOnly===!0?`WHERE memory_id = ? AND resolved_at IS NULL`:`WHERE memory_id = ?`;return this.#e.db.prepare(`SELECT * FROM memory_review_events ${n} ORDER BY created_at DESC`).all(e).map(e=>j(S.parse(e)))}createReviewEvent(e){let t=new Date().toISOString();this.#e.db.prepare(`INSERT INTO memory_review_events
198
+ ORDER BY created_at DESC`).all();if(e.length===0)return[];let t=e.map(e=>e.id),n=this.#t.getProjectsForMemories(t),r=this.#n(t,{unresolvedOnly:!0});return e.map(e=>j(e,n.get(e.id)??[],r.get(e.id)??[]))}listReviewEvents(e,t){let n=t?.unresolvedOnly===!0?`WHERE memory_id = ? AND resolved_at IS NULL`:`WHERE memory_id = ?`;return this.#e.db.prepare(`SELECT * FROM memory_review_events ${n} ORDER BY created_at DESC`).all(e).map(e=>M(C.parse(e)))}createReviewEvent(e){let t=new Date().toISOString();this.#e.db.prepare(`INSERT INTO memory_review_events
172
199
  (id, memory_id, conflicting_memory_id, similarity, conflict_content_snapshot, reason, created_at)
173
- VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run(p(),e.memoryId,e.conflictingMemoryId,e.similarity,e.conflictContentSnapshot,t)}resolveReviewEvents(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(t,e)}getPinnedCharCount(){return(this.#e.db.prepare(`SELECT COALESCE(SUM(LENGTH(content)), 0) as total FROM memories WHERE pinned = 1`).get()??{total:0}).total}stats(){let e=Object.fromEntries(g.map(e=>[e,0])),t=this.#e.db.prepare(`SELECT type, COUNT(*) as count FROM memories GROUP BY type`).all();for(let n of t){let t=_.safeParse(n.type);t.success&&(e[t.data]=n.count)}let n=this.#e.db.prepare(`SELECT COUNT(*) as total, SUM(pinned) as pinned FROM memories`).get()??{total:0,pinned:0},r=this.#e.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get()??{needsReview:0};return{byType:e,total:n.total,pinned:n.pinned??0,needsReview:r.needsReview,pinBudgetChars:this.getPinnedCharCount()}}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=O.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#n([e]);return A(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:_.parse(e.type),tags:v.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)
200
+ VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run(g(),e.memoryId,e.conflictingMemoryId,e.similarity,e.conflictContentSnapshot,t)}resolveReviewEvents(e){let t=new Date().toISOString();this.#e.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(t,e)}getPinnedCharCount(){return(this.#e.db.prepare(`SELECT COALESCE(SUM(LENGTH(content)), 0) as total FROM memories WHERE pinned = 1`).get()??{total:0}).total}stats(){let e=Object.fromEntries(_.map(e=>[e,0])),t=this.#e.db.prepare(`SELECT type, COUNT(*) as count FROM memories GROUP BY type`).all();for(let n of t){let t=v.safeParse(n.type);t.success&&(e[t.data]=n.count)}let n=this.#e.db.prepare(`SELECT COUNT(*) as total, SUM(pinned) as pinned FROM memories`).get()??{total:0,pinned:0},r=this.#e.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get()??{needsReview:0};return{byType:e,total:n.total,pinned:n.pinned??0,needsReview:r.needsReview,pinBudgetChars:this.getPinnedCharCount()}}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=k.parse(this.#e.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(e)),i=this.#t.getProjectsForMemories([e]),a=this.#n([e]);return j(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:v.parse(e.type),tags:y.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)
174
201
  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,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
175
202
  WHERE memory_id IN (${n}) ${r}
176
- ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=j(S.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function ue(e,t){return new q(e,t)}const J=te(ee);function Y(e){return f(`sha256`).update(e).digest(`hex`).slice(0,16)}async function X(){try{let{stdout:e}=await J(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Y(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Y(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function de(){try{let{stdout:e}=await J(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Y(t)}catch{}return Y(process.cwd())}const fe=[{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 pe(e){let t=await X(),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 me=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=p();return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,t,e,n,n),M(k.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 M(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(M)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:M(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:M(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
203
+ ORDER BY created_at DESC`).all(...e),a=new Map;for(let e of i){let t=M(C.parse(e)),n=a.get(t.memoryId)??[];n.push(t),a.set(t.memoryId,n)}return a}};function Se(e,t){return new q(e,t)}const J=ne(te);function Y(e){return h(`sha256`).update(e).digest(`hex`).slice(0,16)}async function X(){try{let{stdout:e}=await J(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t){let e=Y(t);return{hash:e,name:t.split(`/`).pop()?.replace(/\.git$/,``)??e.slice(0,8)}}}catch{}let e=process.cwd(),t=Y(e);return{hash:t,name:e.split(/[/\\]/).filter(Boolean).pop()??t.slice(0,8)}}async function Ce(){try{let{stdout:e}=await J(`git`,[`remote`,`get-url`,`origin`]),t=e.trim();if(t)return Y(t)}catch{}return Y(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 Te(e){let t=await X(),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 Ee=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=g();return this.#e.db.prepare(`INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`).run(r,t,e,n,n),N(A.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 N(r)}list(){return this.#e.db.prepare(`SELECT * FROM projects ORDER BY name ASC`).all().map(N)}getByHash(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE scope_hash = ?`).get(e);return t===void 0?void 0:N(t)}getByName(e){let t=this.#e.db.prepare(`SELECT * FROM projects WHERE name = ? LIMIT 1`).get(e);return t===void 0?void 0:N(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
177
204
  JOIN memory_projects mp ON mp.project_id = p.id
178
- 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(M(e)),r.set(e.memory_id,t)}return r}};function he(e){return new me(e)}const ge={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function _e(e,t,n){let r=ge[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 Z(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=w.parse(e),s=await t.embedder.embed(n),c=Buffer.from(s.buffer),l=t.adapter.findByEmbedding(c,{type:r,projectHash:i,includePinned:o}),u=Date.now(),d=l.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:_e(n,t,u)}});d.sort((e,t)=>t.score-e.score);let f=d.slice(0,a);for(let e of f)t.repo.incrementAccessCount(e.id);return f}var ve=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=`LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id`,a.push(`p.scope_hash = ?`),o.push(r));let c=a.length>0?`WHERE ${a.join(` AND `)}`:``,l=`
205
+ 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(N(e)),r.set(e.memory_id,t)}return r}};function De(e){return new Ee(e)}const Oe={correction:1,preference:.8,decision:.6,learning:.4,fact:.2};function ke(e,t,n){let r=Oe[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 Z(e,t){let{query:n,type:r,projectHash:i,limit:a=10,includePinned:o}=T.parse(e),s=await t.embedder.embed(n),c=Buffer.from(s.buffer),l=t.adapter.findByEmbedding(c,{type:r,projectHash:i,includePinned:o}),u=Date.now(),d=l.filter(e=>e.cosineSim>0).map(e=>{let{cosineSim:t,...n}=e;return{...n,score:ke(n,t,u)}});d.sort((e,t)=>t.score-e.score);let f=d.slice(0,a);for(let e of f)t.repo.incrementAccessCount(e.id);return f}var Ae=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=`LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id`,a.push(`p.scope_hash = ?`),o.push(r));let c=a.length>0?`WHERE ${a.join(` AND `)}`:``,l=`
179
206
  SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim
180
207
  FROM memories m JOIN embeddings e ON e.rowid = m.rowid
181
208
  ${s}
182
209
  ${c}
183
- `;return this.#e.db.prepare(l).all(...o).map(e=>({...A(e,[]),cosineSim:e.cosine_sim}))}},ye=class{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async query(e){return Z(e,{adapter:new ve(this.#e),repo:this.#n,embedder:this.#t})}};function Q(e,t){let n=t.repo.stats();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 be(){return[...g]}var xe=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Q({projectHash:e,synthesis:t},{repo:this.#e})}},Se=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===`global`?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 Ce(e,t){let n=e===`global`?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 we=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=m({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[h(`query_memory`,`Search memories by semantic similarity`,{query:s.string().describe(`Search text`),limit:s.number().optional().describe(`Maximum results to return`),global:s.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}}),h(`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===`global`?`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=ne({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:[`query_memory`,`get_memory_summary`],permissionMode:`bypassPermissions`,env:a}}),c=``;for await(let e of o)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 Te(e,t){return new we(e,t)}function $(e){return D.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 Ee=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
210
+ `;return this.#e.db.prepare(l).all(...o).map(e=>({...j(e,[]),cosineSim:e.cosine_sim}))}},je=class{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}async query(e){return Z(e,{adapter:new Ae(this.#e),repo:this.#n,embedder:this.#t})}};function Q(e,t){let n=t.repo.stats();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 Me(){return[..._]}var Ne=class{#e;constructor(e){this.#e=e}getSessionContext(e,t){return Q({projectHash:e,synthesis:t},{repo:this.#e})}},Pe=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===`global`?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 Fe(e,t){let n=e===`global`?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 Ie=class{#e;constructor(e,t){this.#e=e}async run(e,t){let n=f({name:`membank-synthesis-tools`,version:`1.0.0`,tools:[m(`query_memory`,`Search memories by semantic similarity`,{query:s.string().describe(`Search text`),limit:s.number().optional().describe(`Maximum results to return`),global:s.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}}),m(`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===`global`?`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=p({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}}),c=``;for await(let e of o)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 Le(e,t){return new Ie(e,t)}function $(e){return O.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 Re=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
184
211
  SET content = ?, source_memory_hash = ?, synthesized_at = ?, expires_at = ?,
185
212
  in_flight_since = NULL, updated_at = ?
186
- WHERE scope = ?`).run(t,n,r,i,r,e);else{let a=p();this.#e.db.prepare(`INSERT INTO syntheses
213
+ WHERE scope = ?`).run(t,n,r,i,r,e);else{let a=g();this.#e.db.prepare(`INSERT INTO syntheses
187
214
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
188
215
  in_flight_since, created_at, updated_at)
189
- 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=p(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
216
+ 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=g(),r=new Date(Date.now()+720*60*60*1e3).toISOString();this.#e.db.prepare(`INSERT INTO syntheses
190
217
  (id, scope, content, source_memory_hash, synthesized_at, expires_at,
191
218
  in_flight_since, created_at, updated_at)
192
219
  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;return t=e===`global`?this.#e.db.prepare(`SELECT content FROM memories
@@ -195,5 +222,5 @@ PRAGMA foreign_keys = ON;
195
222
  JOIN memory_projects mp ON mp.memory_id = m.id
196
223
  JOIN projects p ON p.id = mp.project_id
197
224
  WHERE p.scope_hash = ?
198
- ORDER BY m.id`).all(e),f(`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[`global`,...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 De(e){return new Ee(e)}export{P as DatabaseError,se as DatabaseManager,B as EmbeddingService,g as MEMORY_TYPE_VALUES,fe as MIGRATIONS,I as MODEL_NAME,N as MembankError,E as MemoryPatchSchema,O as MemoryRowSchema,C as MemorySchema,_ as MemoryTypeSchema,L as ModelDownloadError,z as ModelDownloader,K as PIN_BUDGET_THRESHOLD,k as ProjectRowSchema,y as ProjectSchema,ye as QueryEngine,w as QueryOptionsSchema,S as ReviewEventRowSchema,x as ReviewEventSchema,b as ReviewReasonSchema,T as SaveOptionsSchema,xe as SessionContextBuilder,ae as SessionContextSchema,q as SqliteMemoryRepository,Se as SynthesisEngine,D as SynthesisSchema,v as TagsJsonSchema,ue as createMemoryRepository,he as createProjectRepository,Te as createSynthesisAgentRunner,De as createSynthesisRepository,V as deleteMemory,Q as getSessionContext,le as isOverBudget,ie as isSynthesisEnabled,be as listMemoryTypes,Z as queryMemories,X as resolveProject,H as resolveReview,de as resolveScope,A as rowToMemory,M as rowToProject,pe as runScopeToProjectsMigration,Ce as runSynthesis,W as saveMemory,G as updateMemory};
225
+ ORDER BY m.id`).all(e),h(`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[`global`,...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 ze(e){return new Re(e)}export{F as DatabaseError,ce as DatabaseManager,B as EmbeddingService,_ as MEMORY_TYPE_VALUES,we as MIGRATIONS,I as MODEL_NAME,P as MembankError,D as MemoryPatchSchema,k as MemoryRowSchema,w as MemorySchema,v as MemoryTypeSchema,L as ModelDownloadError,z as ModelDownloader,K as PIN_BUDGET_THRESHOLD,A as ProjectRowSchema,b as ProjectSchema,je as QueryEngine,T as QueryOptionsSchema,C as ReviewEventRowSchema,S as ReviewEventSchema,x as ReviewReasonSchema,E as SaveOptionsSchema,Ne as SessionContextBuilder,ae as SessionContextSchema,q as SqliteMemoryRepository,Pe as SynthesisEngine,O as SynthesisSchema,y as TagsJsonSchema,ge as createClaudeCodeTranscriptReader,W as createExtractionAgentRunner,pe as createExtractionRunRepository,Se as createMemoryRepository,De as createProjectRepository,Le as createSynthesisAgentRunner,ze as createSynthesisRepository,_e as deleteMemory,Q as getSessionContext,xe as isOverBudget,ie as isSynthesisEnabled,Me as listMemoryTypes,Z as queryMemories,X as resolveProject,ve as resolveReview,Ce as resolveScope,j as rowToMemory,N as rowToProject,V as runExtraction,Te as runScopeToProjectsMigration,Fe as runSynthesis,ye as saveMemory,be as updateMemory};
199
226
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@membank/core",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",