claude-mem 10.5.6 → 10.6.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/README.md CHANGED
@@ -1,13 +1,3 @@
1
- <p align="center">
2
- Official $CMEM Links:
3
- <a href="https://bags.fm/2TsmuYUrsctE57VLckZBYEEzdokUF8j8e1GavekWBAGS">Bags.fm</a> •
4
- <a href="https://jup.ag/tokens/2TsmuYUrsctE57VLckZBYEEzdokUF8j8e1GavekWBAGS">Jupiter</a> •
5
- <a href="https://photon-sol.tinyastro.io/en/lp/6MzFAkWnac6GSK1EdFX93dZeukGfzrFq4UHWarhGSQyd">Photon</a> •
6
- <a href="https://dexscreener.com/solana/6mzfakwnac6gsk1edfx93dzeukgfzrfq4uhwarhgsqyd">DEXScreener</a>
7
- </p>
8
-
9
- <p align="center">Official CA: 2TsmuYUrsctE57VLckZBYEEzdokUF8j8e1GavekWBAGS (on Solana)</p>
10
-
11
1
  <h1 align="center">
12
2
  <br>
13
3
  <a href="https://github.com/thedotmack/claude-mem">
@@ -84,13 +74,40 @@
84
74
 
85
75
  <br>
86
76
 
87
- <p align="center">
88
- <a href="https://github.com/thedotmack/claude-mem">
89
- <picture>
90
- <img src="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/cm-preview.gif" alt="Claude-Mem Preview" width="800">
91
- </picture>
92
- </a>
93
- </p>
77
+ <table align="center">
78
+ <tr>
79
+ <td align="center">
80
+ <a href="https://github.com/thedotmack/claude-mem">
81
+ <picture>
82
+ <img
83
+ src="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/cm-preview.gif"
84
+ alt="Claude-Mem Preview"
85
+ width="500"
86
+ >
87
+ </picture>
88
+ </a>
89
+ </td>
90
+ <td align="center">
91
+ <a href="https://www.star-history.com/#thedotmack/claude-mem&Date">
92
+ <picture>
93
+ <source
94
+ media="(prefers-color-scheme: dark)"
95
+ srcset="https://api.star-history.com/image?repos=thedotmack/claude-mem&type=date&theme=dark&legend=top-left"
96
+ />
97
+ <source
98
+ media="(prefers-color-scheme: light)"
99
+ srcset="https://api.star-history.com/image?repos=thedotmack/claude-mem&type=date&legend=top-left"
100
+ />
101
+ <img
102
+ alt="Star History Chart"
103
+ src="https://api.star-history.com/image?repos=thedotmack/claude-mem&type=date&legend=top-left"
104
+ width="500"
105
+ />
106
+ </picture>
107
+ </a>
108
+ </td>
109
+ </tr>
110
+ </table>
94
111
 
95
112
  <p align="center">
96
113
  <a href="#quick-start">Quick Start</a> •
@@ -340,3 +357,9 @@ See the [LICENSE](LICENSE) file for full details.
340
357
  ---
341
358
 
342
359
  **Built with Claude Agent SDK** | **Powered by Claude Code** | **Made with TypeScript**
360
+
361
+ ---
362
+
363
+ ### What About $CMEM?
364
+
365
+ $CMEM is a solana token created by a 3rd party without Claude-Mem's prior consent, but officially embraced by the creator of Claude-Mem (Alex Newman, @thedotmack). The token acts as a community catalyst for growth and a vehicle for bringing real-time agent data to the developers and knowledge workers that need it most. $CMEM: 2TsmuYUrsctE57VLckZBYEEzdokUF8j8e1GavekWBAGS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "10.5.6",
3
+ "version": "10.6.0",
4
4
  "description": "Memory compression system for Claude Code - persist context across sessions",
