claude-mem 12.4.6 → 12.4.7
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
|
@@ -149,7 +149,7 @@ ${m}`}let c=o.lineStart;for(let u=o.lineStart-1;u>=0;u--){let d=i[u].trim();if(d
|
|
|
149
149
|
${l}`}var Yu=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"]),FS=new Set(["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","env",".env","target","vendor",".cache",".turbo","coverage",".nyc_output",".claude",".smart-file-read"]),HS=512*1024;async function*Ju(t,e,r=20,n){if(r<=0)return;let s;try{s=await(0,Wt.readdir)(t,{withFileTypes:!0})}catch(o){y.debug("WORKER",`walkDir: failed to read directory ${t}`,void 0,o instanceof Error?o:void 0);return}for(let o of s){if(o.name.startsWith(".")&&o.name!=="."||FS.has(o.name))continue;let i=(0,Fr.join)(t,o.name);if(o.isDirectory())yield*Ju(i,e,r-1,n);else if(o.isFile()){let c=o.name.slice(o.name.lastIndexOf("."));(Yu.has(c)||n&&n.has(c))&&(yield i)}}}async function WS(t){try{let e=await(0,Wt.stat)(t);if(e.size>HS||e.size===0)return null;let r=await(0,Wt.readFile)(t,"utf-8");return r.slice(0,1e3).includes("\0")?null:r}catch(e){return y.debug("WORKER",`safeReadFile: failed to read ${t}`,void 0,e instanceof Error?e:void 0),null}}async function Bu(t,e,r={}){let n=r.maxResults||20,s=e.toLowerCase(),o=s.split(/[\s_\-./]+/).filter(S=>S.length>0),i=r.projectRoot||t,c=Ur(i),l=new Set;for(let S of Object.values(c.grammars))for(let w of S.extensions)Yu.has(w)||l.add(w);let u=[];for await(let S of Ju(t,t,20,l.size>0?l:void 0)){if(r.filePattern&&!(0,Fr.relative)(t,S).toLowerCase().includes(r.filePattern.toLowerCase()))continue;let w=await WS(S);w&&u.push({absolutePath:S,relativePath:(0,Fr.relative)(t,S),content:w})}let d=Vu(u,i),f=[],p=[],m=0;for(let[S,w]of d){m+=VS(w);let k=ns(S.toLowerCase(),o)>0,le=[],de=(Gt,gt)=>{for(let H of Gt){let Ve=0,Ee="",Kt=ns(H.name.toLowerCase(),o);Kt>0&&(Ve+=Kt*3,Ee="name match"),H.signature.toLowerCase().includes(s)&&(Ve+=2,Ee=Ee?`${Ee} + signature`:"signature match"),H.jsdoc&&H.jsdoc.toLowerCase().includes(s)&&(Ve+=1,Ee=Ee?`${Ee} + jsdoc`:"jsdoc match"),Ve>0&&(k=!0,le.push({filePath:S,symbolName:gt?`${gt}.${H.name}`:H.name,kind:H.kind,signature:H.signature,jsdoc:H.jsdoc,lineStart:H.lineStart,lineEnd:H.lineEnd,matchReason:Ee})),H.children&&de(H.children,H.name)}};de(w.symbols),k&&(f.push(w),p.push(...le))}p.sort((S,w)=>{let A=ns(S.symbolName.toLowerCase(),o);return ns(w.symbolName.toLowerCase(),o)-A});let h=p.slice(0,n),g=new Set(h.map(S=>S.filePath)),_=f.filter(S=>g.has(S.filePath)).slice(0,n),E=_.reduce((S,w)=>S+w.foldedTokenEstimate,0);return{foldedFiles:_,matchingSymbols:h,totalFilesScanned:u.length,totalSymbolsFound:m,tokenEstimate:E}}function ns(t,e){let r=0;for(let n of e)if(t===n)r+=10;else if(t.includes(n))r+=5;else{let s=0,o=0;for(let i of n){let c=t.indexOf(i,s);c!==-1&&(o++,s=c+1)}o===n.length&&(r+=1)}return r}function VS(t){let e=t.symbols.length;for(let r of t.symbols)r.children&&(e+=r.children.length);return e}function Zu(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(`
|
|
150
150
|
`);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 s=n.jsdoc.split(`
|
|
151
151
|
`).find(o=>o.replace(/^[\s*/]+/,"").trim().length>0);s&&r.push(` \u{1F4AC} ${s.replace(/^[\s*/]+/,"").trim()}`)}r.push("")}r.push("\u2500\u2500 Folded File Views \u2500\u2500"),r.push("");for(let n of t.foldedFiles)r.push(Ht(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(`
|
|
152
|
-
`)}var Gi=require("node:fs/promises"),ed=require("node:fs"),ht=require("node:path"),td=require("node:url"),rE={},GS="12.4.
|
|
152
|
+
`)}var Gi=require("node:fs/promises"),ed=require("node:fs"),ht=require("node:path"),td=require("node:url"),rE={},GS="12.4.7";console.log=(...t)=>{y.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var rd=!1,nd=(()=>{if(typeof __dirname<"u")return __dirname;try{return(0,ht.dirname)((0,td.fileURLToPath)(rE.url))}catch{return rd=!0,process.cwd()}})(),Ki=(0,ht.resolve)(nd,"worker-service.cjs");function KS(){rd&&((0,ed.existsSync)(Ki)||y.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:Ki,mcpServerDir:nd}))}var Xu={search:"/api/search",timeline:"/api/timeline"};async function Vi(t,e){y.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:t,params:e});let r=new URLSearchParams;for(let[s,o]of Object.entries(e))o!=null&&r.append(s,String(o));let n=`${t}?${r}`;try{let s=await es(n);if(!s.ok){let i=await s.text();throw new Error(`Worker API error (${s.status}): ${i}`)}let o=await s.json();return y.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),o}catch(s){return y.error("SYSTEM","\u2190 Worker API error",{endpoint:t},s instanceof Error?s:new Error(String(s))),{content:[{type:"text",text:`Error calling Worker API: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}async function YS(t,e){let r=await es(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){let s=await r.text();throw new Error(`Worker API error (${r.status}): ${s}`)}let n=await r.json();return y.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}async function Vt(t,e){y.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{return await YS(t,e)}catch(r){return y.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 JS(){try{return(await es("/api/health")).ok}catch(t){return y.debug("SYSTEM","Worker health check failed",{},t instanceof Error?t:new Error(String(t))),!1}}async function BS(){if(await JS())return!0;y.warn("SYSTEM","Worker not available, attempting auto-start for MCP client"),KS();try{let t=Ii(),e=await Iu(t,Ki);return e||y.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 y.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 sd=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
|
|
153
153
|
1. search(query) \u2192 Get index with IDs (~50-100 tokens/result)
|
|
154
154
|
2. timeline(anchor=ID) \u2192 Get context around interesting results
|
|
155
155
|
3. get_observations([IDs]) \u2192 Fetch full details ONLY for filtered IDs
|
|
@@ -1066,7 +1066,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
1066
1066
|
SELECT cwd FROM pending_messages
|
|
1067
1067
|
WHERE cwd IS NOT NULL AND cwd != ''
|
|
1068
1068
|
GROUP BY cwd
|
|
1069
|
-
`).all();for(let{cwd:u}of c){let l=qq(u);l&&n.add(l)}}finally{s?.close()}if(n.size===0)return g.debug("SYSTEM","Worktree adoption found no known parent repos"),i;for(let o of n)try{let a=await _C({repoPath:o,dataDirectory:e,dryRun:t.dryRun});i.push(a)}catch(a){g.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return i}var UB=Oe(z0(),1),LB=Oe(require("http"),1),LA=Oe(require("fs"),1),Eh=Oe(require("path"),1);var $A=["search","context","summarize","import","export"],TB=["workflow","search_params","examples","all"];se();var DA=Oe(z0(),1),AB=Oe(PB(),1),NB=Oe(require("path"),1);Tt();se();function jA(t){let e=[];e.push(DA.default.json({limit:"5mb"})),e.push((0,AB.default)({origin:(n,s)=>{!n||n.startsWith("http://localhost:")||n.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((n,s,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(f=>n.path.endsWith(f)),u=n.path==="/api/logs";if(n.path.startsWith("/health")||n.path==="/"||c||u)return o();let l=Date.now(),d=`${n.method}-${Date.now()}`,p=t(n.method,n.path,n.body);g.debug("HTTP",`\u2192 ${n.method} ${n.path}`,{requestId:d},p);let m=s.send.bind(s);s.send=function(f){let h=Date.now()-l;return g.debug("HTTP",`\u2190 ${s.statusCode} ${n.path}`,{requestId:d,duration:`${h}ms`}),m(f)},o()});let r=Xn(),i=NB.default.join(r,"plugin","ui");return e.push(DA.default.static(i)),e}function xh(t,e,r){let i=t.ip||t.connection.remoteAddress||"";if(!(i==="127.0.0.1"||i==="::1"||i==="::ffff:127.0.0.1"||i==="localhost")){g.warn("SECURITY","Admin endpoint access denied - not localhost",{endpoint:t.path,clientIp:i,method:t.method}),e.status(403).json({error:"Forbidden",message:"Admin endpoints are only accessible from localhost"});return}r()}function zA(t,e,r){if(!r||Object.keys(r).length===0||e.includes("/init"))return"";if(e.includes("/observations")){let i=r.tool_name||"?",n=r.tool_input;return`tool=${g.formatTool(i,n)}`}return e.includes("/summarize")?"requesting summary":""}wh();ja();Xs();Na();var FB=Eh.default.resolve(__dirname,"../skills/mem-search"),Cxe=Eh.default.join(FB,"operations"),UA=Eh.default.join(FB,"SKILL.md"),jB=(()=>{try{let t=LA.readFileSync(UA,"utf-8");return g.info("SYSTEM","Cached SKILL.md at boot",{path:UA,bytes:Buffer.byteLength(t,"utf-8")}),t}catch(t){return g.debug("SYSTEM","SKILL.md not present at boot, /api/instructions will 404 for topic queries",{path:UA,message:t instanceof Error?t.message:String(t)}),null}})(),Pxe=(()=>{let t=new Map;for(let e of $A){let r=Eh.default.join(Cxe,`${e}.md`);try{t.set(e,LA.readFileSync(r,"utf-8"))}catch(i){g.debug("SYSTEM","Operation instruction file not present at boot",{path:r,message:i instanceof Error?i.message:String(i)})}}return t.size>0&&g.info("SYSTEM","Cached operation instruction files at boot",{count:t.size,operations:Array.from(t.keys())}),t})(),zB="12.4.
|
|
1069
|
+
`).all();for(let{cwd:u}of c){let l=qq(u);l&&n.add(l)}}finally{s?.close()}if(n.size===0)return g.debug("SYSTEM","Worktree adoption found no known parent repos"),i;for(let o of n)try{let a=await _C({repoPath:o,dataDirectory:e,dryRun:t.dryRun});i.push(a)}catch(a){g.warn("SYSTEM","Worktree adoption failed for parent repo (continuing)",{repoPath:o,error:a instanceof Error?a.message:String(a)})}return i}var UB=Oe(z0(),1),LB=Oe(require("http"),1),LA=Oe(require("fs"),1),Eh=Oe(require("path"),1);var $A=["search","context","summarize","import","export"],TB=["workflow","search_params","examples","all"];se();var DA=Oe(z0(),1),AB=Oe(PB(),1),NB=Oe(require("path"),1);Tt();se();function jA(t){let e=[];e.push(DA.default.json({limit:"5mb"})),e.push((0,AB.default)({origin:(n,s)=>{!n||n.startsWith("http://localhost:")||n.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((n,s,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(f=>n.path.endsWith(f)),u=n.path==="/api/logs";if(n.path.startsWith("/health")||n.path==="/"||c||u)return o();let l=Date.now(),d=`${n.method}-${Date.now()}`,p=t(n.method,n.path,n.body);g.debug("HTTP",`\u2192 ${n.method} ${n.path}`,{requestId:d},p);let m=s.send.bind(s);s.send=function(f){let h=Date.now()-l;return g.debug("HTTP",`\u2190 ${s.statusCode} ${n.path}`,{requestId:d,duration:`${h}ms`}),m(f)},o()});let r=Xn(),i=NB.default.join(r,"plugin","ui");return e.push(DA.default.static(i)),e}function xh(t,e,r){let i=t.ip||t.connection.remoteAddress||"";if(!(i==="127.0.0.1"||i==="::1"||i==="::ffff:127.0.0.1"||i==="localhost")){g.warn("SECURITY","Admin endpoint access denied - not localhost",{endpoint:t.path,clientIp:i,method:t.method}),e.status(403).json({error:"Forbidden",message:"Admin endpoints are only accessible from localhost"});return}r()}function zA(t,e,r){if(!r||Object.keys(r).length===0||e.includes("/init"))return"";if(e.includes("/observations")){let i=r.tool_name||"?",n=r.tool_input;return`tool=${g.formatTool(i,n)}`}return e.includes("/summarize")?"requesting summary":""}wh();ja();Xs();Na();var FB=Eh.default.resolve(__dirname,"../skills/mem-search"),Cxe=Eh.default.join(FB,"operations"),UA=Eh.default.join(FB,"SKILL.md"),jB=(()=>{try{let t=LA.readFileSync(UA,"utf-8");return g.info("SYSTEM","Cached SKILL.md at boot",{path:UA,bytes:Buffer.byteLength(t,"utf-8")}),t}catch(t){return g.debug("SYSTEM","SKILL.md not present at boot, /api/instructions will 404 for topic queries",{path:UA,message:t instanceof Error?t.message:String(t)}),null}})(),Pxe=(()=>{let t=new Map;for(let e of $A){let r=Eh.default.join(Cxe,`${e}.md`);try{t.set(e,LA.readFileSync(r,"utf-8"))}catch(i){g.debug("SYSTEM","Operation instruction file not present at boot",{path:r,message:i instanceof Error?i.message:String(i)})}}return t.size>0&&g.info("SYSTEM","Cached operation instruction files at boot",{count:t.size,operations:Array.from(t.keys())}),t})(),zB="12.4.7",U0=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,UB.default)(),this.setupMiddleware(),this.setupCoreRoutes()}getHttpServer(){return this.server}async listen(e,r){return new Promise((i,n)=>{let s=LB.default.createServer(this.app);this.server=s;let o=c=>{s.off("listening",a),n(c)},a=()=>{s.off("error",o),g.info("SYSTEM","HTTP server started",{host:r,port:e,pid:process.pid}),i()};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(i=>i?r(i):e())}),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),this.server=null,g.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(DB),this.app.use($B)}setupMiddleware(){jA(zA).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:zB,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:zB})}),this.app.get("/api/instructions",(e,r)=>{let i=e.query.topic||"all",n=e.query.operation;if(i&&!TB.includes(i))return r.status(400).json({error:"Invalid topic"});if(n&&!$A.includes(n))return r.status(400).json({error:"Invalid operation"});if(n){let o=Pxe.get(n);return o===void 0?(g.debug("HTTP","Instruction file not cached at boot",{operation:n}),r.status(404).json({error:"Instruction not found"})):r.json({content:[{type:"text",text:o}]})}if(jB===null)return g.debug("HTTP","SKILL.md not cached at boot",{topic:i}),r.status(404).json({error:"Instruction not found"});let s=this.extractInstructionSection(jB,i);r.json({content:[{type:"text",text:s}]})}),this.app.post("/api/admin/restart",xh,async(e,r)=>{r.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(g.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",xh,async(e,r)=>{r.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(g.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",xh,(e,r)=>{let o=Qr().getRegistry().getAll().map(f=>({id:f.id,pid:f.pid,type:f.type,status:mi(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=>LR.has(f)||UR.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 i={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 i[r]||i.all}extractBetween(e,r,i){let n=e.indexOf(r),s=e.indexOf(i);return n===-1?e:s===-1?e.substring(n):e.substring(n,s).trim()}};var qt=Oe(require("path"),1),Th=require("os"),or=require("fs"),HB=require("child_process"),BB=require("util");se();hn();Tt();var Xi=require("fs"),kh=require("path");se();function qB(t){try{return(0,Xi.existsSync)(t)?JSON.parse((0,Xi.readFileSync)(t,"utf-8")):{}}catch(e){return g.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function WB(t,e){let r=(0,kh.join)(t,"..");(0,Xi.mkdirSync)(r,{recursive:!0}),(0,Xi.writeFileSync)(t,JSON.stringify(e,null,2))}function FA(t,e){let r=(0,kh.join)(t,".cursor","rules"),i=(0,kh.join)(r,"claude-mem-context.mdc"),n=`${i}.tmp`;(0,Xi.mkdirSync)(r,{recursive:!0});let s=`---
|
|
1070
1070
|
alwaysApply: true
|
|
1071
1071
|
description: "Claude-mem context from past sessions (auto-updated)"
|
|
1072
1072
|
---
|
|
@@ -1728,7 +1728,7 @@ ${s.formatTableHeader()}`,m=d.map((f,h)=>s.formatObservationIndex(f,h));i.json({
|
|
|
1728
1728
|
`);Er(Ui);let n=this.findClaudeExecutable(),s=pi(Gf()),o=Ng({prompt:i,options:{model:this.getModelId(),cwd:Ui,disallowedTools:Yee,pathToClaudeCodeExecutable:n,env:s,mcpServers:{}}}),a;try{for await(let c of o)c.session_id&&(a=c.session_id),c.type==="result"&&g.info("WORKER",`Knowledge agent primed for corpus "${e.name}"`)}catch(c){if(a)c instanceof Error?g.debug("WORKER",`SDK process exited after priming corpus "${e.name}" \u2014 session captured, continuing`,{},c):g.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 i=await this.executeQuery(e,r);return i.session_id!==e.session_id&&(e.session_id=i.session_id,this.corpusStore.write(e)),i}catch(i){if(!this.isSessionResumeError(i))throw i instanceof Error?g.error("WORKER",`Query failed for corpus "${e.name}"`,{},i):g.error("WORKER",`Query failed for corpus "${e.name}" (non-Error thrown)`,{thrownValue:String(i)}),i;g.info("WORKER",`Session expired for corpus "${e.name}", auto-repriming...`),await this.prime(e);let n=this.corpusStore.read(e.name);if(!n||!n.session_id)throw new Error(`Auto-reprime failed for corpus "${e.name}"`);let s=await this.executeQuery(n,r);return s.session_id!==n.session_id&&(n.session_id=s.session_id,this.corpusStore.write(n)),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){Er(Ui);let i=this.findClaudeExecutable(),n=pi(Gf()),s=Ng({prompt:r,options:{model:this.getModelId(),resume:e.session_id,cwd:Ui,disallowedTools:Yee,pathToClaudeCodeExecutable:i,env:n,mcpServers:{}}}),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?g.debug("WORKER","SDK process exited after query \u2014 answer captured, continuing",{},c):g.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 ke.loadFromFile(kt).CLAUDE_MEM_MODEL}findClaudeExecutable(){let e=ke.loadFromFile(kt);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,rj.execSync)("where claude.cmd",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}),"claude.cmd"}catch{}try{let r=(0,rj.execSync)(process.platform==="win32"?"where claude":"which claude",{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}).trim().split(`
|
|
1729
1729
|
`)[0].trim();if(r)return r}catch(r){r instanceof Error?g.debug("WORKER","Claude executable auto-detection failed",{},r):g.debug("WORKER","Claude executable auto-detection failed (non-Error thrown)",{thrownValue:String(r)})}throw new Error(`Claude executable not found. Please either:
|
|
1730
1730
|
1. Add "claude" to your system PATH, or
|
|
1731
|
-
2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};Xs();var JDe={},GDe="12.4.6";function Tte(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var XE=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 W0,this.sessionManager=new G0(this.dbManager),this.sseBroadcaster=new V0,this.sdkAgent=new Hw(this.dbManager,this.sessionManager),this.geminiAgent=new Bw(this.dbManager,this.sessionManager),this.openRouterAgent=new Vw(this.dbManager,this.sessionManager),this.paginationHelper=new Kw(this.dbManager),this.settingsManager=new Yw(this.dbManager),this.sessionEventBroadcaster=new tE(this.sseBroadcaster,this),this.completionHandler=new rE(this.sessionManager,this.sessionEventBroadcaster,this.dbManager),this.corpusStore=new GE,fZ({sessionManager:this.sessionManager,dbManager:this.dbManager,eventBroadcaster:this.sessionEventBroadcaster}),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Vl({name:"worker-search-proxy",version:GDe},{capabilities:{}}),this.server=new U0({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return _p()&&ku()?e="openrouter":yp()&&Eu()&&(e="gemini"),{provider:e,authMethod:gS(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){rq(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.registerRoutes(new ZE),this.server.app.get("/api/context/inject",async(r,i,n)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){g.warn("SYSTEM","Context requested before initialization complete, returning empty"),i.status(200).json({content:[{type:"text",text:""}]});return}n()}),this.server.app.use("/api",async(r,i,n)=>{if(r.path==="/chroma/status"||r.path==="/health"||r.path==="/readiness"||r.path==="/version"){n();return}if(this.initializationCompleteFlag){n();return}let s=12e4,o=new Promise((a,c)=>setTimeout(()=>c(new Error("Database initialization timeout")),s));try{await Promise.race([this.initializationComplete,o]),n()}catch(a){a instanceof Error?g.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized`,{},a):g.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized with non-Error`,{},new Error(String(a))),i.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"});return}}),this.server.registerRoutes(new CE(this.sseBroadcaster,this.dbManager,this.sessionManager));let e=new AE(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this,this.completionHandler);this.server.registerRoutes(e),hZ((r,i)=>e.ensureGeneratorRunning(r,i)),this.server.registerRoutes(new NE(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new FE(this.settingsManager)),this.server.registerRoutes(new WE),this.server.registerRoutes(new HE(this.dbManager,"claude-mem"))}async start(){let e=On(),r=KR();await tq(),await this.server.listen(e,r),Iq({pid:process.pid,port:e,startedAt:new Date().toISOString()}),Qr().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),g.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(i=>{g.error("SYSTEM","Background initialization failed",{},i)})}async initializeBackground(){try{g.info("WORKER","Background initialization starting...");let{ModeManager:e}=await Promise.resolve().then(()=>(Pn(),nZ)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(sr(),RF)),{USER_SETTINGS_PATH:i}=await Promise.resolve().then(()=>(Tt(),DF)),n=r.loadFromFile(i),s=n.CLAUDE_MEM_MODE;e.getInstance().loadMode(s),g.info("SYSTEM",`Mode loaded: ${s}`),(n.CLAUDE_MEM_MODE==="local"||!n.CLAUDE_MEM_MODE)&&(g.info("WORKER","Checking for one-time Chroma migration..."),Oq()),g.info("WORKER","Checking for one-time CWD remap..."),Rq(),g.info("WORKER","Adopting merged worktrees (background)..."),Wq({}).then(h=>{if(h)for(let v of h)(v.adoptedObservations>0||v.adoptedSummaries>0||v.chromaUpdates>0)&&g.info("SYSTEM","Merged worktrees adopted in background",v),v.errors.length>0&&g.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:v.repoPath,errors:v.errors})}).catch(h=>{g.error("WORKER","Worktree adoption failed (background)",{},h instanceof Error?h:new Error(String(h)))}),n.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Fi.getInstance(),g.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):g.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager"),g.info("WORKER","Initializing database manager..."),await this.dbManager.initialize();try{g.info("WORKER","Running startup GC for pending messages...");let{PendingMessageStore:h}=await Promise.resolve().then(()=>(H0(),VA)),y=new h(this.dbManager.getSessionStore().db,3).clearFailedOlderThan(10080*60*1e3);y>0&&g.info("QUEUE","Startup GC cleared old failed pending_messages rows",{cleared:y})}catch(h){g.warn("QUEUE","Startup GC for failed pending_messages rows failed",{},h instanceof Error?h:void 0)}vC(),g.info("WORKER","Initializing search services...");let a=new Qw,c=new eE,u=new Xw(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),a,c);this.searchRoutes=new zE(u),this.server.registerRoutes(this.searchRoutes),g.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:l}=await Promise.resolve().then(()=>(vD(),xX)),d=new l(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),p=new KE(this.dbManager.getSessionStore(),d,this.corpusStore),m=new YE(this.corpusStore);this.server.registerRoutes(new BE(this.corpusStore,p,m)),g.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),g.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(n),this.chromaMcpManager&&Ua.backfillAllProjects(this.dbManager.getSessionStore()).then(()=>{g.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(h=>{g.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},h)});let f=kte.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,vj.existsSync)(f),this.runMcpSelfCheck(f).catch(h=>{g.debug("WORKER","MCP self-check failed (non-fatal)",{error:h.message})});return}catch(e){g.error("SYSTEM","Background initialization failed",{},e instanceof Error?e:void 0)}}async runMcpSelfCheck(e){try{Qr().assertCanSpawn("mcp server");let r=new Jl({command:process.execPath,args:[e],env:Object.fromEntries(Object.entries(pi(process.env)).filter(([,o])=>o!==void 0))}),i=6e4,n=this.mcpClient.connect(r),s=new Promise((o,a)=>{setTimeout(()=>a(new Error("MCP connection timeout")),6e4)});await Promise.race([n,s]),g.info("WORKER","MCP loopback self-check connected successfully"),await r.close()}catch(r){g.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")){g.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let i=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||iE,n=ea(i);(0,vj.existsSync)(n)||(EX(i),g.info("TRANSCRIPT","Created default transcript watch config",{configPath:n}));let s=wX(i),o=ea(s.stateFile??sE);try{this.transcriptWatcher=new IE(s,o),await this.transcriptWatcher.start()}catch(a){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,a instanceof Error?g.error("WORKER","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:n},a):g.error("WORKER","Failed to start transcript watcher with non-Error (continuing without Codex ingestion)",{configPath:n},new Error(String(a)));return}g.info("TRANSCRIPT","Transcript watcher started",{configPath:n,statePath:o,watches:s.watches.length})}getActiveAgent(){return _p()&&ku()?this.openRouterAgent:yp()&&Eu()?this.geminiAgent:this.sdkAgent}startSessionProcessor(e,r){if(!e)return;let i=e.sessionDbId,n=this.getActiveAgent(),s=n.constructor.name;e.abortController.signal.aborted&&(g.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;g.info("SYSTEM",`Starting generator (${r}) using ${s}`,{sessionId:i}),e.lastGeneratorActivity=Date.now(),e.generatorPromise=n.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},g.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return g.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&&(g.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),g.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=$a(e.sessionDbId);if(c&&c.process.exitCode===null&&await Da(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 qa);let d=e.restartGuard.recordRestart();if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,!d){g.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}g.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 i=(e instanceof Error?e.message:String(e)).toLowerCase();return t.SESSION_TERMINATED_PATTERNS.some(n=>i.includes(n))}async runFallbackForTerminatedSession(e,r){if(!e)return;let i=e.sessionDbId;if(!e.memorySessionId){let n=`fallback-${i}-${Date.now()}`;e.memorySessionId=n,this.dbManager.getSessionStore().updateMemorySessionId(i,n)}if(Eu())try{await this.geminiAgent.startSession(e,this);return}catch(n){n instanceof Error?(g.warn("WORKER","Fallback Gemini failed, trying OpenRouter",{sessionId:i}),g.error("WORKER","Gemini fallback error detail",{sessionId:i},n)):g.error("WORKER","Gemini fallback failed with non-Error",{sessionId:i},new Error(String(n)))}if(ku())try{await this.openRouterAgent.startSession(e,this);return}catch(n){n instanceof Error?g.error("WORKER","Fallback OpenRouter failed, will abandon messages",{sessionId:i},n):g.error("WORKER","Fallback OpenRouter failed with non-Error, will abandon messages",{sessionId:i},new Error(String(n)))}this.completionHandler.finalizeSession(i),this.sessionManager.removeSessionImmediate(i)}terminateSession(e,r){g.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(()=>(H0(),VA)),i=new r(this.dbManager.getSessionStore().db,3),n=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s,a=n.db.prepare(`
|
|
1731
|
+
2. Set CLAUDE_CODE_PATH in ~/.claude-mem/settings.json`)}};Xs();var JDe={},GDe="12.4.7";function Tte(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var XE=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 W0,this.sessionManager=new G0(this.dbManager),this.sseBroadcaster=new V0,this.sdkAgent=new Hw(this.dbManager,this.sessionManager),this.geminiAgent=new Bw(this.dbManager,this.sessionManager),this.openRouterAgent=new Vw(this.dbManager,this.sessionManager),this.paginationHelper=new Kw(this.dbManager),this.settingsManager=new Yw(this.dbManager),this.sessionEventBroadcaster=new tE(this.sseBroadcaster,this),this.completionHandler=new rE(this.sessionManager,this.sessionEventBroadcaster,this.dbManager),this.corpusStore=new GE,fZ({sessionManager:this.sessionManager,dbManager:this.dbManager,eventBroadcaster:this.sessionEventBroadcaster}),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Vl({name:"worker-search-proxy",version:GDe},{capabilities:{}}),this.server=new U0({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return _p()&&ku()?e="openrouter":yp()&&Eu()&&(e="gemini"),{provider:e,authMethod:gS(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){rq(async()=>{this.isShuttingDown=!0,await this.shutdown()})}registerRoutes(){this.server.registerRoutes(new ZE),this.server.app.get("/api/context/inject",async(r,i,n)=>{if(!this.initializationCompleteFlag||!this.searchRoutes){g.warn("SYSTEM","Context requested before initialization complete, returning empty"),i.status(200).json({content:[{type:"text",text:""}]});return}n()}),this.server.app.use("/api",async(r,i,n)=>{if(r.path==="/chroma/status"||r.path==="/health"||r.path==="/readiness"||r.path==="/version"){n();return}if(this.initializationCompleteFlag){n();return}let s=12e4,o=new Promise((a,c)=>setTimeout(()=>c(new Error("Database initialization timeout")),s));try{await Promise.race([this.initializationComplete,o]),n()}catch(a){a instanceof Error?g.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized`,{},a):g.error("WORKER",`Request to ${r.method} ${r.path} rejected \u2014 DB not initialized with non-Error`,{},new Error(String(a))),i.status(503).json({error:"Service initializing",message:"Database is still initializing, please retry"});return}}),this.server.registerRoutes(new CE(this.sseBroadcaster,this.dbManager,this.sessionManager));let e=new AE(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this,this.completionHandler);this.server.registerRoutes(e),hZ((r,i)=>e.ensureGeneratorRunning(r,i)),this.server.registerRoutes(new NE(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new FE(this.settingsManager)),this.server.registerRoutes(new WE),this.server.registerRoutes(new HE(this.dbManager,"claude-mem"))}async start(){let e=On(),r=KR();await tq(),await this.server.listen(e,r),Iq({pid:process.pid,port:e,startedAt:new Date().toISOString()}),Qr().registerProcess("worker",{pid:process.pid,type:"worker",startedAt:new Date().toISOString()}),g.info("SYSTEM","Worker started",{host:r,port:e,pid:process.pid}),this.initializeBackground().catch(i=>{g.error("SYSTEM","Background initialization failed",{},i)})}async initializeBackground(){try{g.info("WORKER","Background initialization starting...");let{ModeManager:e}=await Promise.resolve().then(()=>(Pn(),nZ)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(sr(),RF)),{USER_SETTINGS_PATH:i}=await Promise.resolve().then(()=>(Tt(),DF)),n=r.loadFromFile(i),s=n.CLAUDE_MEM_MODE;e.getInstance().loadMode(s),g.info("SYSTEM",`Mode loaded: ${s}`),(n.CLAUDE_MEM_MODE==="local"||!n.CLAUDE_MEM_MODE)&&(g.info("WORKER","Checking for one-time Chroma migration..."),Oq()),g.info("WORKER","Checking for one-time CWD remap..."),Rq(),g.info("WORKER","Adopting merged worktrees (background)..."),Wq({}).then(h=>{if(h)for(let v of h)(v.adoptedObservations>0||v.adoptedSummaries>0||v.chromaUpdates>0)&&g.info("SYSTEM","Merged worktrees adopted in background",v),v.errors.length>0&&g.warn("SYSTEM","Worktree adoption had per-branch errors",{repoPath:v.repoPath,errors:v.errors})}).catch(h=>{g.error("WORKER","Worktree adoption failed (background)",{},h instanceof Error?h:new Error(String(h)))}),n.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Fi.getInstance(),g.info("SYSTEM","ChromaMcpManager initialized (lazy - connects on first use)")):g.info("SYSTEM","Chroma disabled via CLAUDE_MEM_CHROMA_ENABLED=false, skipping ChromaMcpManager"),g.info("WORKER","Initializing database manager..."),await this.dbManager.initialize();try{g.info("WORKER","Running startup GC for pending messages...");let{PendingMessageStore:h}=await Promise.resolve().then(()=>(H0(),VA)),y=new h(this.dbManager.getSessionStore().db,3).clearFailedOlderThan(10080*60*1e3);y>0&&g.info("QUEUE","Startup GC cleared old failed pending_messages rows",{cleared:y})}catch(h){g.warn("QUEUE","Startup GC for failed pending_messages rows failed",{},h instanceof Error?h:void 0)}vC(),g.info("WORKER","Initializing search services...");let a=new Qw,c=new eE,u=new Xw(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),a,c);this.searchRoutes=new zE(u),this.server.registerRoutes(this.searchRoutes),g.info("WORKER","SearchManager initialized and search routes registered");let{SearchOrchestrator:l}=await Promise.resolve().then(()=>(vD(),xX)),d=new l(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync()),p=new KE(this.dbManager.getSessionStore(),d,this.corpusStore),m=new YE(this.corpusStore);this.server.registerRoutes(new BE(this.corpusStore,p,m)),g.info("WORKER","CorpusRoutes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),g.info("SYSTEM","Core initialization complete (DB + search ready)"),await this.startTranscriptWatcher(n),this.chromaMcpManager&&Ua.backfillAllProjects(this.dbManager.getSessionStore()).then(()=>{g.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(h=>{g.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},h)});let f=kte.default.join(__dirname,"mcp-server.cjs");this.mcpReady=(0,vj.existsSync)(f),this.runMcpSelfCheck(f).catch(h=>{g.debug("WORKER","MCP self-check failed (non-fatal)",{error:h.message})});return}catch(e){g.error("SYSTEM","Background initialization failed",{},e instanceof Error?e:void 0)}}async runMcpSelfCheck(e){try{Qr().assertCanSpawn("mcp server");let r=new Jl({command:process.execPath,args:[e],env:Object.fromEntries(Object.entries(pi(process.env)).filter(([,o])=>o!==void 0))}),i=6e4,n=this.mcpClient.connect(r),s=new Promise((o,a)=>{setTimeout(()=>a(new Error("MCP connection timeout")),6e4)});await Promise.race([n,s]),g.info("WORKER","MCP loopback self-check connected successfully"),await r.close()}catch(r){g.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")){g.info("TRANSCRIPT","Transcript watcher disabled via CLAUDE_MEM_TRANSCRIPTS_ENABLED=false");return}let i=e.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH||iE,n=ea(i);(0,vj.existsSync)(n)||(EX(i),g.info("TRANSCRIPT","Created default transcript watch config",{configPath:n}));let s=wX(i),o=ea(s.stateFile??sE);try{this.transcriptWatcher=new IE(s,o),await this.transcriptWatcher.start()}catch(a){this.transcriptWatcher?.stop(),this.transcriptWatcher=null,a instanceof Error?g.error("WORKER","Failed to start transcript watcher (continuing without Codex ingestion)",{configPath:n},a):g.error("WORKER","Failed to start transcript watcher with non-Error (continuing without Codex ingestion)",{configPath:n},new Error(String(a)));return}g.info("TRANSCRIPT","Transcript watcher started",{configPath:n,statePath:o,watches:s.watches.length})}getActiveAgent(){return _p()&&ku()?this.openRouterAgent:yp()&&Eu()?this.geminiAgent:this.sdkAgent}startSessionProcessor(e,r){if(!e)return;let i=e.sessionDbId,n=this.getActiveAgent(),s=n.constructor.name;e.abortController.signal.aborted&&(g.debug("SYSTEM","Replacing aborted AbortController before starting generator",{sessionId:e.sessionDbId}),e.abortController=new AbortController);let o=!1,a=!1;g.info("SYSTEM",`Starting generator (${r}) using ${s}`,{sessionId:i}),e.lastGeneratorActivity=Date.now(),e.generatorPromise=n.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},g.error("SDK","Unrecoverable generator error - will NOT restart",{sessionId:e.sessionDbId,project:e.project,errorMessage:u});return}if(this.isSessionTerminatedError(c))return g.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&&(g.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),g.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=$a(e.sessionDbId);if(c&&c.process.exitCode===null&&await Da(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 qa);let d=e.restartGuard.recordRestart();if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,!d){g.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}g.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 i=(e instanceof Error?e.message:String(e)).toLowerCase();return t.SESSION_TERMINATED_PATTERNS.some(n=>i.includes(n))}async runFallbackForTerminatedSession(e,r){if(!e)return;let i=e.sessionDbId;if(!e.memorySessionId){let n=`fallback-${i}-${Date.now()}`;e.memorySessionId=n,this.dbManager.getSessionStore().updateMemorySessionId(i,n)}if(Eu())try{await this.geminiAgent.startSession(e,this);return}catch(n){n instanceof Error?(g.warn("WORKER","Fallback Gemini failed, trying OpenRouter",{sessionId:i}),g.error("WORKER","Gemini fallback error detail",{sessionId:i},n)):g.error("WORKER","Gemini fallback failed with non-Error",{sessionId:i},new Error(String(n)))}if(ku())try{await this.openRouterAgent.startSession(e,this);return}catch(n){n instanceof Error?g.error("WORKER","Fallback OpenRouter failed, will abandon messages",{sessionId:i},n):g.error("WORKER","Fallback OpenRouter failed with non-Error, will abandon messages",{sessionId:i},new Error(String(n)))}this.completionHandler.finalizeSession(i),this.sessionManager.removeSessionImmediate(i)}terminateSession(e,r){g.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(()=>(H0(),VA)),i=new r(this.dbManager.getSessionStore().db,3),n=this.dbManager.getSessionStore(),s=360*60*1e3,o=Date.now()-s,a=n.db.prepare(`
|
|
1732
1732
|
SELECT id FROM sdk_sessions
|
|
1733
1733
|
WHERE status = 'active' AND started_at_epoch < ?
|
|
1734
1734
|
`).all(o);if(a.length>0){let l=a.map(m=>m.id),d=l.map(()=>"?").join(","),p=Date.now();try{n.db.prepare(`
|