diff --git a/plugin/hooks/CLAUDE.md b/plugin/hooks/CLAUDE.md index 0533702f..32953a0d 100644 --- a/plugin/hooks/CLAUDE.md +++ b/plugin/hooks/CLAUDE.md @@ -28,4 +28,10 @@ | ID | Time | T | Title | Read | |----|------|---|-------|------| | #32309 | 3:09 PM | 🔵 | Claude-mem hooks system configuration structure | ~435 | + +### Jan 9, 2026 + +| ID | Time | T | Title | Read | +|----|------|---|-------|------| +| #38802 | 5:11 PM | 🔵 | Claude-Mem Hook Configuration Architecture | ~450 | \ No newline at end of file diff --git a/plugin/package.json b/plugin/package.json index d20fdf26..cc521d61 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,6 +1,6 @@ { "name": "claude-mem-plugin", - "version": "9.0.1", + "version": "9.0.2", "private": true, "description": "Runtime dependencies for claude-mem bundled hooks", "type": "module", diff --git a/plugin/scripts/worker-service.cjs b/plugin/scripts/worker-service.cjs index b49d202f..01f666f5 100755 --- a/plugin/scripts/worker-service.cjs +++ b/plugin/scripts/worker-service.cjs @@ -749,7 +749,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs. `}var fG=yl.default.platform==="win32"?["APPDATA","HOMEDRIVE","HOMEPATH","LOCALAPPDATA","PATH","PROCESSOR_ARCHITECTURE","SYSTEMDRIVE","SYSTEMROOT","TEMP","USERNAME","USERPROFILE","PROGRAMFILES"]:["HOME","LOGNAME","PATH","SHELL","TERM","USER"];function mG(){let t={};for(let e of fG){let r=yl.default.env[e];r!==void 0&&(r.startsWith("()")||(t[e]=r))}return t}var Es=class{constructor(e){this._readBuffer=new am,this._stderrStream=null,this._serverParams=e,(e.stderr==="pipe"||e.stderr==="overlapped")&&(this._stderrStream=new DR.PassThrough)}async start(){if(this._process)throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");return new Promise((e,r)=>{this._process=(0,MR.default)(this._serverParams.command,this._serverParams.args??[],{env:{...mG(),...this._serverParams.env},stdio:["pipe","pipe",this._serverParams.stderr??"inherit"],shell:!1,windowsHide:yl.default.platform==="win32"&&hG(),cwd:this._serverParams.cwd}),this._process.on("error",n=>{r(n),this.onerror?.(n)}),this._process.on("spawn",()=>{e()}),this._process.on("close",n=>{this._process=void 0,this.onclose?.()}),this._process.stdin?.on("error",n=>{this.onerror?.(n)}),this._process.stdout?.on("data",n=>{this._readBuffer.append(n),this.processReadBuffer()}),this._process.stdout?.on("error",n=>{this.onerror?.(n)}),this._stderrStream&&this._process.stderr&&this._process.stderr.pipe(this._stderrStream)})}get stderr(){return this._stderrStream?this._stderrStream:this._process?.stderr??null}get pid(){return this._process?.pid??null}processReadBuffer(){for(;;)try{let e=this._readBuffer.readMessage();if(e===null)break;this.onmessage?.(e)}catch(e){this.onerror?.(e)}}async close(){if(this._process){let e=this._process;this._process=void 0;let r=new Promise(n=>{e.once("close",()=>{n()})});try{e.stdin?.end()}catch{}if(await Promise.race([r,new Promise(n=>setTimeout(n,2e3).unref())]),e.exitCode===null){try{e.kill("SIGTERM")}catch{}await Promise.race([r,new Promise(n=>setTimeout(n,2e3).unref())])}if(e.exitCode===null)try{e.kill("SIGKILL")}catch{}}this._readBuffer.clear()}send(e){return new Promise(r=>{if(!this._process?.stdin)throw new Error("Not connected");let n=AR(e);this._process.stdin.write(n)?r():this._process.stdin.once("drain",r)})}};function hG(){return"type"in yl.default}Zr();$e();var W0=ut(require("path"),1),XR=require("os"),Hn=require("fs"),ks=require("child_process"),YR=require("util");$e();xl();var cm=(0,YR.promisify)(ks.exec),QR=W0.default.join((0,XR.homedir)(),".claude-mem"),ro=W0.default.join(QR,"worker.pid");function K0(t){(0,Hn.mkdirSync)(QR,{recursive:!0}),(0,Hn.writeFileSync)(ro,JSON.stringify(t,null,2))}function eC(){if(!(0,Hn.existsSync)(ro))return null;try{return JSON.parse((0,Hn.readFileSync)(ro,"utf-8"))}catch(t){return k.warn("SYSTEM","Failed to parse PID file",{path:ro},t),null}}function Ui(){if((0,Hn.existsSync)(ro))try{(0,Hn.unlinkSync)(ro)}catch(t){k.warn("SYSTEM","Failed to remove PID file",{path:ro},t)}}function no(t){return process.platform==="win32"?Math.round(t*2):t}async function tC(t){if(process.platform!=="win32")return[];if(!Number.isInteger(t)||t<=0)return k.warn("SYSTEM","Invalid parent PID for child process enumeration",{parentPid:t}),[];try{let e=`powershell -NoProfile -NonInteractive -Command "Get-Process | Where-Object { \\$_.ParentProcessId -eq ${t} } | Select-Object -ExpandProperty Id"`,{stdout:r}=await cm(e,{timeout:ma.POWERSHELL_COMMAND});return r.split(` `).map(n=>n.trim()).filter(n=>n.length>0&&/^\d+$/.test(n)).map(n=>parseInt(n,10)).filter(n=>n>0)}catch(e){return k.error("SYSTEM","Failed to enumerate child processes",{parentPid:t},e),[]}}async function rC(t){if(!Number.isInteger(t)||t<=0){k.warn("SYSTEM","Invalid PID for force kill",{pid:t});return}try{process.platform==="win32"?await cm(`taskkill /PID ${t} /T /F`,{timeout:ma.POWERSHELL_COMMAND}):process.kill(t,"SIGKILL"),k.info("SYSTEM","Killed process",{pid:t})}catch(e){k.debug("SYSTEM","Process already exited during force kill",{pid:t},e)}}async function nC(t,e){let r=Date.now();for(;Date.now()-r{try{return process.kill(i,0),!0}catch{return!1}});if(n.length===0){k.info("SYSTEM","All child processes exited");return}k.debug("SYSTEM","Waiting for processes to exit",{stillAlive:n}),await new Promise(i=>setTimeout(i,100))}k.warn("SYSTEM","Timeout waiting for child processes to exit")}async function iC(){let t=process.platform==="win32",e=[];try{if(t){let r=`powershell -NoProfile -NonInteractive -Command "Get-CimInstance Win32_Process | Where-Object { \\$_.Name -like '*python*' -and \\$_.CommandLine -like '*chroma-mcp*' } | Select-Object -ExpandProperty ProcessId"`,{stdout:n}=await cm(r,{timeout:ma.POWERSHELL_COMMAND});if(!n.trim()){k.debug("SYSTEM","No orphaned chroma-mcp processes found (Windows)");return}let i=n.split(` `).map(a=>a.trim()).filter(a=>a.length>0&&/^\d+$/.test(a));for(let a of i){let o=parseInt(a,10);!isNaN(o)&&Number.isInteger(o)&&o>0&&e.push(o)}}else{let{stdout:r}=await cm('ps aux | grep "chroma-mcp" | grep -v grep || true');if(!r.trim()){k.debug("SYSTEM","No orphaned chroma-mcp processes found (Unix)");return}let n=r.trim().split(` -`);for(let i of n){let a=i.trim().split(/\s+/);if(a.length>1){let o=parseInt(a[1],10);!isNaN(o)&&Number.isInteger(o)&&o>0&&e.push(o)}}}}catch(r){k.error("SYSTEM","Failed to enumerate orphaned processes",{},r);return}if(e.length!==0){if(k.info("SYSTEM","Cleaning up orphaned chroma-mcp processes",{platform:t?"Windows":"Unix",count:e.length,pids:e}),t)for(let r of e){if(!Number.isInteger(r)||r<=0){k.warn("SYSTEM","Skipping invalid PID",{pid:r});continue}try{(0,ks.execSync)(`taskkill /PID ${r} /T /F`,{timeout:ma.POWERSHELL_COMMAND,stdio:"ignore"})}catch(n){k.debug("SYSTEM","Failed to kill process, may have already exited",{pid:r},n)}}else for(let r of e)try{process.kill(r,"SIGKILL")}catch(n){k.debug("SYSTEM","Process already exited",{pid:r},n)}k.info("SYSTEM","Orphaned processes cleaned up",{count:e.length})}}function J0(t,e,r={}){let n=(0,ks.spawn)(process.execPath,[t,"--daemon"],{detached:!0,stdio:"ignore",windowsHide:!0,env:{...process.env,CLAUDE_MEM_WORKER_PORT:String(e),...r}});if(n.pid!==void 0)return n.unref(),n.pid}function aC(t,e){return async r=>{if(e.value){k.warn("SYSTEM",`Received ${r} but shutdown already in progress`);return}e.value=!0,k.info("SYSTEM",`Received ${r}, shutting down...`);try{await t(),process.exit(0)}catch(n){k.error("SYSTEM","Error during shutdown",{},n),process.exit(0)}}}var X0=ut(require("path"),1),oC=require("os"),sC=require("fs");$e();async function um(t){try{return(await fetch(`http://127.0.0.1:${t}/api/health`)).ok}catch{return!1}}async function El(t,e=3e4){let r=Date.now();for(;Date.now()-rsetTimeout(n,500))}return!1}async function lm(t,e=1e4){let r=Date.now();for(;Date.now()-rsetTimeout(n,500))}return!1}async function dm(t){try{let e=await fetch(`http://127.0.0.1:${t}/api/admin/shutdown`,{method:"POST"});return e.ok?!0:(k.warn("SYSTEM","Shutdown request returned error",{port:t,status:e.status}),!1)}catch(e){return e instanceof Error&&e.message?.includes("ECONNREFUSED")?(k.debug("SYSTEM","Worker already stopped",{port:t},e),!1):(k.error("SYSTEM","Shutdown request failed unexpectedly",{port:t},e),!1)}}function xG(){let t=X0.default.join((0,oC.homedir)(),".claude","plugins","marketplaces","thedotmack"),e=X0.default.join(t,"package.json");return JSON.parse((0,sC.readFileSync)(e,"utf-8")).version}async function SG(t){try{let e=await fetch(`http://127.0.0.1:${t}/api/version`);return e.ok?(await e.json()).version:null}catch{return k.debug("SYSTEM","Could not fetch worker version",{port:t}),null}}async function cC(t){let e=xG(),r=await SG(t);return r?{matches:e===r,pluginVersion:e,workerVersion:r}:{matches:!0,pluginVersion:e,workerVersion:r}}$e();async function uC(t){k.info("SYSTEM","Shutdown initiated"),Ui();let e=await tC(process.pid);if(k.info("SYSTEM","Found child processes",{count:e.length,pids:e}),t.server&&(await wG(t.server),k.info("SYSTEM","HTTP server closed")),await t.sessionManager.shutdownAll(),t.mcpClient&&(await t.mcpClient.close(),k.info("SYSTEM","MCP client closed")),t.dbManager&&await t.dbManager.close(),e.length>0){k.info("SYSTEM","Force killing remaining children");for(let r of e)await rC(r);await nC(e,5e3)}k.info("SYSTEM","Worker shutdown complete")}async function wG(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)),k.info("SYSTEM","Waited for Windows port cleanup"))}var I4=ut(_h(),1),a$=ut(require("fs"),1),o$=ut(require("path"),1);$e();var r$=ut(_h(),1),w4=ut(f4(),1),$4=ut(require("path"),1);ln();$e();function n$(t){let e=[];e.push(r$.default.json({limit:"50mb"})),e.push((0,w4.default)()),e.push((i,a,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(g=>i.path.endsWith(g)),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);k.info("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let f=a.send.bind(a);a.send=function(g){let _=Date.now()-l;return k.info("HTTP",`\u2190 ${a.statusCode} ${i.path}`,{requestId:d,duration:`${_}ms`}),f(g)},o()});let r=Kr(),n=$4.default.join(r,"plugin","ui");return e.push(r$.default.static(n)),e}function bh(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")){k.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 i$(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=${k.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}$e();var Qs=class extends Error{constructor(r,n=500,i,a){super(r);this.statusCode=n;this.code=i;this.details=a;this.name="AppError"}};function E4(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var k4=(t,e,r,n)=>{let i=t instanceof Qs?t.statusCode:500;k.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof Qs?t.code:void 0},t);let a=E4(t.name||"Error",t.message,t instanceof Qs?t.code:void 0,t instanceof Qs?t.details:void 0);r.status(i).json(a)};function T4(t,e){e.status(404).json(E4("NotFound",`Cannot ${t.method} ${t.path}`))}var Dne="9.0.1",xh=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,I4.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,()=>{k.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,k.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(T4),this.app.use(k4)}setupMiddleware(){n$(i$).forEach(r=>this.app.use(r))}setupCoreRoutes(){let e="TEST-008-wrapper-ipc";this.app.get("/api/health",(r,n)=>{n.status(200).json({status:"ok",build:e,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()})}),this.app.get("/api/readiness",(r,n)=>{this.options.getInitializationComplete()?n.status(200).json({status:"ready",mcpReady:this.options.getMcpReady()}):n.status(503).json({status:"initializing",message:"Worker is still initializing, please retry"})}),this.app.get("/api/version",(r,n)=>{n.status(200).json({version:Dne})}),this.app.get("/api/instructions",async(r,n)=>{let i=r.query.topic||"all",a=r.query.operation;try{let o;if(a){let s=o$.default.join(__dirname,"../skills/mem-search/operations",`${a}.md`);o=await a$.promises.readFile(s,"utf-8")}else{let s=o$.default.join(__dirname,"../skills/mem-search/SKILL.md"),c=await a$.promises.readFile(s,"utf-8");o=this.extractInstructionSection(c,i)}n.json({content:[{type:"text",text:o}]})}catch{n.status(404).json({error:"Instruction not found"})}}),this.app.post("/api/admin/restart",bh,async(r,n)=>{n.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(k.info("SYSTEM","Sending restart request to wrapper"),process.send({type:"restart"})):setTimeout(async()=>{await this.options.onRestart()},100)}),this.app.post("/api/admin/shutdown",bh,async(r,n)=>{n.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(k.info("SYSTEM","Sending shutdown request to wrapper"),process.send({type:"shutdown"})):setTimeout(async()=>{await this.options.onShutdown()},100)})}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),a=e.indexOf(n);return i===-1?e:a===-1?e.substring(i):e.substring(i,a).trim()}};var lt=ut(require("path"),1),ec=require("os"),Vt=require("fs"),R4=require("child_process"),C4=require("util");$e();Zr();var In=require("fs"),ud=require("path");$e();function P4(t){try{return(0,In.existsSync)(t)?JSON.parse((0,In.readFileSync)(t,"utf-8")):{}}catch(e){return k.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function O4(t,e){let r=(0,ud.join)(t,"..");(0,In.mkdirSync)(r,{recursive:!0}),(0,In.writeFileSync)(t,JSON.stringify(e,null,2))}function s$(t,e){let r=(0,ud.join)(t,".cursor","rules"),n=(0,ud.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,In.mkdirSync)(r,{recursive:!0});let a=`--- +`);for(let i of n){let a=i.trim().split(/\s+/);if(a.length>1){let o=parseInt(a[1],10);!isNaN(o)&&Number.isInteger(o)&&o>0&&e.push(o)}}}}catch(r){k.error("SYSTEM","Failed to enumerate orphaned processes",{},r);return}if(e.length!==0){if(k.info("SYSTEM","Cleaning up orphaned chroma-mcp processes",{platform:t?"Windows":"Unix",count:e.length,pids:e}),t)for(let r of e){if(!Number.isInteger(r)||r<=0){k.warn("SYSTEM","Skipping invalid PID",{pid:r});continue}try{(0,ks.execSync)(`taskkill /PID ${r} /T /F`,{timeout:ma.POWERSHELL_COMMAND,stdio:"ignore"})}catch(n){k.debug("SYSTEM","Failed to kill process, may have already exited",{pid:r},n)}}else for(let r of e)try{process.kill(r,"SIGKILL")}catch(n){k.debug("SYSTEM","Process already exited",{pid:r},n)}k.info("SYSTEM","Orphaned processes cleaned up",{count:e.length})}}function J0(t,e,r={}){let n=(0,ks.spawn)(process.execPath,[t,"--daemon"],{detached:!0,stdio:"ignore",windowsHide:!0,env:{...process.env,CLAUDE_MEM_WORKER_PORT:String(e),...r}});if(n.pid!==void 0)return n.unref(),n.pid}function aC(t,e){return async r=>{if(e.value){k.warn("SYSTEM",`Received ${r} but shutdown already in progress`);return}e.value=!0,k.info("SYSTEM",`Received ${r}, shutting down...`);try{await t(),process.exit(0)}catch(n){k.error("SYSTEM","Error during shutdown",{},n),process.exit(0)}}}var X0=ut(require("path"),1),oC=require("os"),sC=require("fs");$e();async function um(t){try{return(await fetch(`http://127.0.0.1:${t}/api/health`)).ok}catch{return!1}}async function El(t,e=3e4){let r=Date.now();for(;Date.now()-rsetTimeout(n,500))}return!1}async function lm(t,e=1e4){let r=Date.now();for(;Date.now()-rsetTimeout(n,500))}return!1}async function dm(t){try{let e=await fetch(`http://127.0.0.1:${t}/api/admin/shutdown`,{method:"POST"});return e.ok?!0:(k.warn("SYSTEM","Shutdown request returned error",{port:t,status:e.status}),!1)}catch(e){return e instanceof Error&&e.message?.includes("ECONNREFUSED")?(k.debug("SYSTEM","Worker already stopped",{port:t},e),!1):(k.error("SYSTEM","Shutdown request failed unexpectedly",{port:t},e),!1)}}function xG(){let t=X0.default.join((0,oC.homedir)(),".claude","plugins","marketplaces","thedotmack"),e=X0.default.join(t,"package.json");return JSON.parse((0,sC.readFileSync)(e,"utf-8")).version}async function SG(t){try{let e=await fetch(`http://127.0.0.1:${t}/api/version`);return e.ok?(await e.json()).version:null}catch{return k.debug("SYSTEM","Could not fetch worker version",{port:t}),null}}async function cC(t){let e=xG(),r=await SG(t);return r?{matches:e===r,pluginVersion:e,workerVersion:r}:{matches:!0,pluginVersion:e,workerVersion:r}}$e();async function uC(t){k.info("SYSTEM","Shutdown initiated"),Ui();let e=await tC(process.pid);if(k.info("SYSTEM","Found child processes",{count:e.length,pids:e}),t.server&&(await wG(t.server),k.info("SYSTEM","HTTP server closed")),await t.sessionManager.shutdownAll(),t.mcpClient&&(await t.mcpClient.close(),k.info("SYSTEM","MCP client closed")),t.dbManager&&await t.dbManager.close(),e.length>0){k.info("SYSTEM","Force killing remaining children");for(let r of e)await rC(r);await nC(e,5e3)}k.info("SYSTEM","Worker shutdown complete")}async function wG(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)),k.info("SYSTEM","Waited for Windows port cleanup"))}var I4=ut(_h(),1),a$=ut(require("fs"),1),o$=ut(require("path"),1);$e();var r$=ut(_h(),1),w4=ut(f4(),1),$4=ut(require("path"),1);ln();$e();function n$(t){let e=[];e.push(r$.default.json({limit:"50mb"})),e.push((0,w4.default)()),e.push((i,a,o)=>{let c=[".html",".js",".css",".svg",".png",".jpg",".jpeg",".webp",".woff",".woff2",".ttf",".eot"].some(g=>i.path.endsWith(g)),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);k.info("HTTP",`\u2192 ${i.method} ${i.path}`,{requestId:d},p);let f=a.send.bind(a);a.send=function(g){let _=Date.now()-l;return k.info("HTTP",`\u2190 ${a.statusCode} ${i.path}`,{requestId:d,duration:`${_}ms`}),f(g)},o()});let r=Kr(),n=$4.default.join(r,"plugin","ui");return e.push(r$.default.static(n)),e}function bh(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")){k.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 i$(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=${k.formatTool(n,i)}`}return e.includes("/summarize")?"requesting summary":""}$e();var Qs=class extends Error{constructor(r,n=500,i,a){super(r);this.statusCode=n;this.code=i;this.details=a;this.name="AppError"}};function E4(t,e,r,n){let i={error:t,message:e};return r&&(i.code=r),n&&(i.details=n),i}var k4=(t,e,r,n)=>{let i=t instanceof Qs?t.statusCode:500;k.error("HTTP",`Error handling ${e.method} ${e.path}`,{statusCode:i,error:t.message,code:t instanceof Qs?t.code:void 0},t);let a=E4(t.name||"Error",t.message,t instanceof Qs?t.code:void 0,t instanceof Qs?t.details:void 0);r.status(i).json(a)};function T4(t,e){e.status(404).json(E4("NotFound",`Cannot ${t.method} ${t.path}`))}var Dne="9.0.2",xh=class{app;server=null;options;startTime=Date.now();constructor(e){this.options=e,this.app=(0,I4.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,()=>{k.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,k.info("SYSTEM","HTTP server closed"))}registerRoutes(e){e.setupRoutes(this.app)}finalizeRoutes(){this.app.use(T4),this.app.use(k4)}setupMiddleware(){n$(i$).forEach(r=>this.app.use(r))}setupCoreRoutes(){let e="TEST-008-wrapper-ipc";this.app.get("/api/health",(r,n)=>{n.status(200).json({status:"ok",build:e,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()})}),this.app.get("/api/readiness",(r,n)=>{this.options.getInitializationComplete()?n.status(200).json({status:"ready",mcpReady:this.options.getMcpReady()}):n.status(503).json({status:"initializing",message:"Worker is still initializing, please retry"})}),this.app.get("/api/version",(r,n)=>{n.status(200).json({version:Dne})}),this.app.get("/api/instructions",async(r,n)=>{let i=r.query.topic||"all",a=r.query.operation;try{let o;if(a){let s=o$.default.join(__dirname,"../skills/mem-search/operations",`${a}.md`);o=await a$.promises.readFile(s,"utf-8")}else{let s=o$.default.join(__dirname,"../skills/mem-search/SKILL.md"),c=await a$.promises.readFile(s,"utf-8");o=this.extractInstructionSection(c,i)}n.json({content:[{type:"text",text:o}]})}catch{n.status(404).json({error:"Instruction not found"})}}),this.app.post("/api/admin/restart",bh,async(r,n)=>{n.json({status:"restarting"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(k.info("SYSTEM","Sending restart request to wrapper"),process.send({type:"restart"})):setTimeout(async()=>{await this.options.onRestart()},100)}),this.app.post("/api/admin/shutdown",bh,async(r,n)=>{n.json({status:"shutting_down"}),process.platform==="win32"&&process.env.CLAUDE_MEM_MANAGED==="true"&&process.send?(k.info("SYSTEM","Sending shutdown request to wrapper"),process.send({type:"shutdown"})):setTimeout(async()=>{await this.options.onShutdown()},100)})}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),a=e.indexOf(n);return i===-1?e:a===-1?e.substring(i):e.substring(i,a).trim()}};var lt=ut(require("path"),1),ec=require("os"),Vt=require("fs"),R4=require("child_process"),C4=require("util");$e();Zr();var In=require("fs"),ud=require("path");$e();function P4(t){try{return(0,In.existsSync)(t)?JSON.parse((0,In.readFileSync)(t,"utf-8")):{}}catch(e){return k.error("CONFIG","Failed to read Cursor registry, using empty registry",{file:t,error:e instanceof Error?e.message:String(e)}),{}}}function O4(t,e){let r=(0,ud.join)(t,"..");(0,In.mkdirSync)(r,{recursive:!0}),(0,In.writeFileSync)(t,JSON.stringify(e,null,2))}function s$(t,e){let r=(0,ud.join)(t,".cursor","rules"),n=(0,ud.join)(r,"claude-mem-context.mdc"),i=`${n}.tmp`;(0,In.mkdirSync)(r,{recursive:!0});let a=`--- alwaysApply: true description: "Claude-mem context from past sessions (auto-updated)" ---