5
5
  "keywords": [
6
6
  "claude",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "10.5.6",
3
+ "version": "10.6.0",
4
4
  "description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
5
5
  "author": {
6
6
  "name": "Alex Newman"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-plugin",
3
- "version": "10.5.6",
3
+ "version": "10.6.0",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for claude-mem bundled hooks",
6
6
  "type": "module",
@@ -114,7 +114,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
114
114
  ${c}`}var xP=new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs",".py",".pyw",".go",".rs",".rb",".java",".cs",".cpp",".c",".h",".hpp",".swift",".kt",".php",".vue",".svelte"]),kP=new Set(["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","env",".env","target","vendor",".cache",".turbo","coverage",".nyc_output",".claude",".smart-file-read"]),SP=512*1024;async function*u$(t,e,r=20){if(r<=0)return;let n;try{n=await(0,zn.readdir)(t,{withFileTypes:!0})}catch{return}for(let o of n){if(o.name.startsWith(".")&&o.name!=="."||kP.has(o.name))continue;let i=(0,hi.join)(t,o.name);if(o.isDirectory())yield*u$(i,e,r-1);else if(o.isFile()){let a=o.name.slice(o.name.lastIndexOf("."));xP.has(a)&&(yield i)}}}async function wP(t){try{let e=await(0,zn.stat)(t);if(e.size>SP||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 l$(t,e,r={}){let n=r.maxResults||20,o=e.toLowerCase(),i=o.split(/[\s_\-./]+/).filter(h=>h.length>0),a=[];for await(let h of u$(t,t)){if(r.filePattern&&!(0,hi.relative)(t,h).toLowerCase().includes(r.filePattern.toLowerCase()))continue;let _=await wP(h);_&&a.push({absolutePath:h,relativePath:(0,hi.relative)(t,h),content:_})}let s=a$(a),c=[],u=[],l=0;for(let[h,_]of s){l+=zP(_);let E=js(h.toLowerCase(),i)>0,I=[],A=(j,Le)=>{for(let de of j){let Wt=0,Qe="",Kt=js(de.name.toLowerCase(),i);Kt>0&&(Wt+=Kt*3,Qe="name match"),de.signature.toLowerCase().includes(o)&&(Wt+=2,Qe=Qe?`${Qe} + signature`:"signature match"),de.jsdoc&&de.jsdoc.toLowerCase().includes(o)&&(Wt+=1,Qe=Qe?`${Qe} + jsdoc`:"jsdoc match"),Wt>0&&(E=!0,I.push({filePath:h,symbolName:Le?`${Le}.${de.name}`:de.name,kind:de.kind,signature:de.signature,jsdoc:de.jsdoc,lineStart:de.lineStart,lineEnd:de.lineEnd,matchReason:Qe})),de.children&&A(de.children,de.name)}};A(_.symbols),E&&(c.push(_),u.push(...I))}u.sort((h,_)=>{let b=js(h.symbolName.toLowerCase(),i);return js(_.symbolName.toLowerCase(),i)-b});let d=u.slice(0,n),p=new Set(d.map(h=>h.filePath)),f=c.filter(h=>p.has(h.filePath)).slice(0,n),g=f.reduce((h,_)=>h+_.foldedTokenEstimate,0);return{foldedFiles:f,matchingSymbols:d,totalFilesScanned:a.length,totalSymbolsFound:l,tokenEstimate:g}}function js(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 zP(t){let e=t.symbols.length;for(let r of t.symbols)r.children&&(e+=r.children.length);return e}function d$(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(`
115
115
  `);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(`
116
116
  `).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(wn(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(`
117
- `)}var jf=require("node:fs/promises"),Ds=require("node:path"),IP="10.5.6";console.log=(...t)=>{ve.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var p$={search:"/api/search",timeline:"/api/timeline"};async function f$(t,e){ve.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 Ps(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return ve.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),i}catch(r){return ve.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 EP(t,e){ve.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{let r=await Ps(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 ve.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}catch(r){return ve.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 TP(){try{return(await Ps("/api/health")).ok}catch(t){return ve.debug("SYSTEM","Worker health check failed",{},t),!1}}var m$=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
117
+ `)}var jf=require("node:fs/promises"),Ds=require("node:path"),IP="10.6.0";console.log=(...t)=>{ve.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:t})};var p$={search:"/api/search",timeline:"/api/timeline"};async function f$(t,e){ve.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 Ps(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return ve.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:t}),i}catch(r){return ve.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 EP(t,e){ve.debug("HTTP","Worker API request (POST)",void 0,{endpoint:t});try{let r=await Ps(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 ve.debug("HTTP","Worker API success (POST)",void 0,{endpoint:t}),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}catch(r){return ve.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 TP(){try{return(await Ps("/api/health")).ok}catch(t){return ve.debug("SYSTEM","Worker health check failed",{},t),!1}}var m$=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
118
118
  1. search(query) \u2192 Get index with IDs (~50-100 tokens/result)
119
119
  2. timeline(anchor=ID) \u2192 Get context around interesting results
120
120
  3. get_observations([IDs]) \u2192 Fetch full details ONLY for filtered IDs
@@ -919,7 +919,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
919
919
  JOIN sdk_sessions s ON up.content_session_id = s.content_session_id
920
920
  WHERE s.project = ?
921
921
  `).get(r);y.info("CHROMA_SYNC","Backfilling user prompts",{project:r,missing:v.length,existing:n.prompts.size,total:x.count});let b=[];for(let _ of v)b.push(this.formatUserPromptDoc(_));for(let _=0;_<b.length;_+=this.BATCH_SIZE){let S=b.slice(_,_+this.BATCH_SIZE);await this.addDocuments(S),y.debug("CHROMA_SYNC","Backfill progress",{project:r,progress:`${Math.min(_+this.BATCH_SIZE,b.length)}/${b.length}`})}y.info("CHROMA_SYNC","Smart backfill complete",{project:r,synced:{observationDocs:u.length,summaryDocs:f.length,promptDocs:b.length},skipped:{observations:n.observations.size,summaries:n.summaries.size,prompts:n.prompts.size}})}catch(s){throw y.error("CHROMA_SYNC","Backfill failed",{project:r},s),new Error(`Backfill failed: ${s instanceof Error?s.message:String(s)}`)}finally{i.close()}}async queryChroma(e,r,n){await this.ensureCollectionExists();try{let s=await Xi.getInstance().callTool("chroma_query_documents",{collection_name:this.collectionName,query_texts:[e],n_results:r,...n&&{where:n},include:["documents","metadatas","distances"]}),o=[],a=new Set,c=s?.ids?.[0]||[],u=s?.metadatas?.[0]||[],l=s?.distances?.[0]||[],d=[],p=[];for(let m=0;m<c.length;m++){let f=c[m],g=f.match(/obs_(\d+)_/),h=f.match(/summary_(\d+)_/),v=f.match(/prompt_(\d+)/),x=null;g?x=parseInt(g[1],10):h?x=parseInt(h[1],10):v&&(x=parseInt(v[1],10)),x!==null&&!a.has(x)&&(a.add(x),o.push(x),d.push(u[m]??null),p.push(l[m]??0))}return{ids:o,distances:p,metadatas:d}}catch(i){let s=i instanceof Error?i.message:String(i);throw s.includes("ECONNREFUSED")||s.includes("ENOTFOUND")||s.includes("fetch failed")||s.includes("subprocess closed")||s.includes("timed out")?(this.collectionCreated=!1,y.error("CHROMA_SYNC","Connection lost during query",{project:this.project,query:e},i),new Error(`Chroma query failed - connection lost: ${s}`)):(y.error("CHROMA_SYNC","Query failed",{project:this.project,query:e},i),i)}}static async backfillAllProjects(){let e=new Yi,r=new t("claude-mem");try{let n=e.db.prepare("SELECT DISTINCT project FROM observations WHERE project IS NOT NULL AND project != ?").all("");y.info("CHROMA_SYNC",`Backfill check for ${n.length} projects`);for(let{project:i}of n)try{await r.ensureBackfilled(i)}catch(s){y.error("CHROMA_SYNC",`Backfill failed for project: ${i}`,{},s)}}finally{await r.close(),e.close()}}async close(){y.info("CHROMA_SYNC","ChromaSync closed",{project:this.project})}};var Hf=require("fs"),B0=require("path"),RA=require("os"),CK="claude-mem@thedotmack";function Zf(){try{let t=process.env.CLAUDE_CONFIG_DIR||(0,B0.join)((0,RA.homedir)(),".claude"),e=(0,B0.join)(t,"settings.json");if(!(0,Hf.existsSync)(e))return!1;let r=(0,Hf.readFileSync)(e,"utf-8");return JSON.parse(r)?.enabledPlugins?.[CK]===!1}catch{return!1}}var yi=Ge(require("path"),1),G0=require("os"),zt=require("fs"),Qi=require("child_process"),AA=require("util");oe();gn();var OA=(0,AA.promisify)(Qi.exec),W0=yi.default.join((0,G0.homedir)(),".claude-mem"),_i=yi.default.join(W0,"worker.pid");var PA=30;function CA(t){return t?/(^|[\\/])bun(\.exe)?$/i.test(t.trim()):!1}function AK(t,e){let r=e==="win32"?`where ${t}`:`which ${t}`;try{return(0,Qi.execSync)(r,{stdio:["ignore","pipe","ignore"],encoding:"utf-8",windowsHide:!0}).split(/\r?\n/).map(s=>s.trim()).find(s=>s.length>0)||null}catch{return null}}function NK(t={}){let e=t.platform??process.platform,r=t.execPath??process.execPath;if(e!=="win32"||CA(r))return r;let n=t.env??process.env,i=t.homeDirectory??(0,G0.homedir)(),s=t.pathExists??zt.existsSync,o=t.lookupInPath??AK,a=[n.BUN,n.BUN_PATH,yi.default.join(i,".bun","bin","bun.exe"),yi.default.join(i,".bun","bin","bun"),n.USERPROFILE?yi.default.join(n.USERPROFILE,".bun","bin","bun.exe"):void 0,n.LOCALAPPDATA?yi.default.join(n.LOCALAPPDATA,"bun","bun.exe"):void 0,n.LOCALAPPDATA?yi.default.join(n.LOCALAPPDATA,"bun","bin","bun.exe"):void 0];for(let c of a){let u=c?.trim();if(u&&(CA(u)&&s(u)||u.toLowerCase()==="bun"))return u}return o("bun",e)}function NA(t){(0,zt.mkdirSync)(W0,{recursive:!0}),(0,zt.writeFileSync)(_i,JSON.stringify(t,null,2))}function K0(){if(!(0,zt.existsSync)(_i))return null;try{return JSON.parse((0,zt.readFileSync)(_i,"utf-8"))}catch(t){return y.warn("SYSTEM","Failed to parse PID file",{path:_i},t),null}}function _o(){if((0,zt.existsSync)(_i))try{(0,zt.unlinkSync)(_i)}catch(t){y.warn("SYSTEM","Failed to remove PID file",{path:_i},t)}}function es(t){return process.platform==="win32"?Math.round(t*2):t}function MK(t){if(!t||t.trim()==="")return-1;let e=t.trim(),r=0,n=e.match(/^(\d+)-(\d+):(\d+):(\d+)$/);if(n)return r=parseInt(n[1],10)*24*60+parseInt(n[2],10)*60+parseInt(n[3],10),r;let i=e.match(/^(\d+):(\d+):(\d+)$/);if(i)return r=parseInt(i[1],10)*60+parseInt(i[2],10),r;let s=e.match(/^(\d+):(\d+)$/);return s?parseInt(s[1],10):-1}var V0=["worker-service.cjs","chroma-mcp"],DK=["mcp-server.cjs"];async function MA(){let t=process.platform==="win32",e=process.pid,r=[],n=[...V0,...DK];try{if(t){let s=`powershell -NoProfile -NonInteractive -Command "Get-CimInstance Win32_Process -Filter '(${n.map(l=>`CommandLine LIKE '%${l}%'`).join(" OR ")}) AND ProcessId != ${e}' | Select-Object ProcessId, CommandLine, CreationDate | ConvertTo-Json"`,{stdout:o}=await OA(s,{timeout:yr.POWERSHELL_COMMAND,windowsHide:!0});if(!o.trim()||o.trim()==="null"){y.debug("SYSTEM","No orphaned claude-mem processes found (Windows)");return}let a=JSON.parse(o),c=Array.isArray(a)?a:[a],u=Date.now();for(let l of c){let d=l.ProcessId;if(!Number.isInteger(d)||d<=0||d===e)continue;let p=l.CommandLine||"";if(V0.some(f=>p.includes(f)))r.push(d),y.debug("SYSTEM","Found orphaned process (aggressive)",{pid:d,commandLine:p.substring(0,80)});else{let f=l.CreationDate?.match(/\/Date\((\d+)\)\//);if(f){let g=parseInt(f[1],10),h=(u-g)/(1e3*60);h>=PA&&(r.push(d),y.debug("SYSTEM","Found orphaned process (age-gated)",{pid:d,ageMinutes:Math.round(h)}))}}}}else{let i=n.join("|"),{stdout:s}=await OA(`ps -eo pid,etime,command | grep -E "${i}" | grep -v grep || true`);if(!s.trim()){y.debug("SYSTEM","No orphaned claude-mem processes found (Unix)");return}let o=s.trim().split(`
922
- `);for(let a of o){let c=a.trim().match(/^(\d+)\s+(\S+)\s+(.*)$/);if(!c)continue;let u=parseInt(c[1],10),l=c[2],d=c[3];if(!Number.isInteger(u)||u<=0||u===e)continue;if(V0.some(m=>d.includes(m)))r.push(u),y.debug("SYSTEM","Found orphaned process (aggressive)",{pid:u,command:d.substring(0,80)});else{let m=MK(l);m>=PA&&(r.push(u),y.debug("SYSTEM","Found orphaned process (age-gated)",{pid:u,ageMinutes:m,command:d.substring(0,80)}))}}}}catch(i){y.error("SYSTEM","Failed to enumerate orphaned processes during aggressive cleanup",{},i);return}if(r.length!==0){if(y.info("SYSTEM","Aggressive startup cleanup: killing orphaned processes",{platform:t?"Windows":"Unix",count:r.length,pids:r}),t){for(let i of r)if(!(!Number.isInteger(i)||i<=0))try{(0,Qi.execSync)(`taskkill /PID ${i} /T /F`,{timeout:yr.POWERSHELL_COMMAND,stdio:"ignore",windowsHide:!0})}catch(s){y.debug("SYSTEM","Failed to kill process, may have already exited",{pid:i},s)}}else for(let i of r)try{process.kill(i,"SIGKILL")}catch(s){y.debug("SYSTEM","Process already exited",{pid:i},s)}y.info("SYSTEM","Aggressive startup cleanup complete",{count:r.length})}}var jK=".chroma-cleaned-v10.3";function DA(t){let e=t??W0,r=yi.default.join(e,jK),n=yi.default.join(e,"chroma");if((0,zt.existsSync)(r)){y.debug("SYSTEM","Chroma migration marker exists, skipping wipe");return}y.warn("SYSTEM","Running one-time chroma data wipe (upgrade from pre-v10.3)",{chromaDir:n}),(0,zt.existsSync)(n)&&((0,zt.rmSync)(n,{recursive:!0,force:!0}),y.info("SYSTEM","Chroma data directory removed",{chromaDir:n})),(0,zt.mkdirSync)(e,{recursive:!0}),(0,zt.writeFileSync)(r,new Date().toISOString()),y.info("SYSTEM","Chroma migration marker written",{markerPath:r})}function J0(t,e,r={}){let n=process.platform==="win32";gt().assertCanSpawn("worker daemon");let i=vi({...process.env,CLAUDE_MEM_WORKER_PORT:String(e),...r});if(n){let a=NK();if(!a){y.error("SYSTEM","Failed to locate Bun runtime for Windows worker spawn");return}let c=a.replace(/'/g,"''"),u=t.replace(/'/g,"''"),l=`Start-Process -FilePath '${c}' -ArgumentList '${u}','--daemon' -WindowStyle Hidden`;try{return(0,Qi.execSync)(`powershell -NoProfile -Command "${l}"`,{stdio:"ignore",windowsHide:!0,env:i}),0}catch(d){y.error("SYSTEM","Failed to spawn worker daemon on Windows",{runtimePath:a},d);return}}let s="/usr/bin/setsid";if((0,zt.existsSync)(s)){let a=(0,Qi.spawn)(s,[process.execPath,t,"--daemon"],{detached:!0,stdio:"ignore",env:i});return a.pid===void 0?void 0:(a.unref(),a.pid)}let o=(0,Qi.spawn)(process.execPath,[t,"--daemon"],{detached:!0,stdio:"ignore",env:i});if(o.pid!==void 0)return o.unref(),o.pid}function jA(t){if(t===0)return!0;if(!Number.isInteger(t)||t<0)return!1;try{return process.kill(t,0),!0}catch(e){return e.code==="EPERM"}}function zA(t=15e3){try{let e=(0,zt.statSync)(_i);return Date.now()-e.mtimeMs<t}catch{return!1}}function LA(){try{if(!(0,zt.existsSync)(_i))return;let t=new Date;(0,zt.utimesSync)(_i,t,t)}catch{}}function UA(){return q0({logAlive:!1})}var qA=Ge(require("path"),1),FA=require("fs");oe();Dt();async function X0(t,e,r="GET"){let n=await fetch(`http://127.0.0.1:${t}${e}`,{method:r}),i="";try{i=await n.text()}catch{}return{ok:n.ok,statusCode:n.status,body:i}}async function Wl(t){try{return(await fetch(`http://127.0.0.1:${t}/api/health`)).ok}catch{return!1}}async function HA(t,e,r,n){let i=Date.now();for(;Date.now()-i<r;){try{if((await X0(t,e)).ok)return!0}catch(s){y.debug("SYSTEM",n,{},s)}await new Promise(s=>setTimeout(s,500))}return!1}function bo(t,e=3e4){return HA(t,"/api/health",e,"Service not ready yet, will retry")}function ZA(t,e=3e4){return HA(t,"/api/readiness",e,"Worker not ready yet, will retry")}async function Bf(t,e=1e4){let r=Date.now();for(;Date.now()-r<e;){if(!await Wl(t))return!0;await new Promise(n=>setTimeout(n,500))}return!1}async function Vf(t){try{let e=await X0(t,"/api/admin/shutdown","POST");return e.ok?!0:(y.warn("SYSTEM","Shutdown request returned error",{status:e.statusCode}),!1)}catch(e){return e instanceof Error&&e.message?.includes("ECONNREFUSED")?(y.debug("SYSTEM","Worker already stopped",{},e),!1):(y.error("SYSTEM","Shutdown request failed unexpectedly",{},e),!1)}}function zK(){try{let t=qA.default.join(Ki,"package.json");return JSON.parse((0,FA.readFileSync)(t,"utf-8")).version}catch(t){let e=t.code;if(e==="ENOENT"||e==="EBUSY")return y.debug("SYSTEM","Could not read plugin version (shutdown race)",{code:e}),"unknown";throw t}}async function LK(t){try{let e=await X0(t,"/api/version");return e.ok?JSON.parse(e.body).version:null}catch{return y.debug("SYSTEM","Could not fetch worker version",{}),null}}async function BA(t){let e=zK(),r=await LK(t);return!r||e==="unknown"?{matches:!0,pluginVersion:e,workerVersion:r}:{matches:e===r,pluginVersion:e,workerVersion:r}}oe();async function VA(t){y.info("SYSTEM","Shutdown initiated"),t.server&&(await UK(t.server),y.info("SYSTEM","HTTP server closed")),await t.sessionManager.shutdownAll(),t.mcpClient&&(await t.mcpClient.close(),y.info("SYSTEM","MCP client closed")),t.chromaMcpManager&&(y.info("SHUTDOWN","Stopping Chroma MCP connection..."),await t.chromaMcpManager.stop(),y.info("SHUTDOWN","Chroma MCP connection stopped")),t.dbManager&&await t.dbManager.close(),await SA(),y.info("SYSTEM","Worker shutdown complete")}async function UK(t){t.closeAllConnections(),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),await new Promise((e,r)=>{t.close(n=>n?r(n):e())}),process.platform==="win32"&&(await new Promise(e=>setTimeout(e,500)),y.info("SYSTEM","Waited for Windows port cleanup"))}var rU=Ge(Qh(),1),nk=Ge(require("fs"),1),Ad=Ge(require("path"),1);var HL=["search","context","summarize","import","export"],ZL=["workflow","search_params","examples","all"];oe();var ek=Ge(Qh(),1),JL=Ge(KL(),1),XL=Ge(require("path"),1);Dt();oe();function tk(t){let e=[];e.push(ek.default.json({limit:"50mb"})),e.push((0,JL.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 g=Date.now()-l;return y.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${g}ms`}),m(f)},o()});let r=Qr(),n=XL.default.join(r,"plugin","ui");return e.push(ek.default.static(n)),e}function Cd(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 rk(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":""}oe();var Ec=class extends Error{constructor(r,n=500,i,s){super(r);this.statusCode=n;this.code=i;this.details=s;this.name="AppError"}};function YL(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var QL=(t,e,r,n)=>{let i=t instanceof Ec?t.statusCode:500;y.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof Ec?t.code:void 0},t);let s=YL(t.name||"Error",t.message,t instanceof Ec?t.code:void 0,t instanceof Ec?t.details:void 0);r.status(i).json(s)};function eU(t,e){e.status(404).json(YL("NotFound",`Cannot ${t.method} ${t.path}`))}var tU="10.5.6",eg=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,rU.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(eU),this.app.use(QL)}setupMiddleware(){tk(rk).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:tU,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:tU})}),this.app.get("/api/instructions",async(e,r)=>{let n=e.query.topic||"all",i=e.query.operation;if(n&&!ZL.includes(n))return r.status(400).json({error:"Invalid topic"});try{let s;if(i){if(!HL.includes(i))return r.status(400).json({error:"Invalid operation"});let o=Ad.default.resolve(__dirname,"../skills/mem-search/operations"),a=Ad.default.resolve(o,`${i}.md`);if(!a.startsWith(o+Ad.default.sep))return r.status(400).json({error:"Invalid request"});s=await nk.promises.readFile(a,"utf-8")}else{let o=Ad.default.join(__dirname,"../skills/mem-search/SKILL.md"),a=await nk.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",Cd,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",Cd,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",Cd,(e,r)=>{let o=gt().getRegistry().getAll().map(f=>({id:f.id,pid:f.pid,type:f.type,status:vn(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=>M0.has(f)||N0.some(g=>f.startsWith(g))),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 yt=Ge(require("path"),1),Md=require("os"),Kt=require("fs"),sU=require("child_process"),oU=require("util");oe();qr();Dt();var Mn=require("fs"),Nd=require("path");oe();function nU(t){try{return(0,Mn.existsSync)(t)?JSON.parse((0,Mn.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 iU(t,e){let r=(0,Nd.join)(t,"..");(0,Mn.mkdirSync)(r,{recursive:!0}),(0,Mn.writeFileSync)(t,JSON.stringify(e,null,2))}function ik(t,e){let r=(0,Nd.join)(t,".cursor","rules"),n=(0,Nd.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,Mn.mkdirSync)(r,{recursive:!0});let s=`---
922
+ `);for(let a of o){let c=a.trim().match(/^(\d+)\s+(\S+)\s+(.*)$/);if(!c)continue;let u=parseInt(c[1],10),l=c[2],d=c[3];if(!Number.isInteger(u)||u<=0||u===e)continue;if(V0.some(m=>d.includes(m)))r.push(u),y.debug("SYSTEM","Found orphaned process (aggressive)",{pid:u,command:d.substring(0,80)});else{let m=MK(l);m>=PA&&(r.push(u),y.debug("SYSTEM","Found orphaned process (age-gated)",{pid:u,ageMinutes:m,command:d.substring(0,80)}))}}}}catch(i){y.error("SYSTEM","Failed to enumerate orphaned processes during aggressive cleanup",{},i);return}if(r.length!==0){if(y.info("SYSTEM","Aggressive startup cleanup: killing orphaned processes",{platform:t?"Windows":"Unix",count:r.length,pids:r}),t){for(let i of r)if(!(!Number.isInteger(i)||i<=0))try{(0,Qi.execSync)(`taskkill /PID ${i} /T /F`,{timeout:yr.POWERSHELL_COMMAND,stdio:"ignore",windowsHide:!0})}catch(s){y.debug("SYSTEM","Failed to kill process, may have already exited",{pid:i},s)}}else for(let i of r)try{process.kill(i,"SIGKILL")}catch(s){y.debug("SYSTEM","Process already exited",{pid:i},s)}y.info("SYSTEM","Aggressive startup cleanup complete",{count:r.length})}}var jK=".chroma-cleaned-v10.3";function DA(t){let e=t??W0,r=yi.default.join(e,jK),n=yi.default.join(e,"chroma");if((0,zt.existsSync)(r)){y.debug("SYSTEM","Chroma migration marker exists, skipping wipe");return}y.warn("SYSTEM","Running one-time chroma data wipe (upgrade from pre-v10.3)",{chromaDir:n}),(0,zt.existsSync)(n)&&((0,zt.rmSync)(n,{recursive:!0,force:!0}),y.info("SYSTEM","Chroma data directory removed",{chromaDir:n})),(0,zt.mkdirSync)(e,{recursive:!0}),(0,zt.writeFileSync)(r,new Date().toISOString()),y.info("SYSTEM","Chroma migration marker written",{markerPath:r})}function J0(t,e,r={}){let n=process.platform==="win32";gt().assertCanSpawn("worker daemon");let i=vi({...process.env,CLAUDE_MEM_WORKER_PORT:String(e),...r});if(n){let a=NK();if(!a){y.error("SYSTEM","Failed to locate Bun runtime for Windows worker spawn");return}let c=a.replace(/'/g,"''"),u=t.replace(/'/g,"''"),l=`Start-Process -FilePath '${c}' -ArgumentList '${u}','--daemon' -WindowStyle Hidden`;try{return(0,Qi.execSync)(`powershell -NoProfile -Command "${l}"`,{stdio:"ignore",windowsHide:!0,env:i}),0}catch(d){y.error("SYSTEM","Failed to spawn worker daemon on Windows",{runtimePath:a},d);return}}let s="/usr/bin/setsid";if((0,zt.existsSync)(s)){let a=(0,Qi.spawn)(s,[process.execPath,t,"--daemon"],{detached:!0,stdio:"ignore",env:i});return a.pid===void 0?void 0:(a.unref(),a.pid)}let o=(0,Qi.spawn)(process.execPath,[t,"--daemon"],{detached:!0,stdio:"ignore",env:i});if(o.pid!==void 0)return o.unref(),o.pid}function jA(t){if(t===0)return!0;if(!Number.isInteger(t)||t<0)return!1;try{return process.kill(t,0),!0}catch(e){return e.code==="EPERM"}}function zA(t=15e3){try{let e=(0,zt.statSync)(_i);return Date.now()-e.mtimeMs<t}catch{return!1}}function LA(){try{if(!(0,zt.existsSync)(_i))return;let t=new Date;(0,zt.utimesSync)(_i,t,t)}catch{}}function UA(){return q0({logAlive:!1})}var qA=Ge(require("path"),1),FA=require("fs");oe();Dt();async function X0(t,e,r="GET"){let n=await fetch(`http://127.0.0.1:${t}${e}`,{method:r}),i="";try{i=await n.text()}catch{}return{ok:n.ok,statusCode:n.status,body:i}}async function Wl(t){try{return(await fetch(`http://127.0.0.1:${t}/api/health`)).ok}catch{return!1}}async function HA(t,e,r,n){let i=Date.now();for(;Date.now()-i<r;){try{if((await X0(t,e)).ok)return!0}catch(s){y.debug("SYSTEM",n,{},s)}await new Promise(s=>setTimeout(s,500))}return!1}function bo(t,e=3e4){return HA(t,"/api/health",e,"Service not ready yet, will retry")}function ZA(t,e=3e4){return HA(t,"/api/readiness",e,"Worker not ready yet, will retry")}async function Bf(t,e=1e4){let r=Date.now();for(;Date.now()-r<e;){if(!await Wl(t))return!0;await new Promise(n=>setTimeout(n,500))}return!1}async function Vf(t){try{let e=await X0(t,"/api/admin/shutdown","POST");return e.ok?!0:(y.warn("SYSTEM","Shutdown request returned error",{status:e.statusCode}),!1)}catch(e){return e instanceof Error&&e.message?.includes("ECONNREFUSED")?(y.debug("SYSTEM","Worker already stopped",{},e),!1):(y.error("SYSTEM","Shutdown request failed unexpectedly",{},e),!1)}}function zK(){try{let t=qA.default.join(Ki,"package.json");return JSON.parse((0,FA.readFileSync)(t,"utf-8")).version}catch(t){let e=t.code;if(e==="ENOENT"||e==="EBUSY")return y.debug("SYSTEM","Could not read plugin version (shutdown race)",{code:e}),"unknown";throw t}}async function LK(t){try{let e=await X0(t,"/api/version");return e.ok?JSON.parse(e.body).version:null}catch{return y.debug("SYSTEM","Could not fetch worker version",{}),null}}async function BA(t){let e=zK(),r=await LK(t);return!r||e==="unknown"?{matches:!0,pluginVersion:e,workerVersion:r}:{matches:e===r,pluginVersion:e,workerVersion:r}}oe();async function VA(t){y.info("SYSTEM","Shutdown initiated"),t.server&&(await UK(t.server),y.info("SYSTEM","HTTP server closed")),await t.sessionManager.shutdownAll(),t.mcpClient&&(await t.mcpClient.close(),y.info("SYSTEM","MCP client closed")),t.chromaMcpManager&&(y.info("SHUTDOWN","Stopping Chroma MCP connection..."),await t.chromaMcpManager.stop(),y.info("SHUTDOWN","Chroma MCP connection stopped")),t.dbManager&&await t.dbManager.close(),await SA(),y.info("SYSTEM","Worker shutdown complete")}async function UK(t){t.closeAllConnections(),process.platform==="win32"&&await new Promise(e=>setTimeout(e,500)),await new Promise((e,r)=>{t.close(n=>n?r(n):e())}),process.platform==="win32"&&(await new Promise(e=>setTimeout(e,500)),y.info("SYSTEM","Waited for Windows port cleanup"))}var rU=Ge(Qh(),1),nk=Ge(require("fs"),1),Ad=Ge(require("path"),1);var HL=["search","context","summarize","import","export"],ZL=["workflow","search_params","examples","all"];oe();var ek=Ge(Qh(),1),JL=Ge(KL(),1),XL=Ge(require("path"),1);Dt();oe();function tk(t){let e=[];e.push(ek.default.json({limit:"50mb"})),e.push((0,JL.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 g=Date.now()-l;return y.debug("HTTP",`\u2190 ${s.statusCode} ${i.path}`,{requestId:d,duration:`${g}ms`}),m(f)},o()});let r=Qr(),n=XL.default.join(r,"plugin","ui");return e.push(ek.default.static(n)),e}function Cd(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 rk(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":""}oe();var Ec=class extends Error{constructor(r,n=500,i,s){super(r);this.statusCode=n;this.code=i;this.details=s;this.name="AppError"}};function YL(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var QL=(t,e,r,n)=>{let i=t instanceof Ec?t.statusCode:500;y.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof Ec?t.code:void 0},t);let s=YL(t.name||"Error",t.message,t instanceof Ec?t.code:void 0,t instanceof Ec?t.details:void 0);r.status(i).json(s)};function eU(t,e){e.status(404).json(YL("NotFound",`Cannot ${t.method} ${t.path}`))}var tU="10.6.0",eg=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,rU.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(eU),this.app.use(QL)}setupMiddleware(){tk(rk).forEach(r=>this.app.use(r))}setupCoreRoutes(){this.app.get("/api/health",(e,r)=>{r.status(200).json({status:"ok",version:tU,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:tU})}),this.app.get("/api/instructions",async(e,r)=>{let n=e.query.topic||"all",i=e.query.operation;if(n&&!ZL.includes(n))return r.status(400).json({error:"Invalid topic"});try{let s;if(i){if(!HL.includes(i))return r.status(400).json({error:"Invalid operation"});let o=Ad.default.resolve(__dirname,"../skills/mem-search/operations"),a=Ad.default.resolve(o,`${i}.md`);if(!a.startsWith(o+Ad.default.sep))return r.status(400).json({error:"Invalid request"});s=await nk.promises.readFile(a,"utf-8")}else{let o=Ad.default.join(__dirname,"../skills/mem-search/SKILL.md"),a=await nk.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",Cd,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",Cd,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",Cd,(e,r)=>{let o=gt().getRegistry().getAll().map(f=>({id:f.id,pid:f.pid,type:f.type,status:vn(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=>M0.has(f)||N0.some(g=>f.startsWith(g))),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 yt=Ge(require("path"),1),Md=require("os"),Kt=require("fs"),sU=require("child_process"),oU=require("util");oe();qr();Dt();var Mn=require("fs"),Nd=require("path");oe();function nU(t){try{return(0,Mn.existsSync)(t)?JSON.parse((0,Mn.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 iU(t,e){let r=(0,Nd.join)(t,"..");(0,Mn.mkdirSync)(r,{recursive:!0}),(0,Mn.writeFileSync)(t,JSON.stringify(e,null,2))}function ik(t,e){let r=(0,Nd.join)(t,".cursor","rules"),n=(0,Nd.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,Mn.mkdirSync)(r,{recursive:!0});let s=`---
923
923
  alwaysApply: true
924
924
  description: "Claude-mem context from past sessions (auto-updated)"
925
925
  ---
@@ -1428,7 +1428,7 @@ Tips:
1428
1428
  `&&u++;if(u>=e||f===0)break;a=Math.min(a*2,i,o)}let l=c.split(`
1429
1429
  `);l.length>0&&l[l.length-1]===""&&l.pop();let d=Math.max(0,l.length-e),p=l.slice(d),m;if(i<=a)m=l.length;else{let f=c.length/Math.max(u,1);m=Math.round(i/f)}return{lines:p.join(`
1430
1430
  `),totalEstimate:m}}finally{(0,bn.closeSync)(r)}}var fv=class extends Cr{getLogFilePath(){let e=Ee.get("CLAUDE_MEM_DATA_DIR"),r=(0,mv.join)(e,"logs"),n=new Date().toISOString().split("T")[0];return(0,mv.join)(r,`claude-mem-${n}.log`)}getLogsDir(){let e=Ee.get("CLAUDE_MEM_DATA_DIR");return(0,mv.join)(e,"logs")}setupRoutes(e){e.get("/api/logs",this.handleGetLogs.bind(this)),e.post("/api/logs/clear",this.handleClearLogs.bind(this))}handleGetLogs=this.wrapHandler((e,r)=>{let n=this.getLogFilePath();if(!(0,bn.existsSync)(n)){r.json({logs:"",path:n,exists:!1});return}let i=parseInt(e.query.lines||"1000",10),s=Math.min(i,1e4),{lines:o,totalEstimate:a}=nge(n,s),c=o===""?0:o.split(`
1431
- `).length;r.json({logs:o,path:n,exists:!0,totalLines:a,returnedLines:c})});handleClearLogs=this.wrapHandler((e,r)=>{let n=this.getLogFilePath();if(!(0,bn.existsSync)(n)){r.json({success:!0,message:"Log file does not exist",path:n});return}(0,bn.writeFileSync)(n,"","utf-8"),y.info("SYSTEM","Log file cleared via UI",{path:n}),r.json({success:!0,message:"Log file cleared",path:n})})};oe();var hv=class extends Cr{constructor(r,n){super();this.dbManager=r;this.defaultProject=n}setupRoutes(r){r.post("/api/memory/save",this.handleSaveMemory.bind(this))}handleSaveMemory=this.wrapHandler(async(r,n)=>{let{text:i,title:s,project:o}=r.body,a=o||this.defaultProject;if(!i||typeof i!="string"||i.trim().length===0){this.badRequest(n,"text is required and must be non-empty");return}let c=this.dbManager.getSessionStore(),u=this.dbManager.getChromaSync(),l=c.getOrCreateManualSession(a),d={type:"discovery",title:s||i.substring(0,60).trim()+(i.length>60?"...":""),subtitle:"Manual memory",facts:[],narrative:i,concepts:[],files_read:[],files_modified:[]},p=c.storeObservation(l,a,d,0,0);y.info("HTTP","Manual observation saved",{id:p.id,project:a,title:d.title}),u.syncObservation(p.id,l,a,d,0,p.createdAtEpoch,0).catch(m=>{y.error("CHROMA","ChromaDB sync failed",{id:p.id},m)}),n.json({success:!0,id:p.id,title:d.title,project:a,message:`Memory saved as observation #${p.id}`})})};var Cge={},Ege=120*1e3;function F$(){return q$.default.join(Ee.get("CLAUDE_MEM_DATA_DIR"),".worker-start-attempted")}function kge(){if(process.platform!=="win32")return!1;let t=F$();if(!(0,ms.existsSync)(t))return!1;try{let e=(0,ms.statSync)(t).mtimeMs;return Date.now()-e<Ege}catch{return!1}}function $ge(){if(process.platform==="win32")try{(0,ms.writeFileSync)(F$(),"","utf-8")}catch{}}function Tge(){if(process.platform==="win32")try{let t=F$();(0,ms.existsSync)(t)&&(0,ms.unlinkSync)(t)}catch{}}var Ige="10.5.6";function L9(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var yv=class{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;searchRoutes=null;chromaMcpManager=null;initializationComplete;resolveInitialization;stopOrphanReaper=null;staleSessionReaperInterval=null;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new rg,this.sessionManager=new og(this.dbManager),this.sseBroadcaster=new ag,this.sdkAgent=new Lg(this.dbManager,this.sessionManager),this.geminiAgent=new Ug(this.dbManager,this.sessionManager),this.openRouterAgent=new Hg(this.dbManager,this.sessionManager),this.paginationHelper=new Zg(this.dbManager),this.settingsManager=new Bg(this.dbManager),this.sessionEventBroadcaster=new Kg(this.sseBroadcaster,this),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Ha({name:"worker-search-proxy",version:Ige},{capabilities:{}}),this.server=new eg({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return eu()&&Go()?e="openrouter":Qc()&&Vo()&&(e="gemini"),{provider:e,authMethod:Df(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){wA(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 Xg(this.sseBroadcaster,this.dbManager,this.sessionManager)),this.server.registerRoutes(new ev(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this)),this.server.registerRoutes(new tv(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new pv(this.settingsManager)),this.server.registerRoutes(new fv),this.server.registerRoutes(new hv(this.dbManager,"claude-mem"))}async start(){let e=Ur(),r=O0();await xA(),await this.server.listen(e,r),NA({pid:process.pid,port:e,startedAt:new Date().toISOString()}),gt().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 MA();let{ModeManager:e}=await Promise.resolve().then(()=>(Zr(),wU)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(tr(),JC)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(Dt(),iA)),i=r.loadFromFile(n);(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&DA(),i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Xi.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(()=>(Us(),zo)),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 Gg,d=new Wg,p=new Vg(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),l,d);this.searchRoutes=new uv(p),this.server.registerRoutes(this.searchRoutes),y.info("WORKER","SearchManager initialized and search routes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),y.info("SYSTEM","Core initialization complete (DB + search ready)"),this.chromaMcpManager&&Ja.backfillAllProjects().then(()=>{y.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(_=>{y.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},_)});let m=q$.default.join(__dirname,"mcp-server.cjs");gt().assertCanSpawn("mcp server");let f=new Va({command:"node",args:[m],env:vi(process.env)}),g=3e5,h=this.mcpClient.connect(f),v,x=new Promise((_,S)=>{v=setTimeout(()=>S(new Error("MCP connection timeout after 5 minutes")),g)});try{await Promise.race([h,x])}catch(_){clearTimeout(v),y.warn("WORKER","MCP server connection failed, cleaning up subprocess",{error:_ instanceof Error?_.message:String(_)});try{await f.close()}catch{}throw _}clearTimeout(v);let b=f._process;b?.pid&&(gt().registerProcess("mcp-server",{pid:b.pid,type:"mcp",startedAt:new Date().toISOString()},b),b.once("exit",()=>{gt().unregisterProcess("mcp-server")})),this.mcpReady=!0,y.success("WORKER","MCP server connected"),this.stopOrphanReaper=xU(()=>{let _=new Set;for(let[S]of this.sessionManager.sessions)_.add(S);return _}),y.info("SYSTEM","Started orphan reaper (runs every 30 seconds)"),this.staleSessionReaperInterval=setInterval(async()=>{try{let _=await this.sessionManager.reapStaleSessions();_>0&&y.info("SYSTEM",`Reaped ${_} stale sessions`)}catch(_){y.error("SYSTEM","Stale session reaper error",{error:_ instanceof Error?_.message:String(_)})}},120*1e3),this.processPendingQueues(50).then(_=>{_.sessionsStarted>0&&y.info("SYSTEM",`Auto-recovered ${_.sessionsStarted} sessions with pending work`,{totalPending:_.totalPendingSessions,started:_.sessionsStarted,sessionIds:_.startedSessionIds})}).catch(_=>{y.error("SYSTEM","Auto-recovery of pending queues failed",{},_)})}catch(e){throw y.error("SYSTEM","Background initialization failed",{},e),e}}getActiveAgent(){return eu()&&Go()?this.openRouterAgent:Qc()&&Vo()?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","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=qs(e.sessionDbId);if(c&&c.process.exitCode===null&&await Fs(c,5e3),e.generatorPromise=null,!a&&!o&&(this.lastAiInteraction={timestamp:Date.now(),success:!0,provider:s}),o){y.warn("SYSTEM","Skipping restart due to unrecoverable error",{sessionId:e.sessionDbId}),this.broadcastProcessingStatus();return}let{PendingMessageStore:u}=(Us(),ou(zo)),l=new u(this.dbManager.getSessionStore().db,3);if(e.idleTimedOut){y.info("SYSTEM","Generator exited due to idle timeout, not restarting",{sessionId:e.sessionDbId}),e.idleTimedOut=!1,this.broadcastProcessingStatus();return}let d=l.getPendingCount(e.sessionDbId),p=3;if(d>0){if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,e.consecutiveRestarts>p){y.error("SYSTEM","Exceeded max pending-work restarts, stopping to prevent infinite loop",{sessionId:e.sessionDbId,pendingCount:d,consecutiveRestarts:e.consecutiveRestarts}),e.consecutiveRestarts=0,this.broadcastProcessingStatus();return}y.info("SYSTEM","Pending work remains after generator exit, restarting with fresh AbortController",{sessionId:e.sessionDbId,pendingCount:d,attempt:e.consecutiveRestarts}),e.abortController=new AbortController,this.startSessionProcessor(e,"pending-work-restart")}else e.consecutiveRestarts=0;this.broadcastProcessingStatus()})}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(Vo())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(Go())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)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(Us(),zo)),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(`
1431
+ `).length;r.json({logs:o,path:n,exists:!0,totalLines:a,returnedLines:c})});handleClearLogs=this.wrapHandler((e,r)=>{let n=this.getLogFilePath();if(!(0,bn.existsSync)(n)){r.json({success:!0,message:"Log file does not exist",path:n});return}(0,bn.writeFileSync)(n,"","utf-8"),y.info("SYSTEM","Log file cleared via UI",{path:n}),r.json({success:!0,message:"Log file cleared",path:n})})};oe();var hv=class extends Cr{constructor(r,n){super();this.dbManager=r;this.defaultProject=n}setupRoutes(r){r.post("/api/memory/save",this.handleSaveMemory.bind(this))}handleSaveMemory=this.wrapHandler(async(r,n)=>{let{text:i,title:s,project:o}=r.body,a=o||this.defaultProject;if(!i||typeof i!="string"||i.trim().length===0){this.badRequest(n,"text is required and must be non-empty");return}let c=this.dbManager.getSessionStore(),u=this.dbManager.getChromaSync(),l=c.getOrCreateManualSession(a),d={type:"discovery",title:s||i.substring(0,60).trim()+(i.length>60?"...":""),subtitle:"Manual memory",facts:[],narrative:i,concepts:[],files_read:[],files_modified:[]},p=c.storeObservation(l,a,d,0,0);y.info("HTTP","Manual observation saved",{id:p.id,project:a,title:d.title}),u.syncObservation(p.id,l,a,d,0,p.createdAtEpoch,0).catch(m=>{y.error("CHROMA","ChromaDB sync failed",{id:p.id},m)}),n.json({success:!0,id:p.id,title:d.title,project:a,message:`Memory saved as observation #${p.id}`})})};var Cge={},Ege=120*1e3;function F$(){return q$.default.join(Ee.get("CLAUDE_MEM_DATA_DIR"),".worker-start-attempted")}function kge(){if(process.platform!=="win32")return!1;let t=F$();if(!(0,ms.existsSync)(t))return!1;try{let e=(0,ms.statSync)(t).mtimeMs;return Date.now()-e<Ege}catch{return!1}}function $ge(){if(process.platform==="win32")try{(0,ms.writeFileSync)(F$(),"","utf-8")}catch{}}function Tge(){if(process.platform==="win32")try{let t=F$();(0,ms.existsSync)(t)&&(0,ms.unlinkSync)(t)}catch{}}var Ige="10.6.0";function L9(t,e){return{continue:!0,suppressOutput:!0,status:t,...e&&{message:e}}}var yv=class{server;startTime=Date.now();mcpClient;mcpReady=!1;initializationCompleteFlag=!1;isShuttingDown=!1;dbManager;sessionManager;sseBroadcaster;sdkAgent;geminiAgent;openRouterAgent;paginationHelper;settingsManager;sessionEventBroadcaster;searchRoutes=null;chromaMcpManager=null;initializationComplete;resolveInitialization;stopOrphanReaper=null;staleSessionReaperInterval=null;lastAiInteraction=null;constructor(){this.initializationComplete=new Promise(e=>{this.resolveInitialization=e}),this.dbManager=new rg,this.sessionManager=new og(this.dbManager),this.sseBroadcaster=new ag,this.sdkAgent=new Lg(this.dbManager,this.sessionManager),this.geminiAgent=new Ug(this.dbManager,this.sessionManager),this.openRouterAgent=new Hg(this.dbManager,this.sessionManager),this.paginationHelper=new Zg(this.dbManager),this.settingsManager=new Bg(this.dbManager),this.sessionEventBroadcaster=new Kg(this.sseBroadcaster,this),this.sessionManager.setOnSessionDeleted(()=>{this.broadcastProcessingStatus()}),this.mcpClient=new Ha({name:"worker-search-proxy",version:Ige},{capabilities:{}}),this.server=new eg({getInitializationComplete:()=>this.initializationCompleteFlag,getMcpReady:()=>this.mcpReady,onShutdown:()=>this.shutdown(),onRestart:()=>this.shutdown(),workerPath:__filename,getAiStatus:()=>{let e="claude";return eu()&&Go()?e="openrouter":Qc()&&Vo()&&(e="gemini"),{provider:e,authMethod:Df(),lastInteraction:this.lastAiInteraction?{timestamp:this.lastAiInteraction.timestamp,success:this.lastAiInteraction.success,...this.lastAiInteraction.error&&{error:this.lastAiInteraction.error}}:null}}}),this.registerRoutes(),this.registerSignalHandlers()}registerSignalHandlers(){wA(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 Xg(this.sseBroadcaster,this.dbManager,this.sessionManager)),this.server.registerRoutes(new ev(this.sessionManager,this.dbManager,this.sdkAgent,this.geminiAgent,this.openRouterAgent,this.sessionEventBroadcaster,this)),this.server.registerRoutes(new tv(this.paginationHelper,this.dbManager,this.sessionManager,this.sseBroadcaster,this,this.startTime)),this.server.registerRoutes(new pv(this.settingsManager)),this.server.registerRoutes(new fv),this.server.registerRoutes(new hv(this.dbManager,"claude-mem"))}async start(){let e=Ur(),r=O0();await xA(),await this.server.listen(e,r),NA({pid:process.pid,port:e,startedAt:new Date().toISOString()}),gt().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 MA();let{ModeManager:e}=await Promise.resolve().then(()=>(Zr(),wU)),{SettingsDefaultsManager:r}=await Promise.resolve().then(()=>(tr(),JC)),{USER_SETTINGS_PATH:n}=await Promise.resolve().then(()=>(Dt(),iA)),i=r.loadFromFile(n);(i.CLAUDE_MEM_MODE==="local"||!i.CLAUDE_MEM_MODE)&&DA(),i.CLAUDE_MEM_CHROMA_ENABLED!=="false"?(this.chromaMcpManager=Xi.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(()=>(Us(),zo)),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 Gg,d=new Wg,p=new Vg(this.dbManager.getSessionSearch(),this.dbManager.getSessionStore(),this.dbManager.getChromaSync(),l,d);this.searchRoutes=new uv(p),this.server.registerRoutes(this.searchRoutes),y.info("WORKER","SearchManager initialized and search routes registered"),this.initializationCompleteFlag=!0,this.resolveInitialization(),y.info("SYSTEM","Core initialization complete (DB + search ready)"),this.chromaMcpManager&&Ja.backfillAllProjects().then(()=>{y.info("CHROMA_SYNC","Backfill check complete for all projects")}).catch(_=>{y.error("CHROMA_SYNC","Backfill failed (non-blocking)",{},_)});let m=q$.default.join(__dirname,"mcp-server.cjs");gt().assertCanSpawn("mcp server");let f=new Va({command:"node",args:[m],env:vi(process.env)}),g=3e5,h=this.mcpClient.connect(f),v,x=new Promise((_,S)=>{v=setTimeout(()=>S(new Error("MCP connection timeout after 5 minutes")),g)});try{await Promise.race([h,x])}catch(_){clearTimeout(v),y.warn("WORKER","MCP server connection failed, cleaning up subprocess",{error:_ instanceof Error?_.message:String(_)});try{await f.close()}catch{}throw _}clearTimeout(v);let b=f._process;b?.pid&&(gt().registerProcess("mcp-server",{pid:b.pid,type:"mcp",startedAt:new Date().toISOString()},b),b.once("exit",()=>{gt().unregisterProcess("mcp-server")})),this.mcpReady=!0,y.success("WORKER","MCP server connected"),this.stopOrphanReaper=xU(()=>{let _=new Set;for(let[S]of this.sessionManager.sessions)_.add(S);return _}),y.info("SYSTEM","Started orphan reaper (runs every 30 seconds)"),this.staleSessionReaperInterval=setInterval(async()=>{try{let _=await this.sessionManager.reapStaleSessions();_>0&&y.info("SYSTEM",`Reaped ${_} stale sessions`)}catch(_){y.error("SYSTEM","Stale session reaper error",{error:_ instanceof Error?_.message:String(_)})}},120*1e3),this.processPendingQueues(50).then(_=>{_.sessionsStarted>0&&y.info("SYSTEM",`Auto-recovered ${_.sessionsStarted} sessions with pending work`,{totalPending:_.totalPendingSessions,started:_.sessionsStarted,sessionIds:_.startedSessionIds})}).catch(_=>{y.error("SYSTEM","Auto-recovery of pending queues failed",{},_)})}catch(e){throw y.error("SYSTEM","Background initialization failed",{},e),e}}getActiveAgent(){return eu()&&Go()?this.openRouterAgent:Qc()&&Vo()?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","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=qs(e.sessionDbId);if(c&&c.process.exitCode===null&&await Fs(c,5e3),e.generatorPromise=null,!a&&!o&&(this.lastAiInteraction={timestamp:Date.now(),success:!0,provider:s}),o){y.warn("SYSTEM","Skipping restart due to unrecoverable error",{sessionId:e.sessionDbId}),this.broadcastProcessingStatus();return}let{PendingMessageStore:u}=(Us(),ou(zo)),l=new u(this.dbManager.getSessionStore().db,3);if(e.idleTimedOut){y.info("SYSTEM","Generator exited due to idle timeout, not restarting",{sessionId:e.sessionDbId}),e.idleTimedOut=!1,this.broadcastProcessingStatus();return}let d=l.getPendingCount(e.sessionDbId),p=3;if(d>0){if(e.consecutiveRestarts=(e.consecutiveRestarts||0)+1,e.consecutiveRestarts>p){y.error("SYSTEM","Exceeded max pending-work restarts, stopping to prevent infinite loop",{sessionId:e.sessionDbId,pendingCount:d,consecutiveRestarts:e.consecutiveRestarts}),e.consecutiveRestarts=0,this.broadcastProcessingStatus();return}y.info("SYSTEM","Pending work remains after generator exit, restarting with fresh AbortController",{sessionId:e.sessionDbId,pendingCount:d,attempt:e.consecutiveRestarts}),e.abortController=new AbortController,this.startSessionProcessor(e,"pending-work-restart")}else e.consecutiveRestarts=0;this.broadcastProcessingStatus()})}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(Vo())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(Go())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)}async processPendingQueues(e=10){let{PendingMessageStore:r}=await Promise.resolve().then(()=>(Us(),zo)),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(`
1432
1432
  SELECT id FROM sdk_sessions
1433
1433
  WHERE status = 'active' AND started_at_epoch < ?
1434
1434
  `).all(o);if(u.length>0){let l=u.map(m=>m.id),d=l.map(()=>"?").join(",");i.db.prepare(`