claude-mem 12.2.2 → 12.3.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/package.json
CHANGED
package/plugin/package.json
CHANGED
|
@@ -194,7 +194,7 @@ ${f}`}let s=i.lineStart;for(let u=i.lineStart-1;u>=0;u--){let l=a[u].trim();if(l
|
|
|
194
194
|
${c}`}var vb=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"]),ij=new Set(["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","env",".env","target","vendor",".cache",".turbo","coverage",".nyc_output",".claude",".smart-file-read"]),aj=512*1024;async function*_b(t,e,r=20,n){if(r<=0)return;let o;try{o=await(0,Zn.readdir)(t,{withFileTypes:!0})}catch{return}for(let i of o){if(i.name.startsWith(".")&&i.name!=="."||ij.has(i.name))continue;let a=(0,Ai.join)(t,i.name);if(i.isDirectory())yield*_b(a,e,r-1,n);else if(i.isFile()){let s=i.name.slice(i.name.lastIndexOf("."));(vb.has(s)||n&&n.has(s))&&(yield a)}}}async function sj(t){try{let e=await(0,Zn.stat)(t);if(e.size>aj||e.size===0)return null;let r=await(0,Zn.readFile)(t,"utf-8");return r.slice(0,1e3).includes("\0")?null:r}catch{return null}}async function yb(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=Mi(a),c=new Set;for(let x of Object.values(s.grammars))for(let b of x.extensions)vb.has(b)||c.add(b);let u=[];for await(let x of _b(t,t,20,c.size>0?c:void 0)){if(r.filePattern&&!(0,Ai.relative)(t,x).toLowerCase().includes(r.filePattern.toLowerCase()))continue;let b=await sj(x);b&&u.push({absolutePath:x,relativePath:(0,Ai.relative)(t,x),content:b})}let l=mb(u,a),d=[],p=[],f=0;for(let[x,b]of l){f+=cj(b);let T=rc(x.toLowerCase(),i)>0,Ve=[],We=(Fn,qr)=>{for(let ye of Fn){let rr=0,mt="",qn=rc(ye.name.toLowerCase(),i);qn>0&&(rr+=qn*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&&(T=!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(b.symbols),T&&(d.push(b),p.push(...Ve))}p.sort((x,b)=>{let N=rc(x.symbolName.toLowerCase(),i);return rc(b.symbolName.toLowerCase(),i)-N});let h=p.slice(0,n),g=new Set(h.map(x=>x.filePath)),y=d.filter(x=>g.has(x.filePath)).slice(0,n),S=y.reduce((x,b)=>x+b.foldedTokenEstimate,0);return{foldedFiles:y,matchingSymbols:h,totalFilesScanned:u.length,totalSymbolsFound:f,tokenEstimate:S}}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 cj(t){let e=t.symbols.length;for(let r of t.symbols)r.children&&(e+=r.children.length);return e}function $b(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(`
|
|
195
195
|
`);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(`
|
|
196
196
|
`).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(Un(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(`
|
|
197
|
-
`)}var gm=require("node:fs/promises"),Sb=require("node:fs"),Fr=require("node:path"),kb=require("node:url"),_j={},uj="12.
|
|
197
|
+
`)}var gm=require("node:fs/promises"),Sb=require("node:fs"),Fr=require("node:path"),kb=require("node:url"),_j={},uj="12.3.0";console.log=(...t)=>{E.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var wb=!1,Eb=(()=>{if(typeof __dirname<"u")return __dirname;try{return(0,Fr.dirname)((0,kb.fileURLToPath)(_j.url))}catch{return wb=!0,process.cwd()}})(),vm=(0,Fr.resolve)(Eb,"worker-service.cjs");function lj(){wb&&((0,Sb.existsSync)(vm)||E.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:vm,mcpServerDir:Eb}))}var bb={search:"/api/search",timeline:"/api/timeline"};async function hm(t,e){E.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:t,params:e});try{let r=new URLSearchParams;for(let[a,s]of Object.entries(e))s!=null&&r.append(a,String(s));let n=`${t}?${r}`,o=await Xs(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return E.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),i}catch(r){return E.error("SYSTEM","\u2190 Worker API error",{endpoint:t},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function Ln(t,e){E.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{let r=await Xs(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 E.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}catch(r){return E.error("HTTP","Worker API error (POST)",{endpoint:t},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function dj(){try{return(await Xs("/api/health")).ok}catch(t){return E.debug("SYSTEM","Worker health check failed",{},t),!1}}async function pj(){if(await dj())return!0;E.warn("SYSTEM","Worker not available, attempting auto-start for MCP client"),lj();try{let t=Yf(),e=await rb(t,vm);return e||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 E.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),!1}}var Ib=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
|
|
198
198
|
1. search(query) \u2192 Get index with IDs (~50-100 tokens/result)
|
|
199
199
|
2. timeline(anchor=ID) \u2192 Get context around interesting results
|
|
200
200
|
3. get_observations([IDs]) \u2192 Fetch full details ONLY for filtered IDs
|
|
@@ -1082,7 +1082,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
1082
1082
|
SELECT cwd FROM pending_messages
|
|
1083
1083
|
WHERE cwd IS NOT NULL AND cwd != ''
|
|
1084
1084
|
GROUP BY cwd
|
|
1085
|
-
`).all();for(let{cwd:u}of c){let l=MD(u);l&&i.add(l)}}finally{s?.close()}if(i.size===0)return y.debug("SYSTEM","Worktree adoption found no known parent repos"),n;for(let o of i)try{let a=await mk({repoPath:o,dataDirectory:e,dryRun:t.dryRun});n.push(a)}catch(a){y.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return n}var W6=Ie(Cv(),1),_$=Ie(require("fs"),1),Lp=Ie(require("path"),1);var A6=["search","context","summarize","import","export"],N6=["workflow","search_params","examples","all"];Q();var g$=Ie(Cv(),1),U6=Ie(L6(),1),F6=Ie(require("path"),1);It();Q();function v$(t){let e=[];e.push(g$.default.json({limit:"50mb"})),e.push((0,U6.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","Authorization","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(f=>i.path.endsWith(f)),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);y.debug("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let m=s.send.bind(s);s.send=function(f){let h=Date.now()-l;return y.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${h}ms`}),m(f)},o()});let r=vn(),n=F6.default.join(r,"plugin","ui");return e.push(g$.default.static(n)),e}function zp(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")){y.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 y$(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=${y.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}Q();var xn=class extends Error{constructor(r,n=500,i,s){super(r);this.statusCode=n;this.code=i;this.details=s;this.name="AppError"}statusCode;code;details};function q6(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var H6=(t,e,r,n)=>{let i=t instanceof xn?t.statusCode:500;y.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof xn?t.code:void 0},t);let s=q6(t.name||"Error",t.message,t instanceof xn?t.code:void 0,t instanceof xn?t.details:void 0);r.status(i).json(s)};function Z6(t,e){e.status(404).json(q6("NotFound",`Cannot ${t.method} ${t.path}`))}var B6="12.
|
|
1085
|
+
`).all();for(let{cwd:u}of c){let l=MD(u);l&&i.add(l)}}finally{s?.close()}if(i.size===0)return y.debug("SYSTEM","Worktree adoption found no known parent repos"),n;for(let o of i)try{let a=await mk({repoPath:o,dataDirectory:e,dryRun:t.dryRun});n.push(a)}catch(a){y.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return n}var W6=Ie(Cv(),1),_$=Ie(require("fs"),1),Lp=Ie(require("path"),1);var A6=["search","context","summarize","import","export"],N6=["workflow","search_params","examples","all"];Q();var g$=Ie(Cv(),1),U6=Ie(L6(),1),F6=Ie(require("path"),1);It();Q();function v$(t){let e=[];e.push(g$.default.json({limit:"50mb"})),e.push((0,U6.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","Authorization","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(f=>i.path.endsWith(f)),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);y.debug("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let m=s.send.bind(s);s.send=function(f){let h=Date.now()-l;return y.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${h}ms`}),m(f)},o()});let r=vn(),n=F6.default.join(r,"plugin","ui");return e.push(g$.default.static(n)),e}function zp(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")){y.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 y$(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=${y.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}Q();var xn=class extends Error{constructor(r,n=500,i,s){super(r);this.statusCode=n;this.code=i;this.details=s;this.name="AppError"}statusCode;code;details};function q6(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var H6=(t,e,r,n)=>{let i=t instanceof xn?t.statusCode:500;y.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof xn?t.code:void 0},t);let s=q6(t.name||"Error",t.message,t instanceof xn?t.code:void 0,t instanceof xn?t.details:void 0);r.status(i).json(s)};function Z6(t,e){e.status(404).json(q6("NotFound",`Cannot ${t.method} ${t.path}`))}var B6="12.3.0",Pv=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,W6.default)(),this.setupMiddleware(),this.setupCoreRoutes()}getHttpServer(){return this.server}async listen(e,r){return new Promise((n,i)=>{this.server=this.app.listen(e,r,()=>{y.info("SYSTEM","HTTP server started",{host:r,port:e,pid:process.pid}),n()}),this.server.on("error",i)})}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,y.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(Z6),this.app.use(H6)}setupMiddleware(){v$(y$).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:B6,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:B6})}),this.app.get("/api/instructions",async(e,r)=>{let n=e.query.topic||"all",i=e.query.operation;if(n&&!N6.includes(n))return r.status(400).json({error:"Invalid topic"});try{let s;if(i){if(!A6.includes(i))return r.status(400).json({error:"Invalid operation"});let o=Lp.default.resolve(__dirname,"../skills/mem-search/operations"),a=Lp.default.resolve(o,`${i}.md`);if(!a.startsWith(o+Lp.default.sep))return r.status(400).json({error:"Invalid request"});s=await _$.promises.readFile(a,"utf-8")}else{let o=Lp.default.join(__dirname,"../skills/mem-search/SKILL.md"),a=await _$.promises.readFile(o,"utf-8");s=this.extractInstructionSection(a,n)}r.json({content:[{type:"text",text:s}]})}catch{r.status(404).json({error:"Instruction not found"})}}),this.app.post("/api/admin/restart",zp,async(e,r)=>{r.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(y.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",zp,async(e,r)=>{r.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(y.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",zp,(e,r)=>{let o=bt().getRegistry().getAll().map(f=>({id:f.id,pid:f.pid,type:f.type,status:Nn(f.pid)?"alive":"dead",startedAt:f.startedAt})),a=o.filter(f=>f.status==="dead").map(f=>f.pid),c=!Object.keys(process.env).some(f=>BE.has(f)||ZE.some(h=>f.startsWith(h))),u=Date.now()-this.startTime,l=Math.floor(u/1e3),d=Math.floor(l/3600),p=Math.floor(l%3600/60),m=d>0?`${d}h ${p}m`:`${p}m`;r.json({supervisor:{running:!0,pid:process.pid,uptime:m},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 At=Ie(require("path"),1),Fp=require("os"),Jt=require("fs"),K6=require("child_process"),J6=require("util");Q();Or();It();var ni=require("fs"),Up=require("path");Q();function G6(t){try{return(0,ni.existsSync)(t)?JSON.parse((0,ni.readFileSync)(t,"utf-8")):{}}catch(e){return y.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function V6(t,e){let r=(0,Up.join)(t,"..");(0,ni.mkdirSync)(r,{recursive:!0}),(0,ni.writeFileSync)(t,JSON.stringify(e,null,2))}function b$(t,e){let r=(0,Up.join)(t,".cursor","rules"),n=(0,Up.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,ni.mkdirSync)(r,{recursive:!0});let s=`---
|
|
1086
1086
|
alwaysApply: true
|
|
1087
1087
|
description: "Claude-mem context from past sessions (auto-updated)"
|
|
1088
1088
|
---
|
|
@@ -1488,7 +1488,7 @@ ${n.prompts.header_memory_continued}`}var Fle=300*1e3,hF=900*1e3;var Uv=class{db
|
|
|
1488
1488
|
|
|
1489
1489
|
`;y.debug("WORKER","SSE broadcast sent",{eventType:e.type,clients:this.sseClients.size});for(let i of this.sseClients)i.write(n)}getClientCount(){return this.sseClients.size}sendToClient(e,r){let n=`data: ${JSON.stringify(r)}
|
|
1490
1490
|
|
|
1491
|
-
`;e.write(n)}};var wI=require("child_process"),e8=require("os"),t8=Ie(require("path"),1);Q();Yt();It();rn();var $$=["429","500","502","503","ECONNREFUSED","ETIMEDOUT","fetch failed"];Q();Q();rn();function _F(t,e){let r=[],n=/<observation>([\s\S]*?)<\/observation>/g,i;for(;(i=n.exec(t))!==null;){let s=i[1],o=Dn(s,"type"),a=Dn(s,"title"),c=Dn(s,"subtitle"),u=Dn(s,"narrative"),l=Vp(s,"facts","fact"),d=Vp(s,"concepts","concept"),p=Vp(s,"files_read","file"),m=Vp(s,"files_modified","file"),h=He.getInstance().getActiveMode().observation_types.map(b=>b.id),g=h[0],v=g;o?h.includes(o.trim())?v=o.trim():y.error("PARSER",`Invalid observation type: ${o}, using "${g}"`,{correlationId:e}):y.error("PARSER",`Observation missing type field, using "${g}"`,{correlationId:e});let _=d.filter(b=>b!==v);if(_.length!==d.length&&y.debug("PARSER","Removed observation type from concepts array",{correlationId:e,type:v,originalConcepts:d,cleanedConcepts:_}),!a&&!u&&l.length===0&&_.length===0){y.warn("PARSER","Skipping empty observation (all content fields null)",{correlationId:e,type:v});continue}r.push({type:v,title:a,subtitle:c,facts:l,narrative:u,concepts:_,files_read:p,files_modified:m})}return r}function bF(t,e,r=!1){let i=/<skip_summary\s+reason="([^"]+)"\s*\/>/.exec(t);if(i)return y.info("PARSER","Summary skipped",{sessionId:e,reason:i[1]}),null;let o=/<summary>([\s\S]*?)<\/summary>/.exec(t);if(!o){if(
|
|
1491
|
+
`;e.write(n)}};var wI=require("child_process"),e8=require("os"),t8=Ie(require("path"),1);Q();Yt();It();rn();var $$=["429","500","502","503","ECONNREFUSED","ETIMEDOUT","fetch failed"];Q();Q();rn();function _F(t,e){let r=[],n=/<observation>([\s\S]*?)<\/observation>/g,i;for(;(i=n.exec(t))!==null;){let s=i[1],o=Dn(s,"type"),a=Dn(s,"title"),c=Dn(s,"subtitle"),u=Dn(s,"narrative"),l=Vp(s,"facts","fact"),d=Vp(s,"concepts","concept"),p=Vp(s,"files_read","file"),m=Vp(s,"files_modified","file"),h=He.getInstance().getActiveMode().observation_types.map(b=>b.id),g=h[0],v=g;o?h.includes(o.trim())?v=o.trim():y.error("PARSER",`Invalid observation type: ${o}, using "${g}"`,{correlationId:e}):y.error("PARSER",`Observation missing type field, using "${g}"`,{correlationId:e});let _=d.filter(b=>b!==v);if(_.length!==d.length&&y.debug("PARSER","Removed observation type from concepts array",{correlationId:e,type:v,originalConcepts:d,cleanedConcepts:_}),!a&&!u&&l.length===0&&_.length===0){y.warn("PARSER","Skipping empty observation (all content fields null)",{correlationId:e,type:v});continue}r.push({type:v,title:a,subtitle:c,facts:l,narrative:u,concepts:_,files_read:p,files_modified:m})}return r}function bF(t,e,r=!1){let i=/<skip_summary\s+reason="([^"]+)"\s*\/>/.exec(t);if(i)return y.info("PARSER","Summary skipped",{sessionId:e,reason:i[1]}),null;let o=/<summary>([\s\S]*?)<\/summary>/.exec(t);if(!o){if(r&&/<observation>/.test(t)){let f=yF(t,e);if(f)return f;y.warn("PARSER","Summary response contained <observation> tags instead of <summary> \u2014 coercion failed, no usable content",{sessionId:e})}return null}let a=o[1],c=Dn(a,"request"),u=Dn(a,"investigated"),l=Dn(a,"learned"),d=Dn(a,"completed"),p=Dn(a,"next_steps"),m=Dn(a,"notes");if(!c&&!u&&!l&&!d&&!p){if(r&&/<observation>/.test(t)){let f=yF(t,e);if(f)return y.warn("PARSER","Empty <summary> match rejected \u2014 coerced from <observation> fallback (#1633)",{sessionId:e}),f}return y.warn("PARSER","Summary match has no sub-tags \u2014 skipping false positive",{sessionId:e}),null}return{request:c,investigated:u,learned:l,completed:d,next_steps:p,notes:m}}function yF(t,e){let r=/<observation>([\s\S]*?)<\/observation>/g,n,i=0;for(;(n=r.exec(t))!==null;){let s=n[1],o=Dn(s,"title"),a=Dn(s,"subtitle"),c=Dn(s,"narrative"),u=Vp(s,"facts","fact");if(o||c||u.length>0){let l=o||a||null,d=c||null,p=u.length>0?u.join("; "):null,m=o?`${o}${a?" \u2014 "+a:""}`:null,f=null;return y.warn("PARSER","Coerced <observation> response into <summary> to prevent retry loop (#1633)",{sessionId:e,blockIndex:i,hasTitle:!!o,hasNarrative:!!c,factCount:u.length}),{request:l,investigated:d,learned:p,completed:m,next_steps:f,notes:null}}i++}return null}function Dn(t,e){let n=new RegExp(`<${e}>([\\s\\S]*?)</${e}>`).exec(t);if(!n)return null;let i=n[1].trim();return i===""?null:i}function Vp(t,e,r){let n=[],s=new RegExp(`<${e}>([\\s\\S]*?)</${e}>`).exec(t);if(!s)return n;let o=s[1],a=new RegExp(`<${r}>([\\s\\S]*?)</${r}>`,"g"),c;for(;(c=a.exec(o))!==null;){let u=c[1].trim();u&&n.push(u)}return n}var Ri=require("fs"),Bt=Ie(require("path"),1),xF=Ie(require("os"),1);Q();Ls();Yt();Or();var wF=Bt.default.join(xF.default.homedir(),".claude-mem","settings.json"),EF="CLAUDE.md",kF="CLAUDE.local.md";function TF(t){return(t??ge.loadFromFile(wF)).CLAUDE_MEM_FOLDER_USE_LOCAL_MD==="true"?kF:EF}function qle(t){let e=t.split(Bt.default.sep).filter(r=>r&&r!=="."&&r!=="..");for(let r=1;r<e.length;r++)if(e[r]===e[r-1])return!0;return!1}function Hle(t,e){if(!t||!t.trim()||t.startsWith("~")||t.startsWith("http://")||t.startsWith("https://")||t.includes(" ")||t.includes("#"))return!1;if(e){let r=Bt.default.isAbsolute(t)?t:Bt.default.resolve(e,t),n=Bt.default.resolve(e);if(!r.startsWith(n+Bt.default.sep)&&r!==n||qle(r))return!1}return!0}function R$(t,e){let r="<claude-mem-context>",n="</claude-mem-context>";if(!t)return`${r}
|
|
1492
1492
|
${e}
|
|
1493
1493
|
${n}`;let i=t.indexOf(r),s=t.indexOf(n);return i!==-1&&s!==-1?t.substring(0,i)+`${r}
|
|
1494
1494
|
${e}
|
|
@@ -1684,7 +1684,7 @@ ${e}`,o=R$(i,s),a=`${t}.tmp`;try{(0,ji.writeFileSync)(a,o),(0,ji.renameSync)(a,t
|
|
|
1684
1684
|
`);sr(Ki);let i=this.findClaudeExecutable(),s=An(Xd()),o=bm({prompt:n,options:{model:this.getModelId(),cwd:Ki,disallowedTools:A5,pathToClaudeCodeExecutable:i,env:s}}),a;try{for await(let c of o)c.session_id&&(a=c.session_id),c.type==="result"&&y.info("WORKER",`Knowledge agent primed for corpus "${e.name}"`)}catch(c){if(a)y.debug("WORKER",`SDK process exited after priming corpus "${e.name}" \u2014 session captured, continuing`,{},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;y.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){sr(Ki);let n=this.findClaudeExecutable(),i=An(Xd()),s=bm({prompt:r,options:{model:this.getModelId(),resume:e.session_id,cwd:Ki,disallowedTools:A5,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)y.debug("WORKER","SDK process exited after query \u2014 answer captured, continuing",{},c);else throw c}return{answer:o,session_id:a}}getModelId(){return ge.loadFromFile(pt).CLAUDE_MEM_MODEL}findClaudeExecutable(){let e=ge.loadFromFile(pt);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,dR.execSync)("where claude.cmd",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}),"claude.cmd"}catch{}try{let r=(0,dR.execSync)(process.platform==="win32"?"where claude":"which claude",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}).trim().split(`
|
|
1685
1685
|
`)[0].trim();if(r)return r}catch(r){y.debug("WORKER","Claude executable auto-detection failed",{},r)}throw new Error(`Claude executable not found. Please either:
|
|
1686
1686
|
1. Add "claude" to your system PATH, or
|
|
1687
|
-
2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};var _we={},hwe="12.2.2";function u3(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var $_=class{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;corpusStore;searchRoutes=null;chromaMcpManager=null;transcriptWatcher=null;initializationComplete;resolveInitialization;stopOrphanReaper=null;staleSessionReaperInterval=null;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new Dv,this.sessionManager=new Uv(this.dbManager),this.sseBroadcaster=new Fv,this.sdkAgent=new vy(this.dbManager,this.sessionManager),this.geminiAgent=new yy(this.dbManager,this.sessionManager),this.openRouterAgent=new Sy(this.dbManager,this.sessionManager),this.paginationHelper=new xy(this.dbManager),this.settingsManager=new wy(this.dbManager),this.sessionEventBroadcaster=new $y(this.sseBroadcaster,this),this.corpusStore=new x_,this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new zc({name:"worker-search-proxy",version:hwe},{capabilities:{}}),this.server=new Pv({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return Ju()&&za()?e="openrouter":Ku()&&ja()&&(e="gemini"),{provider:e,authMethod:cg(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){nD(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.app.get("/api/context/inject",async(e,r,n)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){y.warn("SYSTEM","Context requested before initialization complete, returning empty"),r.status(200).json({content:[{type:"text",text:""}]});return}n()}),this.server.app.use("/api",async(e,r,n)=>{if(this.initializationCompleteFlag){n();return}let i=3e4,s=new Promise((o,a)=>setTimeout(()=>a(new Error("Database initialization timeout")),i));try{await Promise.race([this.initializationComplete,s]),n()}catch(o){y.error("HTTP",`Request to ${e.method} ${e.path} rejected \u2014 DB not initialized`,{},o),r.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"})}}),this.server.registerRoutes(new i_(this.sseBroadcaster,this.dbManager,this.sessionManager)),this.server.registerRoutes(new c_(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this)),this.server.registerRoutes(new u_(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new v_(this.settingsManager)),this.server.registerRoutes(new __),this.server.registerRoutes(new b_(this.dbManager,"claude-mem"))}async start(){let e=Qr(),r=UE();await tD(),await this.server.listen(e,r),_D({pid:process.pid,port:e,startedAt:new Date().toISOString()}),bt().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),y.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(n=>{y.error("SYSTEM","Background initialization failed",{},n)})}async initializeBackground(){try{await bD();let{ModeManager:e}=await Promise.resolve().then(()=>(rn(),vF)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(Yt(),PM)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(It(),LM)),i=r.loadFromFile(n);(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&SD(),xD();try{let k=await DD({});for(let $ of k)($.adoptedObservations>0||$.adoptedSummaries>0||$.chromaUpdates>0)&&y.info("SYSTEM","Merged worktrees adopted on startup",$),$.errors.length>0&&y.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:$.repoPath,errors:$.errors})}catch(k){y.error("SYSTEM","Worktree adoption failed (non-fatal)",{},k)}i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Ji.getInstance(),y.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):y.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager");let o=i.CLAUDE_MEM_MODE;e.getInstance().loadMode(o),y.info("SYSTEM",`Mode loaded: ${o}`),await this.dbManager.initialize();let{PendingMessageStore:a}=await Promise.resolve().then(()=>(Ra(),Su)),u=new a(this.dbManager.getSessionStore().db,3).resetStaleProcessingMessages(0);u>0&&y.info("SYSTEM",`Reset ${u} stale processing messages to pending`);let l=new ky,d=new Ty,p=new Ey(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),l,d);this.searchRoutes=new f_(p),this.server.registerRoutes(this.searchRoutes),y.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:m}=await Promise.resolve().then(()=>(RI(),n8)),f=new m(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),h=new E_(this.dbManager.getSessionStore(),f,this.corpusStore),g=new k_(this.corpusStore);this.server.registerRoutes(new S_(this.corpusStore,h,g)),y.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),y.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(i),this.chromaMcpManager&&_o.backfillAllProjects().then(()=>{y.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(k=>{y.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},k)});let v=c3.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,ER.existsSync)(v),bt().assertCanSpawn("mcp server");let _=new Fc({command:"node",args:[v],env:An(process.env)}),b=3e5,S=this.mcpClient.connect(_),x,w=new Promise((k,$)=>{x=setTimeout(()=>$(new Error("MCP connection timeout after 5 minutes")),b)});try{await Promise.race([S,w])}catch(k){clearTimeout(x),y.warn("WORKER","MCP loopback self-check failed, cleaning up subprocess",{error:k instanceof Error?k.message:String(k)});try{await _.close()}catch{}y.info("WORKER","Bundled MCP server remains available for external stdio clients",{path:v});return}clearTimeout(x);let E=_._process;E?.pid&&(bt().registerProcess("mcp-server",{pid:E.pid,type:"mcp",startedAt:new Date().toISOString()},E),E.once("exit",()=>{bt().unregisterProcess("mcp-server")})),y.success("WORKER","MCP loopback self-check connected"),this.stopOrphanReaper=fF(()=>{let k=new Set;for(let[$]of this.sessionManager.sessions)k.add($);return k}),y.info("SYSTEM","Started orphan reaper (runs every 30 seconds)"),this.staleSessionReaperInterval=setInterval(async()=>{try{let k=await this.sessionManager.reapStaleSessions();k>0&&y.info("SYSTEM",`Reaped ${k} stale sessions`)}catch(k){y.error("SYSTEM","Stale session reaper error",{error:k instanceof Error?k.message:String(k)})}},120*1e3),this.processPendingQueues(50).then(k=>{k.sessionsStarted>0&&y.info("SYSTEM",`Auto-recovered ${k.sessionsStarted} sessions with pending work`,{totalPending:k.totalPendingSessions,started:k.sessionsStarted,sessionIds:k.startedSessionIds})}).catch(k=>{y.error("SYSTEM","Auto-recovery of pending queues failed",{},k)})}catch(e){throw y.error("SYSTEM","Background initialization failed",{},e),e}}async startTranscriptWatcher(e){if(!(e.CLAUDE_MEM_TRANSCRIPTS_ENABLED!=="false")){y.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let n=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||Ry,i=Ks(n);try{(0,ER.existsSync)(i)||(s8(n),y.info("TRANSCRIPT","Created default transcript watch config",{configPath:i}));let s=i8(n),o=Ks(s.stateFile??Oy);this.transcriptWatcher=new t_(s,o),await this.transcriptWatcher.start(),y.info("TRANSCRIPT","Transcript watcher started",{configPath:i,statePath:o,watches:s.watches.length})}catch(s){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,y.error("TRANSCRIPT","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:i},s)}}getActiveAgent(){return Ju()&&za()?this.openRouterAgent:Ku()&&ja()?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&&(y.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;y.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(d=>u.includes(d))){o=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},y.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return y.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(u.includes("aborted by user")||u.includes("No conversation found"))&&e.memorySessionId&&(y.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),y.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=as(e.sessionDbId);if(c&&c.process.exitCode===null&&await Ro(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}let d=3;if(l>0){if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,e.consecutiveRestarts>d){y.error("SYSTEM","Exceeded max pending-work restarts, stopping to prevent infinite loop",{sessionId:e.sessionDbId,pendingCount:l,consecutiveRestarts:e.consecutiveRestarts}),e.consecutiveRestarts=0,this.terminateSession(e.sessionDbId,"max_restarts_exceeded");return}y.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.consecutiveRestarts=0,this.sessionManager.removeSessionImmediate(e.sessionDbId)})}isSessionTerminatedError(e){let n=(e instanceof Error?e.message:String(e)).toLowerCase();return n.includes("process aborted by user")||n.includes("processtransport")||n.includes("not ready for writing")||n.includes("session generator failed")||n.includes("claude code process")}async runFallbackForTerminatedSession(e,r){if(!e)return;let n=e.sessionDbId;if(!e.memorySessionId){let o=`fallback-${n}-${Date.now()}`;e.memorySessionId=o,this.dbManager.getSessionStore().updateMemorySessionId(n,o)}if(ja())try{await this.geminiAgent.startSession(e,this);return}catch(o){y.warn("SDK","Fallback Gemini failed, trying OpenRouter",{sessionId:n,error:o instanceof Error?o.message:String(o)})}if(za())try{await this.openRouterAgent.startSession(e,this);return}catch(o){y.warn("SDK","Fallback OpenRouter failed",{sessionId:n,error:o instanceof Error?o.message:String(o)})}let s=this.sessionManager.getPendingMessageStore().markAllSessionMessagesAbandoned(n);s>0&&y.warn("SDK","No fallback available; marked pending messages abandoned",{sessionId:n,abandoned:s}),this.sessionManager.removeSessionImmediate(n),this.sessionEventBroadcaster.broadcastSessionCompleted(n)}terminateSession(e,r){let i=this.sessionManager.getPendingMessageStore().markAllSessionMessagesAbandoned(e);y.info("SYSTEM","Session terminated",{sessionId:e,reason:r,abandonedMessages:i}),this.sessionManager.removeSessionImmediate(e)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(Ra(),Su)),n=new r(this.dbManager.getSessionStore().db,3),i=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s;try{let u=i.db.prepare(`
|
|
1687
|
+
2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};var _we={},hwe="12.3.0";function u3(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var $_=class{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;corpusStore;searchRoutes=null;chromaMcpManager=null;transcriptWatcher=null;initializationComplete;resolveInitialization;stopOrphanReaper=null;staleSessionReaperInterval=null;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new Dv,this.sessionManager=new Uv(this.dbManager),this.sseBroadcaster=new Fv,this.sdkAgent=new vy(this.dbManager,this.sessionManager),this.geminiAgent=new yy(this.dbManager,this.sessionManager),this.openRouterAgent=new Sy(this.dbManager,this.sessionManager),this.paginationHelper=new xy(this.dbManager),this.settingsManager=new wy(this.dbManager),this.sessionEventBroadcaster=new $y(this.sseBroadcaster,this),this.corpusStore=new x_,this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new zc({name:"worker-search-proxy",version:hwe},{capabilities:{}}),this.server=new Pv({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return Ju()&&za()?e="openrouter":Ku()&&ja()&&(e="gemini"),{provider:e,authMethod:cg(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){nD(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.app.get("/api/context/inject",async(e,r,n)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){y.warn("SYSTEM","Context requested before initialization complete, returning empty"),r.status(200).json({content:[{type:"text",text:""}]});return}n()}),this.server.app.use("/api",async(e,r,n)=>{if(this.initializationCompleteFlag){n();return}let i=3e4,s=new Promise((o,a)=>setTimeout(()=>a(new Error("Database initialization timeout")),i));try{await Promise.race([this.initializationComplete,s]),n()}catch(o){y.error("HTTP",`Request to ${e.method} ${e.path} rejected \u2014 DB not initialized`,{},o),r.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"})}}),this.server.registerRoutes(new i_(this.sseBroadcaster,this.dbManager,this.sessionManager)),this.server.registerRoutes(new c_(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this)),this.server.registerRoutes(new u_(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new v_(this.settingsManager)),this.server.registerRoutes(new __),this.server.registerRoutes(new b_(this.dbManager,"claude-mem"))}async start(){let e=Qr(),r=UE();await tD(),await this.server.listen(e,r),_D({pid:process.pid,port:e,startedAt:new Date().toISOString()}),bt().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),y.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(n=>{y.error("SYSTEM","Background initialization failed",{},n)})}async initializeBackground(){try{await bD();let{ModeManager:e}=await Promise.resolve().then(()=>(rn(),vF)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(Yt(),PM)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(It(),LM)),i=r.loadFromFile(n);(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&SD(),xD();try{let k=await DD({});for(let $ of k)($.adoptedObservations>0||$.adoptedSummaries>0||$.chromaUpdates>0)&&y.info("SYSTEM","Merged worktrees adopted on startup",$),$.errors.length>0&&y.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:$.repoPath,errors:$.errors})}catch(k){y.error("SYSTEM","Worktree adoption failed (non-fatal)",{},k)}i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Ji.getInstance(),y.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):y.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager");let o=i.CLAUDE_MEM_MODE;e.getInstance().loadMode(o),y.info("SYSTEM",`Mode loaded: ${o}`),await this.dbManager.initialize();let{PendingMessageStore:a}=await Promise.resolve().then(()=>(Ra(),Su)),u=new a(this.dbManager.getSessionStore().db,3).resetStaleProcessingMessages(0);u>0&&y.info("SYSTEM",`Reset ${u} stale processing messages to pending`);let l=new ky,d=new Ty,p=new Ey(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),l,d);this.searchRoutes=new f_(p),this.server.registerRoutes(this.searchRoutes),y.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:m}=await Promise.resolve().then(()=>(RI(),n8)),f=new m(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),h=new E_(this.dbManager.getSessionStore(),f,this.corpusStore),g=new k_(this.corpusStore);this.server.registerRoutes(new S_(this.corpusStore,h,g)),y.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),y.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(i),this.chromaMcpManager&&_o.backfillAllProjects().then(()=>{y.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(k=>{y.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},k)});let v=c3.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,ER.existsSync)(v),bt().assertCanSpawn("mcp server");let _=new Fc({command:"node",args:[v],env:An(process.env)}),b=3e5,S=this.mcpClient.connect(_),x,w=new Promise((k,$)=>{x=setTimeout(()=>$(new Error("MCP connection timeout after 5 minutes")),b)});try{await Promise.race([S,w])}catch(k){clearTimeout(x),y.warn("WORKER","MCP loopback self-check failed, cleaning up subprocess",{error:k instanceof Error?k.message:String(k)});try{await _.close()}catch{}y.info("WORKER","Bundled MCP server remains available for external stdio clients",{path:v});return}clearTimeout(x);let E=_._process;E?.pid&&(bt().registerProcess("mcp-server",{pid:E.pid,type:"mcp",startedAt:new Date().toISOString()},E),E.once("exit",()=>{bt().unregisterProcess("mcp-server")})),y.success("WORKER","MCP loopback self-check connected"),this.stopOrphanReaper=fF(()=>{let k=new Set;for(let[$]of this.sessionManager.sessions)k.add($);return k}),y.info("SYSTEM","Started orphan reaper (runs every 30 seconds)"),this.staleSessionReaperInterval=setInterval(async()=>{try{let k=await this.sessionManager.reapStaleSessions();k>0&&y.info("SYSTEM",`Reaped ${k} stale sessions`)}catch(k){y.error("SYSTEM","Stale session reaper error",{error:k instanceof Error?k.message:String(k)})}},120*1e3),this.processPendingQueues(50).then(k=>{k.sessionsStarted>0&&y.info("SYSTEM",`Auto-recovered ${k.sessionsStarted} sessions with pending work`,{totalPending:k.totalPendingSessions,started:k.sessionsStarted,sessionIds:k.startedSessionIds})}).catch(k=>{y.error("SYSTEM","Auto-recovery of pending queues failed",{},k)})}catch(e){throw y.error("SYSTEM","Background initialization failed",{},e),e}}async startTranscriptWatcher(e){if(!(e.CLAUDE_MEM_TRANSCRIPTS_ENABLED!=="false")){y.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let n=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||Ry,i=Ks(n);try{(0,ER.existsSync)(i)||(s8(n),y.info("TRANSCRIPT","Created default transcript watch config",{configPath:i}));let s=i8(n),o=Ks(s.stateFile??Oy);this.transcriptWatcher=new t_(s,o),await this.transcriptWatcher.start(),y.info("TRANSCRIPT","Transcript watcher started",{configPath:i,statePath:o,watches:s.watches.length})}catch(s){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,y.error("TRANSCRIPT","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:i},s)}}getActiveAgent(){return Ju()&&za()?this.openRouterAgent:Ku()&&ja()?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&&(y.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;y.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(d=>u.includes(d))){o=!0,this.lastAiInteraction={timestamp:Date.now(),success:!1,provider:s,error:u},y.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return y.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(u.includes("aborted by user")||u.includes("No conversation found"))&&e.memorySessionId&&(y.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),y.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=as(e.sessionDbId);if(c&&c.process.exitCode===null&&await Ro(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}let d=3;if(l>0){if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,e.consecutiveRestarts>d){y.error("SYSTEM","Exceeded max pending-work restarts, stopping to prevent infinite loop",{sessionId:e.sessionDbId,pendingCount:l,consecutiveRestarts:e.consecutiveRestarts}),e.consecutiveRestarts=0,this.terminateSession(e.sessionDbId,"max_restarts_exceeded");return}y.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.consecutiveRestarts=0,this.sessionManager.removeSessionImmediate(e.sessionDbId)})}isSessionTerminatedError(e){let n=(e instanceof Error?e.message:String(e)).toLowerCase();return n.includes("process aborted by user")||n.includes("processtransport")||n.includes("not ready for writing")||n.includes("session generator failed")||n.includes("claude code process")}async runFallbackForTerminatedSession(e,r){if(!e)return;let n=e.sessionDbId;if(!e.memorySessionId){let o=`fallback-${n}-${Date.now()}`;e.memorySessionId=o,this.dbManager.getSessionStore().updateMemorySessionId(n,o)}if(ja())try{await this.geminiAgent.startSession(e,this);return}catch(o){y.warn("SDK","Fallback Gemini failed, trying OpenRouter",{sessionId:n,error:o instanceof Error?o.message:String(o)})}if(za())try{await this.openRouterAgent.startSession(e,this);return}catch(o){y.warn("SDK","Fallback OpenRouter failed",{sessionId:n,error:o instanceof Error?o.message:String(o)})}let s=this.sessionManager.getPendingMessageStore().markAllSessionMessagesAbandoned(n);s>0&&y.warn("SDK","No fallback available; marked pending messages abandoned",{sessionId:n,abandoned:s}),this.sessionManager.removeSessionImmediate(n),this.sessionEventBroadcaster.broadcastSessionCompleted(n)}terminateSession(e,r){let i=this.sessionManager.getPendingMessageStore().markAllSessionMessagesAbandoned(e);y.info("SYSTEM","Session terminated",{sessionId:e,reason:r,abandonedMessages:i}),this.sessionManager.removeSessionImmediate(e)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(Ra(),Su)),n=new r(this.dbManager.getSessionStore().db,3),i=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s;try{let u=i.db.prepare(`
|
|
1688
1688
|
SELECT id FROM sdk_sessions
|
|
1689
1689
|
WHERE status = 'active' AND started_at_epoch < ?
|
|
1690
1690
|
`).all(o);if(u.length>0){let l=u.map(m=>m.id),d=l.map(()=>"?").join(",");i.db.prepare(`
|