From 533c3177373958b31edb00bd00493feae87d55c0 Mon Sep 17 00:00:00 2001 From: Alex Newman Date: Sat, 25 Apr 2026 14:06:12 -0700 Subject: [PATCH] chore: bump version to 12.4.1 --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- package.json | 2 +- plugin/.claude-plugin/plugin.json | 2 +- plugin/package.json | 2 +- plugin/scripts/mcp-server.cjs | 2 +- plugin/scripts/worker-service.cjs | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 934004cb..8099e33f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "plugins": [ { "name": "claude-mem", - "version": "12.4.0", + "version": "12.4.1", "source": "./plugin", "description": "Persistent memory system for Claude Code - context compression across sessions" } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index adf3d496..0277834f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "12.4.0", + "version": "12.4.1", "description": "Memory compression system for Claude Code - persist context across sessions", "author": { "name": "Alex Newman" diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index dd81b0ed..31e56a10 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "12.4.0", + "version": "12.4.1", "description": "Memory compression system for Claude Code - persist context across sessions", "author": { "name": "Alex Newman", diff --git a/package.json b/package.json index b53b313e..dc566cd1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "12.4.0", + "version": "12.4.1", "description": "Memory compression system for Claude Code - persist context across sessions", "keywords": [ "claude", diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 986c78d0..2dc571b5 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "12.4.0", + "version": "12.4.1", "description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions", "author": { "name": "Alex Newman" diff --git a/plugin/package.json b/plugin/package.json index 10a84b75..4e2123c3 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,6 +1,6 @@ { "name": "claude-mem-plugin", - "version": "12.4.0", + "version": "12.4.1", "private": true, "description": "Runtime dependencies for claude-mem bundled hooks", "type": "module", diff --git a/plugin/scripts/mcp-server.cjs b/plugin/scripts/mcp-server.cjs index 240ac959..a7599594 100755 --- a/plugin/scripts/mcp-server.cjs +++ b/plugin/scripts/mcp-server.cjs @@ -187,7 +187,7 @@ ${f}`}let s=i.lineStart;for(let u=i.lineStart-1;u>=0;u--){let l=a[u].trim();if(l ${c}`}var mb=new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs",".py",".pyw",".go",".rs",".rb",".java",".cs",".cpp",".cc",".cxx",".c",".h",".hpp",".hh",".swift",".kt",".kts",".php",".vue",".svelte",".ex",".exs",".lua",".scala",".sc",".sh",".bash",".zsh",".hs",".zig",".css",".scss",".toml",".yml",".yaml",".sql",".md",".mdx"]),cD=new Set(["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","env",".env","target","vendor",".cache",".turbo","coverage",".nyc_output",".claude",".smart-file-read"]),uD=512*1024;async function*hb(t,e,r=20,n){if(r<=0)return;let o;try{o=await(0,Un.readdir)(t,{withFileTypes:!0})}catch(i){_.debug("WORKER",`walkDir: failed to read directory ${t}`,void 0,i instanceof Error?i:void 0);return}for(let i of o){if(i.name.startsWith(".")&&i.name!=="."||cD.has(i.name))continue;let a=(0,Mi.join)(t,i.name);if(i.isDirectory())yield*hb(a,e,r-1,n);else if(i.isFile()){let s=i.name.slice(i.name.lastIndexOf("."));(mb.has(s)||n&&n.has(s))&&(yield a)}}}async function lD(t){try{let e=await(0,Un.stat)(t);if(e.size>uD||e.size===0)return null;let r=await(0,Un.readFile)(t,"utf-8");return r.slice(0,1e3).includes("\0")?null:r}catch(e){return _.debug("WORKER",`safeReadFile: failed to read ${t}`,void 0,e instanceof Error?e:void 0),null}}async function gb(t,e,r={}){let n=r.maxResults||20,o=e.toLowerCase(),i=o.split(/[\s_\-./]+/).filter(x=>x.length>0),a=r.projectRoot||t,s=Ri(a),c=new Set;for(let x of Object.values(s.grammars))for(let S of x.extensions)mb.has(S)||c.add(S);let u=[];for await(let x of hb(t,t,20,c.size>0?c:void 0)){if(r.filePattern&&!(0,Mi.relative)(t,x).toLowerCase().includes(r.filePattern.toLowerCase()))continue;let S=await lD(x);S&&u.push({absolutePath:x,relativePath:(0,Mi.relative)(t,x),content:S})}let l=db(u,a),d=[],p=[],f=0;for(let[x,S]of l){f+=dD(S);let z=rc(x.toLowerCase(),i)>0,Ve=[],We=(Zn,qr)=>{for(let ye of Zn){let rr=0,mt="",Fn=rc(ye.name.toLowerCase(),i);Fn>0&&(rr+=Fn*3,mt="name match"),ye.signature.toLowerCase().includes(o)&&(rr+=2,mt=mt?`${mt} + signature`:"signature match"),ye.jsdoc&&ye.jsdoc.toLowerCase().includes(o)&&(rr+=1,mt=mt?`${mt} + jsdoc`:"jsdoc match"),rr>0&&(z=!0,Ve.push({filePath:x,symbolName:qr?`${qr}.${ye.name}`:ye.name,kind:ye.kind,signature:ye.signature,jsdoc:ye.jsdoc,lineStart:ye.lineStart,lineEnd:ye.lineEnd,matchReason:mt})),ye.children&&We(ye.children,ye.name)}};We(S.symbols),z&&(d.push(S),p.push(...Ve))}p.sort((x,S)=>{let R=rc(x.symbolName.toLowerCase(),i);return rc(S.symbolName.toLowerCase(),i)-R});let h=p.slice(0,n),g=new Set(h.map(x=>x.filePath)),$=d.filter(x=>g.has(x.filePath)).slice(0,n),k=$.reduce((x,S)=>x+S.foldedTokenEstimate,0);return{foldedFiles:$,matchingSymbols:h,totalFilesScanned:u.length,totalSymbolsFound:f,tokenEstimate:k}}function rc(t,e){let r=0;for(let n of e)if(t===n)r+=10;else if(t.includes(n))r+=5;else{let o=0,i=0;for(let a of n){let s=t.indexOf(a,o);s!==-1&&(i++,o=s+1)}i===n.length&&(r+=1)}return r}function dD(t){let e=t.symbols.length;for(let r of t.symbols)r.children&&(e+=r.children.length);return e}function vb(t,e){let r=[];if(r.push(`\u{1F50D} Smart Search: "${e}"`),r.push(` Scanned ${t.totalFilesScanned} files, found ${t.totalSymbolsFound} symbols`),r.push(` ${t.matchingSymbols.length} matches across ${t.foldedFiles.length} files (~${t.tokenEstimate} tokens for folded view)`),r.push(""),t.matchingSymbols.length===0)return r.push(" No matching symbols found."),r.join(` `);r.push("\u2500\u2500 Matching Symbols \u2500\u2500"),r.push("");for(let n of t.matchingSymbols){if(r.push(` ${n.kind} ${n.symbolName} (${n.filePath}:${n.lineStart+1})`),r.push(` ${n.signature}`),n.jsdoc){let o=n.jsdoc.split(` `).find(i=>i.replace(/^[\s*/]+/,"").trim().length>0);o&&r.push(` \u{1F4AC} ${o.replace(/^[\s*/]+/,"").trim()}`)}r.push("")}r.push("\u2500\u2500 Folded File Views \u2500\u2500"),r.push("");for(let n of t.foldedFiles)r.push(Cn(n)),r.push("");return r.push("\u2500\u2500 Actions \u2500\u2500"),r.push(" To see full implementation: use smart_unfold with file path and symbol name"),r.join(` -`)}var _m=require("node:fs/promises"),$b=require("node:fs"),Fr=require("node:path"),bb=require("node:url"),SD={},pD="12.4.0";console.log=(...t)=>{_.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var Sb=!1,xb=(()=>{if(typeof __dirname<"u")return __dirname;try{return(0,Fr.dirname)((0,bb.fileURLToPath)(SD.url))}catch{return Sb=!0,process.cwd()}})(),ym=(0,Fr.resolve)(xb,"worker-service.cjs");function fD(){Sb&&((0,$b.existsSync)(ym)||_.error("SYSTEM","mcp-server: dirname resolution failed (both __dirname and import.meta.url are unavailable). Fell back to process.cwd() and the resolved WORKER_SCRIPT_PATH does not exist. This is the actual problem \u2014 the worker bundle is fine, but mcp-server cannot locate it. Worker auto-start will fail until the dirname-resolution path is fixed.",{workerScriptPath:ym,mcpServerDir:xb}))}var _b={search:"/api/search",timeline:"/api/timeline"};async function vm(t,e){_.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:t,params:e});let r=new URLSearchParams;for(let[o,i]of Object.entries(e))i!=null&&r.append(o,String(i));let n=`${t}?${r}`;try{let o=await Qs(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return _.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),i}catch(o){return _.error("SYSTEM","\u2190 Worker API error",{endpoint:t},o instanceof Error?o:new Error(String(o))),{content:[{type:"text",text:`Error calling Worker API: ${o instanceof Error?o.message:String(o)}`}],isError:!0}}}async function mD(t,e){let r=await Qs(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){let o=await r.text();throw new Error(`Worker API error (${r.status}): ${o}`)}let n=await r.json();return _.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}async function Ln(t,e){_.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{return await mD(t,e)}catch(r){return _.error("HTTP","Worker API error (POST)",{endpoint:t},r instanceof Error?r:new Error(String(r))),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function hD(){try{return(await Qs("/api/health")).ok}catch(t){return _.debug("SYSTEM","Worker health check failed",{},t instanceof Error?t:new Error(String(t))),!1}}async function gD(){if(await hD())return!0;_.warn("SYSTEM","Worker not available, attempting auto-start for MCP client"),fD();try{let t=im(),e=await Q$(t,ym);return e||_.error("SYSTEM","Worker auto-start returned false \u2014 MCP tools that require the worker (search, timeline, get_observations) will fail until the worker is running. Check earlier log lines for the specific failure reason (Bun not found, missing worker bundle, port conflict, etc.)."),e}catch(t){return _.error("SYSTEM","Worker auto-start threw \u2014 MCP tools that require the worker (search, timeline, get_observations) will fail until the worker is running.",void 0,t instanceof Error?t:new Error(String(t))),!1}}var kb=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW): +`)}var _m=require("node:fs/promises"),$b=require("node:fs"),Fr=require("node:path"),bb=require("node:url"),SD={},pD="12.4.1";console.log=(...t)=>{_.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var Sb=!1,xb=(()=>{if(typeof __dirname<"u")return __dirname;try{return(0,Fr.dirname)((0,bb.fileURLToPath)(SD.url))}catch{return Sb=!0,process.cwd()}})(),ym=(0,Fr.resolve)(xb,"worker-service.cjs");function fD(){Sb&&((0,$b.existsSync)(ym)||_.error("SYSTEM","mcp-server: dirname resolution failed (both __dirname and import.meta.url are unavailable). Fell back to process.cwd() and the resolved WORKER_SCRIPT_PATH does not exist. This is the actual problem \u2014 the worker bundle is fine, but mcp-server cannot locate it. Worker auto-start will fail until the dirname-resolution path is fixed.",{workerScriptPath:ym,mcpServerDir:xb}))}var _b={search:"/api/search",timeline:"/api/timeline"};async function vm(t,e){_.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:t,params:e});let r=new URLSearchParams;for(let[o,i]of Object.entries(e))i!=null&&r.append(o,String(i));let n=`${t}?${r}`;try{let o=await Qs(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return _.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),i}catch(o){return _.error("SYSTEM","\u2190 Worker API error",{endpoint:t},o instanceof Error?o:new Error(String(o))),{content:[{type:"text",text:`Error calling Worker API: ${o instanceof Error?o.message:String(o)}`}],isError:!0}}}async function mD(t,e){let r=await Qs(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){let o=await r.text();throw new Error(`Worker API error (${r.status}): ${o}`)}let n=await r.json();return _.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}async function Ln(t,e){_.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{return await mD(t,e)}catch(r){return _.error("HTTP","Worker API error (POST)",{endpoint:t},r instanceof Error?r:new Error(String(r))),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function hD(){try{return(await Qs("/api/health")).ok}catch(t){return _.debug("SYSTEM","Worker health check failed",{},t instanceof Error?t:new Error(String(t))),!1}}async function gD(){if(await hD())return!0;_.warn("SYSTEM","Worker not available, attempting auto-start for MCP client"),fD();try{let t=im(),e=await Q$(t,ym);return e||_.error("SYSTEM","Worker auto-start returned false \u2014 MCP tools that require the worker (search, timeline, get_observations) will fail until the worker is running. Check earlier log lines for the specific failure reason (Bun not found, missing worker bundle, port conflict, etc.)."),e}catch(t){return _.error("SYSTEM","Worker auto-start threw \u2014 MCP tools that require the worker (search, timeline, get_observations) will fail until the worker is running.",void 0,t instanceof Error?t:new Error(String(t))),!1}}var kb=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW): 1. search(query) \u2192 Get index with IDs (~50-100 tokens/result) 2. timeline(anchor=ID) \u2192 Get context around interesting results 3. get_observations([IDs]) \u2192 Fetch full details ONLY for filtered IDs diff --git a/plugin/scripts/worker-service.cjs b/plugin/scripts/worker-service.cjs index 2e467ad8..18ddc90f 100755 --- a/plugin/scripts/worker-service.cjs +++ b/plugin/scripts/worker-service.cjs @@ -1033,7 +1033,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs. SELECT cwd FROM pending_messages WHERE cwd IS NOT NULL AND cwd != '' GROUP BY cwd - `).all();for(let{cwd:u}of c){let l=RL(u);l&&i.add(l)}}finally{s?.close()}if(i.size===0)return h.debug("SYSTEM","Worktree adoption found no known parent repos"),n;for(let o of i)try{let a=await AI({repoPath:o,dataDirectory:e,dryRun:t.dryRun});n.push(a)}catch(a){h.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return n}var H8=$e(dS(),1),Z8=$e(require("http"),1),FO=$e(require("fs"),1),Em=$e(require("path"),1);var DO=["search","context","summarize","import","export"],O8=["workflow","search_params","examples","all"];re();var jO=$e(dS(),1),D8=$e(M8(),1),j8=$e(require("path"),1);xt();re();function zO(t){let e=[];e.push(jO.default.json({limit:"5mb"})),e.push((0,D8.default)({origin:(i,s)=>{!i||i.startsWith("http://localhost:")||i.startsWith("http://127.0.0.1:")?s(null,!0):s(new Error("CORS not allowed"))},methods:["GET","HEAD","POST","PUT","PATCH","DELETE"],allowedHeaders:["Content-Type","X-Requested-With"],credentials:!1})),e.push((i,s,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(m=>i.path.endsWith(m)),u=i.path==="/api/logs";if(i.path.startsWith("/health")||i.path==="/"||c||u)return o();let l=Date.now(),d=`${i.method}-${Date.now()}`,p=t(i.method,i.path,i.body);h.debug("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let f=s.send.bind(s);s.send=function(m){let g=Date.now()-l;return h.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${g}ms`}),f(m)},o()});let r=Rn(),n=j8.default.join(r,"plugin","ui");return e.push(jO.default.static(n)),e}function xm(t,e,r){let n=t.ip||t.connection.remoteAddress||"";if(!(n==="127.0.0.1"||n==="::1"||n==="::ffff:127.0.0.1"||n==="localhost")){h.warn("SECURITY","Admin endpoint access denied - not localhost",{endpoint:t.path,clientIp:n,method:t.method}),e.status(403).json({error:"Forbidden",message:"Admin endpoints are only accessible from localhost"});return}r()}function LO(t,e,r){if(!r||Object.keys(r).length===0||e.includes("/init"))return"";if(e.includes("/observations")){let n=r.tool_name||"?",i=r.tool_input;return`tool=${h.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}wm();Jo();gs();Wo();var B8=Em.default.resolve(__dirname,"../skills/mem-search"),xme=Em.default.join(B8,"operations"),UO=Em.default.join(B8,"SKILL.md"),F8=(()=>{try{let t=FO.readFileSync(UO,"utf-8");return h.info("SYSTEM","Cached SKILL.md at boot",{path:UO,bytes:Buffer.byteLength(t,"utf-8")}),t}catch(t){return h.debug("SYSTEM","SKILL.md not present at boot, /api/instructions will 404 for topic queries",{path:UO,message:t instanceof Error?t.message:String(t)}),null}})(),wme=(()=>{let t=new Map;for(let e of DO){let r=Em.default.join(xme,`${e}.md`);try{t.set(e,FO.readFileSync(r,"utf-8"))}catch(n){h.debug("SYSTEM","Operation instruction file not present at boot",{path:r,message:n instanceof Error?n.message:String(n)})}}return t.size>0&&h.info("SYSTEM","Cached operation instruction files at boot",{count:t.size,operations:Array.from(t.keys())}),t})(),q8="12.4.0",pS=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,H8.default)(),this.setupMiddleware(),this.setupCoreRoutes()}getHttpServer(){return this.server}async listen(e,r){return new Promise((n,i)=>{let s=Z8.default.createServer(this.app);this.server=s;let o=c=>{s.off("listening",a),i(c)},a=()=>{s.off("error",o),h.info("SYSTEM","HTTP server started",{host:r,port:e,pid:process.pid}),n()};s.once("error",o),s.once("listening",a),s.listen(e,r)})}async close(){this.server&&(this.server.closeAllConnections(),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),await new Promise((e,r)=>{this.server.close(n=>n?r(n):e())}),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),this.server=null,h.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(U8),this.app.use(L8)}setupMiddleware(){zO(LO).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:q8,workerPath:this.options.workerPath,uptime:Date.now()-this.startTime,managed:process.env.CLAUDE_MEM_MANAGED==="true",hasIpc:typeof process.send=="function",platform:process.platform,pid:process.pid,initialized:this.options.getInitializationComplete(),mcpReady:this.options.getMcpReady(),ai:this.options.getAiStatus()})}),this.app.get("/api/readiness",(e,r)=>{this.options.getInitializationComplete()?r.status(200).json({status:"ready",mcpReady:this.options.getMcpReady()}):r.status(503).json({status:"initializing",message:"Worker is still initializing, please retry"})}),this.app.get("/api/version",(e,r)=>{r.status(200).json({version:q8})}),this.app.get("/api/instructions",(e,r)=>{let n=e.query.topic||"all",i=e.query.operation;if(n&&!O8.includes(n))return r.status(400).json({error:"Invalid topic"});if(i&&!DO.includes(i))return r.status(400).json({error:"Invalid operation"});if(i){let o=wme.get(i);return o===void 0?(h.debug("HTTP","Instruction file not cached at boot",{operation:i}),r.status(404).json({error:"Instruction not found"})):r.json({content:[{type:"text",text:o}]})}if(F8===null)return h.debug("HTTP","SKILL.md not cached at boot",{topic:n}),r.status(404).json({error:"Instruction not found"});let s=this.extractInstructionSection(F8,n);r.json({content:[{type:"text",text:s}]})}),this.app.post("/api/admin/restart",xm,async(e,r)=>{r.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(h.info("SYSTEM","Sending restart request to wrapper"),process.send({type:"restart"})):setTimeout(async()=>{try{await this.options.onRestart()}finally{process.exit(0)}},100)}),this.app.post("/api/admin/shutdown",xm,async(e,r)=>{r.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(h.info("SYSTEM","Sending shutdown request to wrapper"),process.send({type:"shutdown"})):setTimeout(async()=>{try{await this.options.onShutdown()}finally{process.exit(0)}},100)}),this.app.get("/api/admin/doctor",xm,(e,r)=>{let o=jr().getRegistry().getAll().map(m=>({id:m.id,pid:m.pid,type:m.type,status:Zn(m.pid)?"alive":"dead",startedAt:m.startedAt})),a=o.filter(m=>m.status==="dead").map(m=>m.pid),c=!Object.keys(process.env).some(m=>tI.has(m)||eI.some(g=>m.startsWith(g))),u=Date.now()-this.startTime,l=Math.floor(u/1e3),d=Math.floor(l/3600),p=Math.floor(l%3600/60),f=d>0?`${d}h ${p}m`:`${p}m`;r.json({supervisor:{running:!0,pid:process.pid,uptime:f},processes:o,health:{deadProcessPids:a,envClean:c}})})}extractInstructionSection(e,r){let n={workflow:this.extractBetween(e,"## The Workflow","## Search Parameters"),search_params:this.extractBetween(e,"## Search Parameters","## Examples"),examples:this.extractBetween(e,"## Examples","## Why This Workflow"),all:e};return n[r]||n.all}extractBetween(e,r,n){let i=e.indexOf(r),s=e.indexOf(n);return i===-1?e:s===-1?e.substring(i):e.substring(i,s).trim()}};var Nt=$e(require("path"),1),Tm=require("os"),er=require("fs"),V8=require("child_process"),K8=require("util");re();zr();xt();var yi=require("fs"),km=require("path");re();function W8(t){try{return(0,yi.existsSync)(t)?JSON.parse((0,yi.readFileSync)(t,"utf-8")):{}}catch(e){return h.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function G8(t,e){let r=(0,km.join)(t,"..");(0,yi.mkdirSync)(r,{recursive:!0}),(0,yi.writeFileSync)(t,JSON.stringify(e,null,2))}function qO(t,e){let r=(0,km.join)(t,".cursor","rules"),n=(0,km.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,yi.mkdirSync)(r,{recursive:!0});let s=`--- + `).all();for(let{cwd:u}of c){let l=RL(u);l&&i.add(l)}}finally{s?.close()}if(i.size===0)return h.debug("SYSTEM","Worktree adoption found no known parent repos"),n;for(let o of i)try{let a=await AI({repoPath:o,dataDirectory:e,dryRun:t.dryRun});n.push(a)}catch(a){h.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return n}var H8=$e(dS(),1),Z8=$e(require("http"),1),FO=$e(require("fs"),1),Em=$e(require("path"),1);var DO=["search","context","summarize","import","export"],O8=["workflow","search_params","examples","all"];re();var jO=$e(dS(),1),D8=$e(M8(),1),j8=$e(require("path"),1);xt();re();function zO(t){let e=[];e.push(jO.default.json({limit:"5mb"})),e.push((0,D8.default)({origin:(i,s)=>{!i||i.startsWith("http://localhost:")||i.startsWith("http://127.0.0.1:")?s(null,!0):s(new Error("CORS not allowed"))},methods:["GET","HEAD","POST","PUT","PATCH","DELETE"],allowedHeaders:["Content-Type","X-Requested-With"],credentials:!1})),e.push((i,s,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(m=>i.path.endsWith(m)),u=i.path==="/api/logs";if(i.path.startsWith("/health")||i.path==="/"||c||u)return o();let l=Date.now(),d=`${i.method}-${Date.now()}`,p=t(i.method,i.path,i.body);h.debug("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let f=s.send.bind(s);s.send=function(m){let g=Date.now()-l;return h.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${g}ms`}),f(m)},o()});let r=Rn(),n=j8.default.join(r,"plugin","ui");return e.push(jO.default.static(n)),e}function xm(t,e,r){let n=t.ip||t.connection.remoteAddress||"";if(!(n==="127.0.0.1"||n==="::1"||n==="::ffff:127.0.0.1"||n==="localhost")){h.warn("SECURITY","Admin endpoint access denied - not localhost",{endpoint:t.path,clientIp:n,method:t.method}),e.status(403).json({error:"Forbidden",message:"Admin endpoints are only accessible from localhost"});return}r()}function LO(t,e,r){if(!r||Object.keys(r).length===0||e.includes("/init"))return"";if(e.includes("/observations")){let n=r.tool_name||"?",i=r.tool_input;return`tool=${h.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}wm();Jo();gs();Wo();var B8=Em.default.resolve(__dirname,"../skills/mem-search"),xme=Em.default.join(B8,"operations"),UO=Em.default.join(B8,"SKILL.md"),F8=(()=>{try{let t=FO.readFileSync(UO,"utf-8");return h.info("SYSTEM","Cached SKILL.md at boot",{path:UO,bytes:Buffer.byteLength(t,"utf-8")}),t}catch(t){return h.debug("SYSTEM","SKILL.md not present at boot, /api/instructions will 404 for topic queries",{path:UO,message:t instanceof Error?t.message:String(t)}),null}})(),wme=(()=>{let t=new Map;for(let e of DO){let r=Em.default.join(xme,`${e}.md`);try{t.set(e,FO.readFileSync(r,"utf-8"))}catch(n){h.debug("SYSTEM","Operation instruction file not present at boot",{path:r,message:n instanceof Error?n.message:String(n)})}}return t.size>0&&h.info("SYSTEM","Cached operation instruction files at boot",{count:t.size,operations:Array.from(t.keys())}),t})(),q8="12.4.1",pS=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,H8.default)(),this.setupMiddleware(),this.setupCoreRoutes()}getHttpServer(){return this.server}async listen(e,r){return new Promise((n,i)=>{let s=Z8.default.createServer(this.app);this.server=s;let o=c=>{s.off("listening",a),i(c)},a=()=>{s.off("error",o),h.info("SYSTEM","HTTP server started",{host:r,port:e,pid:process.pid}),n()};s.once("error",o),s.once("listening",a),s.listen(e,r)})}async close(){this.server&&(this.server.closeAllConnections(),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),await new Promise((e,r)=>{this.server.close(n=>n?r(n):e())}),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),this.server=null,h.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(U8),this.app.use(L8)}setupMiddleware(){zO(LO).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:q8,workerPath:this.options.workerPath,uptime:Date.now()-this.startTime,managed:process.env.CLAUDE_MEM_MANAGED==="true",hasIpc:typeof process.send=="function",platform:process.platform,pid:process.pid,initialized:this.options.getInitializationComplete(),mcpReady:this.options.getMcpReady(),ai:this.options.getAiStatus()})}),this.app.get("/api/readiness",(e,r)=>{this.options.getInitializationComplete()?r.status(200).json({status:"ready",mcpReady:this.options.getMcpReady()}):r.status(503).json({status:"initializing",message:"Worker is still initializing, please retry"})}),this.app.get("/api/version",(e,r)=>{r.status(200).json({version:q8})}),this.app.get("/api/instructions",(e,r)=>{let n=e.query.topic||"all",i=e.query.operation;if(n&&!O8.includes(n))return r.status(400).json({error:"Invalid topic"});if(i&&!DO.includes(i))return r.status(400).json({error:"Invalid operation"});if(i){let o=wme.get(i);return o===void 0?(h.debug("HTTP","Instruction file not cached at boot",{operation:i}),r.status(404).json({error:"Instruction not found"})):r.json({content:[{type:"text",text:o}]})}if(F8===null)return h.debug("HTTP","SKILL.md not cached at boot",{topic:n}),r.status(404).json({error:"Instruction not found"});let s=this.extractInstructionSection(F8,n);r.json({content:[{type:"text",text:s}]})}),this.app.post("/api/admin/restart",xm,async(e,r)=>{r.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(h.info("SYSTEM","Sending restart request to wrapper"),process.send({type:"restart"})):setTimeout(async()=>{try{await this.options.onRestart()}finally{process.exit(0)}},100)}),this.app.post("/api/admin/shutdown",xm,async(e,r)=>{r.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(h.info("SYSTEM","Sending shutdown request to wrapper"),process.send({type:"shutdown"})):setTimeout(async()=>{try{await this.options.onShutdown()}finally{process.exit(0)}},100)}),this.app.get("/api/admin/doctor",xm,(e,r)=>{let o=jr().getRegistry().getAll().map(m=>({id:m.id,pid:m.pid,type:m.type,status:Zn(m.pid)?"alive":"dead",startedAt:m.startedAt})),a=o.filter(m=>m.status==="dead").map(m=>m.pid),c=!Object.keys(process.env).some(m=>tI.has(m)||eI.some(g=>m.startsWith(g))),u=Date.now()-this.startTime,l=Math.floor(u/1e3),d=Math.floor(l/3600),p=Math.floor(l%3600/60),f=d>0?`${d}h ${p}m`:`${p}m`;r.json({supervisor:{running:!0,pid:process.pid,uptime:f},processes:o,health:{deadProcessPids:a,envClean:c}})})}extractInstructionSection(e,r){let n={workflow:this.extractBetween(e,"## The Workflow","## Search Parameters"),search_params:this.extractBetween(e,"## Search Parameters","## Examples"),examples:this.extractBetween(e,"## Examples","## Why This Workflow"),all:e};return n[r]||n.all}extractBetween(e,r,n){let i=e.indexOf(r),s=e.indexOf(n);return i===-1?e:s===-1?e.substring(i):e.substring(i,s).trim()}};var Nt=$e(require("path"),1),Tm=require("os"),er=require("fs"),V8=require("child_process"),K8=require("util");re();zr();xt();var yi=require("fs"),km=require("path");re();function W8(t){try{return(0,yi.existsSync)(t)?JSON.parse((0,yi.readFileSync)(t,"utf-8")):{}}catch(e){return h.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function G8(t,e){let r=(0,km.join)(t,"..");(0,yi.mkdirSync)(r,{recursive:!0}),(0,yi.writeFileSync)(t,JSON.stringify(e,null,2))}function qO(t,e){let r=(0,km.join)(t,".cursor","rules"),n=(0,km.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,yi.mkdirSync)(r,{recursive:!0});let s=`--- alwaysApply: true description: "Claude-mem context from past sessions (auto-updated)" --- @@ -1652,7 +1652,7 @@ ${s.formatTableHeader()}`,f=d.map((m,g)=>s.formatObservationIndex(m,g));n.json({ `);cr(ci);let i=this.findClaudeExecutable(),s=Hn(jf()),o=ih({prompt:n,options:{model:this.getModelId(),cwd:ci,disallowedTools:mW,pathToClaudeCodeExecutable:i,env:s}}),a;try{for await(let c of o)c.session_id&&(a=c.session_id),c.type==="result"&&h.info("WORKER",`Knowledge agent primed for corpus "${e.name}"`)}catch(c){if(a)c instanceof Error?h.debug("WORKER",`SDK process exited after priming corpus "${e.name}" \u2014 session captured, continuing`,{},c):h.debug("WORKER",`SDK process exited after priming corpus "${e.name}" \u2014 session captured, continuing (non-Error thrown)`,{thrownValue:String(c)});else throw c}if(!a)throw new Error(`Failed to capture session_id while priming corpus "${e.name}"`);return e.session_id=a,this.corpusStore.write(e),a}async query(e,r){if(!e.session_id)throw new Error(`Corpus "${e.name}" has no session \u2014 call prime first`);try{let n=await this.executeQuery(e,r);return n.session_id!==e.session_id&&(e.session_id=n.session_id,this.corpusStore.write(e)),n}catch(n){if(!this.isSessionResumeError(n))throw n instanceof Error?h.error("WORKER",`Query failed for corpus "${e.name}"`,{},n):h.error("WORKER",`Query failed for corpus "${e.name}" (non-Error thrown)`,{thrownValue:String(n)}),n;h.info("WORKER",`Session expired for corpus "${e.name}", auto-repriming...`),await this.prime(e);let i=this.corpusStore.read(e.name);if(!i||!i.session_id)throw new Error(`Auto-reprime failed for corpus "${e.name}"`);let s=await this.executeQuery(i,r);return s.session_id!==i.session_id&&(i.session_id=s.session_id,this.corpusStore.write(i)),s}}async reprime(e){return e.session_id=null,this.prime(e)}isSessionResumeError(e){let r=e instanceof Error?e.message:String(e);return/session|resume|expired|invalid.*session|not found/i.test(r)}async executeQuery(e,r){cr(ci);let n=this.findClaudeExecutable(),i=Hn(jf()),s=ih({prompt:r,options:{model:this.getModelId(),resume:e.session_id,cwd:ci,disallowedTools:mW,pathToClaudeCodeExecutable:n,env:i}}),o="",a=e.session_id;try{for await(let c of s)c.session_id&&(a=c.session_id),c.type==="assistant"&&(o=c.message.content.filter(l=>l.type==="text").map(l=>l.text).join(""))}catch(c){if(o)c instanceof Error?h.debug("WORKER","SDK process exited after query \u2014 answer captured, continuing",{},c):h.debug("WORKER","SDK process exited after query \u2014 answer captured, continuing (non-Error thrown)",{thrownValue:String(c)});else throw c}return{answer:o,session_id:a}}getModelId(){return be.loadFromFile(gt).CLAUDE_MEM_MODEL}findClaudeExecutable(){let e=be.loadFromFile(gt);if(e.CLAUDE_CODE_PATH){let{existsSync:r}=require("fs");if(!r(e.CLAUDE_CODE_PATH))throw new Error(`CLAUDE_CODE_PATH is set to "${e.CLAUDE_CODE_PATH}" but the file does not exist.`);return e.CLAUDE_CODE_PATH}if(process.platform==="win32")try{return(0,VP.execSync)("where claude.cmd",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}),"claude.cmd"}catch{}try{let r=(0,VP.execSync)(process.platform==="win32"?"where claude":"which claude",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}).trim().split(` `)[0].trim();if(r)return r}catch(r){r instanceof Error?h.debug("WORKER","Claude executable auto-detection failed",{},r):h.debug("WORKER","Claude executable auto-detection failed (non-Error thrown)",{thrownValue:String(r)})}throw new Error(`Claude executable not found. Please either: 1. Add "claude" to your system PATH, or -2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};gs();var DTe={},PTe="12.4.0";function ZW(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var pw=class t{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;completionHandler;corpusStore;searchRoutes=null;chromaMcpManager=null;transcriptWatcher=null;initializationComplete;resolveInitialization;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new gS,this.sessionManager=new bS(this.dbManager),this.sseBroadcaster=new SS,this.sdkAgent=new ex(this.dbManager,this.sessionManager),this.geminiAgent=new tx(this.dbManager,this.sessionManager),this.openRouterAgent=new ix(this.dbManager,this.sessionManager),this.paginationHelper=new sx(this.dbManager),this.settingsManager=new ox(this.dbManager),this.sessionEventBroadcaster=new dx(this.sseBroadcaster,this),this.completionHandler=new px(this.sessionManager,this.sessionEventBroadcaster,this.dbManager),this.corpusStore=new aw,vH({sessionManager:this.sessionManager,dbManager:this.dbManager,eventBroadcaster:this.sessionEventBroadcaster}),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Ku({name:"worker-search-proxy",version:PTe},{capabilities:{}}),this.server=new pS({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return od()&&Tc()?e="openrouter":sd()&&kc()&&(e="gemini"),{provider:e,authMethod:Z_(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){q4(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.registerRoutes(new ow),this.server.app.get("/api/context/inject",async(r,n,i)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){h.warn("SYSTEM","Context requested before initialization complete, returning empty"),n.status(200).json({content:[{type:"text",text:""}]});return}i()}),this.server.app.use("/api",async(r,n,i)=>{if(r.path==="/chroma/status"||r.path==="/health"||r.path==="/readiness"||r.path==="/version"){i();return}if(this.initializationCompleteFlag){i();return}let s=12e4,o=new Promise((a,c)=>setTimeout(()=>c(new Error("Database initialization timeout")),s));try{await Promise.race([this.initializationComplete,o]),i()}catch(a){a instanceof Error?h.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized`,{},a):h.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized with non-Error`,{},new Error(String(a))),n.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"});return}}),this.server.registerRoutes(new Zx(this.sseBroadcaster,this.dbManager,this.sessionManager));let e=new Wx(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this,this.completionHandler);this.server.registerRoutes(e),yH((r,n)=>e.ensureGeneratorRunning(r,n)),this.server.registerRoutes(new Gx(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new tw(this.settingsManager)),this.server.registerRoutes(new nw),this.server.registerRoutes(new iw(this.dbManager,"claude-mem"))}async start(){let e=un(),r=lI();await F4(),await this.server.listen(e,r),mL({pid:process.pid,port:e,startedAt:new Date().toISOString()}),jr().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),h.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(n=>{h.error("SYSTEM","Background initialization failed",{},n)})}async initializeBackground(){try{h.info("WORKER","Background initialization starting..."),await hL();let{ModeManager:e}=await Promise.resolve().then(()=>(fn(),aH)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(Jt(),h4)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(xt(),x4)),i=r.loadFromFile(n),s=i.CLAUDE_MEM_MODE;e.getInstance().loadMode(s),h.info("SYSTEM",`Mode loaded: ${s}`),(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&(h.info("WORKER","Checking for one-time Chroma migration..."),gL()),h.info("WORKER","Checking for one-time CWD remap..."),vL(),h.info("WORKER","Adopting merged worktrees (background)..."),OL({}).then(g=>{if(g)for(let v of g)(v.adoptedObservations>0||v.adoptedSummaries>0||v.chromaUpdates>0)&&h.info("SYSTEM","Merged worktrees adopted in background",v),v.errors.length>0&&h.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:v.repoPath,errors:v.errors})}).catch(g=>{h.error("WORKER","Worktree adoption failed (background)",{},g instanceof Error?g:new Error(String(g)))}),i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=li.getInstance(),h.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):h.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager"),h.info("WORKER","Initializing database manager..."),await this.dbManager.initialize();try{h.info("WORKER","Running startup GC for pending messages...");let{PendingMessageStore:g}=await Promise.resolve().then(()=>(vS(),KO)),y=new g(this.dbManager.getSessionStore().db,3).clearFailedOlderThan(10080*60*1e3);y>0&&h.info("QUEUE","Startup GC cleared old failed pending_messages rows",{cleared:y})}catch(g){h.warn("QUEUE","Startup GC for failed pending_messages rows failed",{},g instanceof Error?g:void 0)}h.info("WORKER","Initializing search services...");let a=new ux,c=new lx,u=new cx(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),a,c);this.searchRoutes=new Xx(u),this.server.registerRoutes(this.searchRoutes),h.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:l}=await Promise.resolve().then(()=>(nP(),iZ)),d=new l(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),p=new uw(this.dbManager.getSessionStore(),d,this.corpusStore),f=new lw(this.corpusStore);this.server.registerRoutes(new sw(this.corpusStore,p,f)),h.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),h.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(i),this.chromaMcpManager&&Xo.backfillAllProjects(this.dbManager.getSessionStore()).then(()=>{h.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(g=>{h.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},g)});let m=HW.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,u1.existsSync)(m),this.runMcpSelfCheck(m).catch(g=>{h.debug("WORKER","MCP self-check failed (non-fatal)",{error:g.message})});return}catch(e){h.error("SYSTEM","Background initialization failed",{},e instanceof Error?e:void 0)}}async runMcpSelfCheck(e){try{jr().assertCanSpawn("mcp server");let r=new Xu({command:process.execPath,args:[e],env:Object.fromEntries(Object.entries(Hn(process.env)).filter(([,o])=>o!==void 0))}),n=6e4,i=this.mcpClient.connect(r),s=new Promise((o,a)=>{setTimeout(()=>a(new Error("MCP connection timeout")),6e4)});await Promise.race([i,s]),h.info("WORKER","MCP loopback self-check connected successfully"),await r.close()}catch(r){h.warn("WORKER","MCP loopback self-check failed",{error:r instanceof Error?r.message:String(r)})}}async startTranscriptWatcher(e){if(!(e.CLAUDE_MEM_TRANSCRIPTS_ENABLED!=="false")){h.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let n=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||mx,i=ho(n);(0,u1.existsSync)(i)||(oZ(n),h.info("TRANSCRIPT","Created default transcript watch config",{configPath:i}));let s=sZ(n),o=ho(s.stateFile??hx);try{this.transcriptWatcher=new Fx(s,o),await this.transcriptWatcher.start()}catch(a){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,a instanceof Error?h.error("WORKER","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:i},a):h.error("WORKER","Failed to start transcript watcher with non-Error (continuing without Codex ingestion)",{configPath:i},new Error(String(a)));return}h.info("TRANSCRIPT","Transcript watcher started",{configPath:i,statePath:o,watches:s.watches.length})}getActiveAgent(){return od()&&Tc()?this.openRouterAgent:sd()&&kc()?this.geminiAgent:this.sdkAgent}startSessionProcessor(e,r){if(!e)return;let n=e.sessionDbId,i=this.getActiveAgent(),s=i.constructor.name;e.abortController.signal.aborted&&(h.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;h.info("SYSTEM",`Starting generator (${r}) using ${s}`,{sessionId:n}),e.lastGeneratorActivity=Date.now(),e.generatorPromise=i.startSession(e,this).catch(async c=>{let u=c?.message||"";if(["Claude executable not found","CLAUDE_CODE_PATH","ENOENT","spawn","Invalid API key","API_KEY_INVALID","API key expired","API key not valid","PERMISSION_DENIED","Gemini API error: 400","Gemini API error: 401","Gemini API error: 403","FOREIGN KEY constraint failed"].some(p=>u.includes(p))){o=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},h.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return h.warn("SDK","SDK resume failed, falling back to standalone processing",{sessionId:e.sessionDbId,project:e.project,reason:c instanceof Error?c.message:String(c)}),this.runFallbackForTerminatedSession(e,c);throw["aborted by user","No conversation found"].some(p=>u.includes(p))&&e.memorySessionId&&(h.warn("SDK","Detected stale resume failure, clearing memorySessionId for fresh start",{sessionId:e.sessionDbId,memorySessionId:e.memorySessionId,errorMessage:u}),this.dbManager.getSessionStore().updateMemorySessionId(e.sessionDbId,null),e.memorySessionId=null,e.forceInit=!0),h.error("SDK","Session generator failed",{sessionId:e.sessionDbId,project:e.project,provider:s},c),a=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},c}).finally(async()=>{let c=Vo(e.sessionDbId);if(c&&c.process.exitCode===null&&await Ko(c,5e3),e.generatorPromise=null,!a&&!o&&(this.lastAiInteraction={timestamp:Date.now(),success:!0,provider:s}),o){this.terminateSession(e.sessionDbId,"unrecoverable_error");return}let l=this.sessionManager.getPendingMessageStore().getPendingCount(e.sessionDbId);if(e.idleTimedOut&&(e.idleTimedOut=!1,l===0)){this.terminateSession(e.sessionDbId,"idle_timeout");return}if(l>0){e.restartGuard||(e.restartGuard=new ea);let d=e.restartGuard.recordRestart();if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,!d){h.error("SYSTEM","Restart guard tripped: session is dead, terminating",{sessionId:e.sessionDbId,pendingCount:l,restartsInWindow:e.restartGuard.restartsInWindow,windowMs:e.restartGuard.windowMs,maxRestarts:e.restartGuard.maxRestarts,consecutiveFailures:e.restartGuard.consecutiveFailuresSinceSuccess,maxConsecutiveFailures:e.restartGuard.maxConsecutiveFailures}),e.consecutiveRestarts=0,this.terminateSession(e.sessionDbId,"max_restarts_exceeded");return}h.info("SYSTEM","Pending work remains after generator exit, restarting with fresh AbortController",{sessionId:e.sessionDbId,pendingCount:l,attempt:e.consecutiveRestarts}),e.abortController=new AbortController,this.startSessionProcessor(e,"pending-work-restart"),this.broadcastProcessingStatus()}else e.restartGuard?.recordSuccess(),e.consecutiveRestarts=0,this.completionHandler.finalizeSession(e.sessionDbId),this.sessionManager.removeSessionImmediate(e.sessionDbId)})}static SESSION_TERMINATED_PATTERNS=["process aborted by user","processtransport","not ready for writing","session generator failed","claude code process"];isSessionTerminatedError(e){let n=(e instanceof Error?e.message:String(e)).toLowerCase();return t.SESSION_TERMINATED_PATTERNS.some(i=>n.includes(i))}async runFallbackForTerminatedSession(e,r){if(!e)return;let n=e.sessionDbId;if(!e.memorySessionId){let i=`fallback-${n}-${Date.now()}`;e.memorySessionId=i,this.dbManager.getSessionStore().updateMemorySessionId(n,i)}if(kc())try{await this.geminiAgent.startSession(e,this);return}catch(i){i instanceof Error?(h.warn("WORKER","Fallback Gemini failed, trying OpenRouter",{sessionId:n}),h.error("WORKER","Gemini fallback error detail",{sessionId:n},i)):h.error("WORKER","Gemini fallback failed with non-Error",{sessionId:n},new Error(String(i)))}if(Tc())try{await this.openRouterAgent.startSession(e,this);return}catch(i){i instanceof Error?h.error("WORKER","Fallback OpenRouter failed, will abandon messages",{sessionId:n},i):h.error("WORKER","Fallback OpenRouter failed with non-Error, will abandon messages",{sessionId:n},new Error(String(i)))}this.completionHandler.finalizeSession(n),this.sessionManager.removeSessionImmediate(n)}terminateSession(e,r){h.info("SYSTEM","Session terminated",{sessionId:e,reason:r}),this.completionHandler.finalizeSession(e),this.sessionManager.removeSessionImmediate(e)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(vS(),KO)),n=new r(this.dbManager.getSessionStore().db,3),i=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s,a=i.db.prepare(` +2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};gs();var DTe={},PTe="12.4.1";function ZW(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var pw=class t{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;completionHandler;corpusStore;searchRoutes=null;chromaMcpManager=null;transcriptWatcher=null;initializationComplete;resolveInitialization;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new gS,this.sessionManager=new bS(this.dbManager),this.sseBroadcaster=new SS,this.sdkAgent=new ex(this.dbManager,this.sessionManager),this.geminiAgent=new tx(this.dbManager,this.sessionManager),this.openRouterAgent=new ix(this.dbManager,this.sessionManager),this.paginationHelper=new sx(this.dbManager),this.settingsManager=new ox(this.dbManager),this.sessionEventBroadcaster=new dx(this.sseBroadcaster,this),this.completionHandler=new px(this.sessionManager,this.sessionEventBroadcaster,this.dbManager),this.corpusStore=new aw,vH({sessionManager:this.sessionManager,dbManager:this.dbManager,eventBroadcaster:this.sessionEventBroadcaster}),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Ku({name:"worker-search-proxy",version:PTe},{capabilities:{}}),this.server=new pS({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return od()&&Tc()?e="openrouter":sd()&&kc()&&(e="gemini"),{provider:e,authMethod:Z_(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){q4(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.registerRoutes(new ow),this.server.app.get("/api/context/inject",async(r,n,i)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){h.warn("SYSTEM","Context requested before initialization complete, returning empty"),n.status(200).json({content:[{type:"text",text:""}]});return}i()}),this.server.app.use("/api",async(r,n,i)=>{if(r.path==="/chroma/status"||r.path==="/health"||r.path==="/readiness"||r.path==="/version"){i();return}if(this.initializationCompleteFlag){i();return}let s=12e4,o=new Promise((a,c)=>setTimeout(()=>c(new Error("Database initialization timeout")),s));try{await Promise.race([this.initializationComplete,o]),i()}catch(a){a instanceof Error?h.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized`,{},a):h.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized with non-Error`,{},new Error(String(a))),n.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"});return}}),this.server.registerRoutes(new Zx(this.sseBroadcaster,this.dbManager,this.sessionManager));let e=new Wx(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this,this.completionHandler);this.server.registerRoutes(e),yH((r,n)=>e.ensureGeneratorRunning(r,n)),this.server.registerRoutes(new Gx(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new tw(this.settingsManager)),this.server.registerRoutes(new nw),this.server.registerRoutes(new iw(this.dbManager,"claude-mem"))}async start(){let e=un(),r=lI();await F4(),await this.server.listen(e,r),mL({pid:process.pid,port:e,startedAt:new Date().toISOString()}),jr().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),h.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(n=>{h.error("SYSTEM","Background initialization failed",{},n)})}async initializeBackground(){try{h.info("WORKER","Background initialization starting..."),await hL();let{ModeManager:e}=await Promise.resolve().then(()=>(fn(),aH)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(Jt(),h4)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(xt(),x4)),i=r.loadFromFile(n),s=i.CLAUDE_MEM_MODE;e.getInstance().loadMode(s),h.info("SYSTEM",`Mode loaded: ${s}`),(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&(h.info("WORKER","Checking for one-time Chroma migration..."),gL()),h.info("WORKER","Checking for one-time CWD remap..."),vL(),h.info("WORKER","Adopting merged worktrees (background)..."),OL({}).then(g=>{if(g)for(let v of g)(v.adoptedObservations>0||v.adoptedSummaries>0||v.chromaUpdates>0)&&h.info("SYSTEM","Merged worktrees adopted in background",v),v.errors.length>0&&h.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:v.repoPath,errors:v.errors})}).catch(g=>{h.error("WORKER","Worktree adoption failed (background)",{},g instanceof Error?g:new Error(String(g)))}),i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=li.getInstance(),h.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):h.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager"),h.info("WORKER","Initializing database manager..."),await this.dbManager.initialize();try{h.info("WORKER","Running startup GC for pending messages...");let{PendingMessageStore:g}=await Promise.resolve().then(()=>(vS(),KO)),y=new g(this.dbManager.getSessionStore().db,3).clearFailedOlderThan(10080*60*1e3);y>0&&h.info("QUEUE","Startup GC cleared old failed pending_messages rows",{cleared:y})}catch(g){h.warn("QUEUE","Startup GC for failed pending_messages rows failed",{},g instanceof Error?g:void 0)}h.info("WORKER","Initializing search services...");let a=new ux,c=new lx,u=new cx(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),a,c);this.searchRoutes=new Xx(u),this.server.registerRoutes(this.searchRoutes),h.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:l}=await Promise.resolve().then(()=>(nP(),iZ)),d=new l(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),p=new uw(this.dbManager.getSessionStore(),d,this.corpusStore),f=new lw(this.corpusStore);this.server.registerRoutes(new sw(this.corpusStore,p,f)),h.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),h.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(i),this.chromaMcpManager&&Xo.backfillAllProjects(this.dbManager.getSessionStore()).then(()=>{h.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(g=>{h.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},g)});let m=HW.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,u1.existsSync)(m),this.runMcpSelfCheck(m).catch(g=>{h.debug("WORKER","MCP self-check failed (non-fatal)",{error:g.message})});return}catch(e){h.error("SYSTEM","Background initialization failed",{},e instanceof Error?e:void 0)}}async runMcpSelfCheck(e){try{jr().assertCanSpawn("mcp server");let r=new Xu({command:process.execPath,args:[e],env:Object.fromEntries(Object.entries(Hn(process.env)).filter(([,o])=>o!==void 0))}),n=6e4,i=this.mcpClient.connect(r),s=new Promise((o,a)=>{setTimeout(()=>a(new Error("MCP connection timeout")),6e4)});await Promise.race([i,s]),h.info("WORKER","MCP loopback self-check connected successfully"),await r.close()}catch(r){h.warn("WORKER","MCP loopback self-check failed",{error:r instanceof Error?r.message:String(r)})}}async startTranscriptWatcher(e){if(!(e.CLAUDE_MEM_TRANSCRIPTS_ENABLED!=="false")){h.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let n=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||mx,i=ho(n);(0,u1.existsSync)(i)||(oZ(n),h.info("TRANSCRIPT","Created default transcript watch config",{configPath:i}));let s=sZ(n),o=ho(s.stateFile??hx);try{this.transcriptWatcher=new Fx(s,o),await this.transcriptWatcher.start()}catch(a){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,a instanceof Error?h.error("WORKER","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:i},a):h.error("WORKER","Failed to start transcript watcher with non-Error (continuing without Codex ingestion)",{configPath:i},new Error(String(a)));return}h.info("TRANSCRIPT","Transcript watcher started",{configPath:i,statePath:o,watches:s.watches.length})}getActiveAgent(){return od()&&Tc()?this.openRouterAgent:sd()&&kc()?this.geminiAgent:this.sdkAgent}startSessionProcessor(e,r){if(!e)return;let n=e.sessionDbId,i=this.getActiveAgent(),s=i.constructor.name;e.abortController.signal.aborted&&(h.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;h.info("SYSTEM",`Starting generator (${r}) using ${s}`,{sessionId:n}),e.lastGeneratorActivity=Date.now(),e.generatorPromise=i.startSession(e,this).catch(async c=>{let u=c?.message||"";if(["Claude executable not found","CLAUDE_CODE_PATH","ENOENT","spawn","Invalid API key","API_KEY_INVALID","API key expired","API key not valid","PERMISSION_DENIED","Gemini API error: 400","Gemini API error: 401","Gemini API error: 403","FOREIGN KEY constraint failed"].some(p=>u.includes(p))){o=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},h.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return h.warn("SDK","SDK resume failed, falling back to standalone processing",{sessionId:e.sessionDbId,project:e.project,reason:c instanceof Error?c.message:String(c)}),this.runFallbackForTerminatedSession(e,c);throw["aborted by user","No conversation found"].some(p=>u.includes(p))&&e.memorySessionId&&(h.warn("SDK","Detected stale resume failure, clearing memorySessionId for fresh start",{sessionId:e.sessionDbId,memorySessionId:e.memorySessionId,errorMessage:u}),this.dbManager.getSessionStore().updateMemorySessionId(e.sessionDbId,null),e.memorySessionId=null,e.forceInit=!0),h.error("SDK","Session generator failed",{sessionId:e.sessionDbId,project:e.project,provider:s},c),a=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},c}).finally(async()=>{let c=Vo(e.sessionDbId);if(c&&c.process.exitCode===null&&await Ko(c,5e3),e.generatorPromise=null,!a&&!o&&(this.lastAiInteraction={timestamp:Date.now(),success:!0,provider:s}),o){this.terminateSession(e.sessionDbId,"unrecoverable_error");return}let l=this.sessionManager.getPendingMessageStore().getPendingCount(e.sessionDbId);if(e.idleTimedOut&&(e.idleTimedOut=!1,l===0)){this.terminateSession(e.sessionDbId,"idle_timeout");return}if(l>0){e.restartGuard||(e.restartGuard=new ea);let d=e.restartGuard.recordRestart();if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,!d){h.error("SYSTEM","Restart guard tripped: session is dead, terminating",{sessionId:e.sessionDbId,pendingCount:l,restartsInWindow:e.restartGuard.restartsInWindow,windowMs:e.restartGuard.windowMs,maxRestarts:e.restartGuard.maxRestarts,consecutiveFailures:e.restartGuard.consecutiveFailuresSinceSuccess,maxConsecutiveFailures:e.restartGuard.maxConsecutiveFailures}),e.consecutiveRestarts=0,this.terminateSession(e.sessionDbId,"max_restarts_exceeded");return}h.info("SYSTEM","Pending work remains after generator exit, restarting with fresh AbortController",{sessionId:e.sessionDbId,pendingCount:l,attempt:e.consecutiveRestarts}),e.abortController=new AbortController,this.startSessionProcessor(e,"pending-work-restart"),this.broadcastProcessingStatus()}else e.restartGuard?.recordSuccess(),e.consecutiveRestarts=0,this.completionHandler.finalizeSession(e.sessionDbId),this.sessionManager.removeSessionImmediate(e.sessionDbId)})}static SESSION_TERMINATED_PATTERNS=["process aborted by user","processtransport","not ready for writing","session generator failed","claude code process"];isSessionTerminatedError(e){let n=(e instanceof Error?e.message:String(e)).toLowerCase();return t.SESSION_TERMINATED_PATTERNS.some(i=>n.includes(i))}async runFallbackForTerminatedSession(e,r){if(!e)return;let n=e.sessionDbId;if(!e.memorySessionId){let i=`fallback-${n}-${Date.now()}`;e.memorySessionId=i,this.dbManager.getSessionStore().updateMemorySessionId(n,i)}if(kc())try{await this.geminiAgent.startSession(e,this);return}catch(i){i instanceof Error?(h.warn("WORKER","Fallback Gemini failed, trying OpenRouter",{sessionId:n}),h.error("WORKER","Gemini fallback error detail",{sessionId:n},i)):h.error("WORKER","Gemini fallback failed with non-Error",{sessionId:n},new Error(String(i)))}if(Tc())try{await this.openRouterAgent.startSession(e,this);return}catch(i){i instanceof Error?h.error("WORKER","Fallback OpenRouter failed, will abandon messages",{sessionId:n},i):h.error("WORKER","Fallback OpenRouter failed with non-Error, will abandon messages",{sessionId:n},new Error(String(i)))}this.completionHandler.finalizeSession(n),this.sessionManager.removeSessionImmediate(n)}terminateSession(e,r){h.info("SYSTEM","Session terminated",{sessionId:e,reason:r}),this.completionHandler.finalizeSession(e),this.sessionManager.removeSessionImmediate(e)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(vS(),KO)),n=new r(this.dbManager.getSessionStore().db,3),i=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s,a=i.db.prepare(` SELECT id FROM sdk_sessions WHERE status = 'active' AND started_at_epoch < ? `).all(o);if(a.length>0){let l=a.map(f=>f.id),d=l.map(()=>"?").join(","),p=Date.now();try{i.db.prepare(`