diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index dc25afe6..0c6c7f7c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "plugins": [ { "name": "claude-mem", - "version": "7.3.4", + "version": "7.3.5", "source": "./plugin", "description": "Persistent memory system for Claude Code - context compression across sessions" } diff --git a/package.json b/package.json index e32725ec..5856ba61 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "7.3.4", + "version": "7.3.5", "description": "Memory compression system for Claude Code - persist context across sessions", "keywords": [ "claude", diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 6ee75494..bd789966 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-mem", - "version": "7.3.4", + "version": "7.3.5", "description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions", "author": { "name": "Alex Newman" diff --git a/plugin/package.json b/plugin/package.json index 4247a2bb..1eda2d60 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,6 +1,6 @@ { "name": "claude-mem-plugin", - "version": "7.3.4", + "version": "7.3.5", "private": true, "description": "Runtime dependencies for claude-mem bundled hooks", "type": "module", diff --git a/plugin/scripts/mcp-server.cjs b/plugin/scripts/mcp-server.cjs index 81ec4d3e..2a6c70de 100755 --- a/plugin/scripts/mcp-server.cjs +++ b/plugin/scripts/mcp-server.cjs @@ -37,4 +37,4 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs. `}var Il=class{constructor(t=tg.default.stdin,n=tg.default.stdout){this._stdin=t,this._stdout=n,this._readBuffer=new zl,this._started=!1,this._ondata=o=>{this._readBuffer.append(o),this.processReadBuffer()},this._onerror=o=>{this.onerror?.(o)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let t=this._readBuffer.readMessage();if(t===null)break;this.onmessage?.(t)}catch(t){this.onerror?.(t)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(t){return new Promise(n=>{let o=Jx(t);this._stdout.write(o)?n():this._stdout.once("drain",n)})}};var fo=require("fs"),Hx=require("path"),Bx=require("os");var nN=["bugfix","feature","refactor","discovery","decision","change"],oN=["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"];var Wx=nN.join(","),Kx=oN.join(",");var zt=class{static DEFAULTS={CLAUDE_MEM_MODEL:"claude-sonnet-4-5",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_WORKER_PORT:"37777",CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_DATA_DIR:(0,Hx.join)((0,Bx.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS:"true",CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS:"true",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT:"true",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT:"true",CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES:Wx,CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS:Kx,CLAUDE_MEM_CONTEXT_FULL_COUNT:"5",CLAUDE_MEM_CONTEXT_FULL_FIELD:"narrative",CLAUDE_MEM_CONTEXT_SESSION_COUNT:"10",CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY:"true",CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE:"false"};static getAllDefaults(){return{...this.DEFAULTS}}static get(t){return this.DEFAULTS[t]}static getInt(t){let n=this.get(t);return parseInt(n,10)}static getBool(t){return this.get(t)==="true"}static loadFromFile(t){if(!(0,fo.existsSync)(t))return this.getAllDefaults();let n=(0,fo.readFileSync)(t,"utf-8"),o=JSON.parse(n),r=o;if(o.env&&typeof o.env=="object"){r=o.env;try{(0,fo.writeFileSync)(t,JSON.stringify(r,null,2),"utf-8"),be.info("SETTINGS","Migrated settings file from nested to flat schema",{settingsPath:t})}catch(a){be.warn("SETTINGS","Failed to auto-migrate settings file",{settingsPath:t},a)}}let i={...this.DEFAULTS};for(let a of Object.keys(this.DEFAULTS))r[a]!==void 0&&(i[a]=r[a]);return i}};var rg=(i=>(i[i.DEBUG=0]="DEBUG",i[i.INFO=1]="INFO",i[i.WARN=2]="WARN",i[i.ERROR=3]="ERROR",i[i.SILENT=4]="SILENT",i))(rg||{}),ng=class{level=null;useColor;constructor(){this.useColor=process.stdout.isTTY??!1}getLevel(){if(this.level===null){let t=zt.get("CLAUDE_MEM_LOG_LEVEL").toUpperCase();this.level=rg[t]??1}return this.level}correlationId(t,n){return`obs-${t}-${n}`}sessionId(t){return`session-${t}`}formatData(t){if(t==null)return"";if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return t.toString();if(typeof t=="object"){if(t instanceof Error)return this.getLevel()===0?`${t.message} ${t.stack}`:t.message;if(Array.isArray(t))return`[${t.length} items]`;let n=Object.keys(t);return n.length===0?"{}":n.length<=3?JSON.stringify(t):`{${n.length} keys: ${n.slice(0,3).join(", ")}...}`}return String(t)}formatTool(t,n){if(!n)return t;try{let o=typeof n=="string"?JSON.parse(n):n;if(t==="Bash"&&o.command){let r=o.command.length>50?o.command.substring(0,50)+"...":o.command;return`${t}(${r})`}if(t==="Read"&&o.file_path){let r=o.file_path.split("/").pop()||o.file_path;return`${t}(${r})`}if(t==="Edit"&&o.file_path){let r=o.file_path.split("/").pop()||o.file_path;return`${t}(${r})`}if(t==="Write"&&o.file_path){let r=o.file_path.split("/").pop()||o.file_path;return`${t}(${r})`}return t}catch{return t}}formatTimestamp(t){let n=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),r=String(t.getDate()).padStart(2,"0"),i=String(t.getHours()).padStart(2,"0"),a=String(t.getMinutes()).padStart(2,"0"),s=String(t.getSeconds()).padStart(2,"0"),c=String(t.getMilliseconds()).padStart(3,"0");return`${n}-${o}-${r} ${i}:${a}:${s}.${c}`}log(t,n,o,r,i){if(t0&&(d=` {${Object.entries(S).map(([A,N])=>`${A}=${N}`).join(", ")}}`)}let f=`[${a}] [${s}] [${c}] ${u}${o}${d}${l}`;t===3?console.error(f):console.log(f)}debug(t,n,o,r){this.log(0,t,n,o,r)}info(t,n,o,r){this.log(1,t,n,o,r)}warn(t,n,o,r){this.log(2,t,n,o,r)}error(t,n,o,r){this.log(3,t,n,o,r)}dataIn(t,n,o,r){this.info(t,`\u2192 ${n}`,o,r)}dataOut(t,n,o,r){this.info(t,`\u2190 ${n}`,o,r)}success(t,n,o,r){this.info(t,`\u2713 ${n}`,o,r)}failure(t,n,o,r){this.error(t,`\u2717 ${n}`,o,r)}timing(t,n,o,r){this.info(t,`\u23F1 ${n}`,r,{duration:`${o}ms`})}happyPathError(t,n,o,r,i=""){let u=((new Error().stack||"").split(` -`)[2]||"").match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/),l=u?`${u[1].split("/").pop()}:${u[2]}`:"unknown",d={...o,location:l};return this.warn(t,`[HAPPY-PATH] ${n}`,d,r),i}},be=new ng;var El=va(require("path"),1),ag=require("os");var og={DEFAULT:5e3,HEALTH_CHECK:1e3,WORKER_STARTUP_WAIT:1e3,WORKER_STARTUP_RETRIES:15,PRE_RESTART_SETTLE_DELAY:2e3,WINDOWS_MULTIPLIER:1.5};function Gx(e){return process.platform==="win32"?Math.round(e*og.WINDOWS_MULTIPLIER):e}var Pl=require("path");var Qx=require("os");var Je=require("path"),Xx=require("os");var Yx=require("url");var aN={};function iN(){return typeof __dirname<"u"?__dirname:(0,Je.dirname)((0,Yx.fileURLToPath)(aN.url))}var EM=iN(),Zt=zt.get("CLAUDE_MEM_DATA_DIR"),ig=process.env.CLAUDE_CONFIG_DIR||(0,Je.join)((0,Xx.homedir)(),".claude"),OM=(0,Je.join)(Zt,"archives"),TM=(0,Je.join)(Zt,"logs"),jM=(0,Je.join)(Zt,"trash"),NM=(0,Je.join)(Zt,"backups"),RM=(0,Je.join)(Zt,"settings.json"),DM=(0,Je.join)(Zt,"claude-mem.db"),AM=(0,Je.join)(Zt,"vector-db"),ZM=(0,Je.join)(ig,"settings.json"),UM=(0,Je.join)(ig,"commands"),CM=(0,Je.join)(ig,"CLAUDE.md");var WM=(0,Pl.join)(Zt,"worker.pid"),KM=(0,Pl.join)(Zt,"logs"),HM=(0,Pl.join)((0,Qx.homedir)(),".claude","plugins","marketplaces","thedotmack");var o6=El.default.join((0,ag.homedir)(),".claude","plugins","marketplaces","thedotmack"),i6=Gx(og.HEALTH_CHECK),po=null;function ek(){if(po!==null)return po;try{let e=El.default.join(zt.get("CLAUDE_MEM_DATA_DIR"),"settings.json"),t=zt.loadFromFile(e);return po=parseInt(t.CLAUDE_MEM_WORKER_PORT,10),po}catch(e){return be.debug("SYSTEM","Failed to load port from settings, using default",{error:e}),po=parseInt(zt.get("CLAUDE_MEM_WORKER_PORT"),10),po}}function tk(){let e=El.default.join((0,ag.homedir)(),".claude-mem","settings.json");return zt.loadFromFile(e).CLAUDE_MEM_WORKER_HOST}var sN=ek(),cN=tk(),mo=`http://${cN}:${sN}`,ha={search:"/api/search",timeline:"/api/timeline",get_recent_context:"/api/context/recent",get_context_timeline:"/api/context/timeline",progressive_description:"/api/instructions"};async function ga(e,t){be.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:e,params:t});try{let n=new URLSearchParams;for(let[a,s]of Object.entries(t))s!=null&&n.append(a,String(s));let o=`${mo}${e}?${n}`,r=await fetch(o);if(!r.ok){let a=await r.text();throw new Error(`Worker API error (${r.status}): ${a}`)}let i=await r.json();return be.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:e}),i}catch(n){return be.error("SYSTEM","\u2190 Worker API error",void 0,{endpoint:e,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function sg(e,t){be.debug("HTTP","Worker API request (path)",void 0,{endpoint:e,id:t});try{let n=`${mo}${e}/${t}`,o=await fetch(n);if(!o.ok){let i=await o.text();throw new Error(`Worker API error (${o.status}): ${i}`)}let r=await o.json();return be.debug("HTTP","Worker API success (path)",void 0,{endpoint:e,id:t}),{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(n){return be.error("HTTP","Worker API error (path)",void 0,{endpoint:e,id:t,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function uN(e,t){be.debug("HTTP","Worker API request (POST)",void 0,{endpoint:e});try{let n=`${mo}${e}`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!o.ok){let i=await o.text();throw new Error(`Worker API error (${o.status}): ${i}`)}let r=await o.json();return be.debug("HTTP","Worker API success (POST)",void 0,{endpoint:e}),{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(n){return be.error("HTTP","Worker API error (POST)",void 0,{endpoint:e,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function lN(){try{return(await fetch(`${mo}/api/health`)).ok}catch{return!1}}var rk=[{name:"search",description:"Search memory",inputSchema:T.object({query:T.string().optional(),type:T.enum(["observations","sessions","prompts"]).optional(),obs_type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional(),dateStart:T.union([T.string(),T.number()]).optional(),dateEnd:T.union([T.string(),T.number()]).optional(),limit:T.number().min(1).max(100).default(20),offset:T.number().min(0).default(0),orderBy:T.enum(["relevance","date_desc","date_asc"]).default("date_desc")}),handler:async e=>{let t=ha.search;return await ga(t,e)}},{name:"timeline",description:"Timeline context",inputSchema:T.object({query:T.string().optional(),anchor:T.number().optional(),depth_before:T.number().min(0).max(100).default(10),depth_after:T.number().min(0).max(100).default(10),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional()}),handler:async e=>{let t=ha.timeline;return await ga(t,e)}},{name:"get_recent_context",description:"Recent context",inputSchema:T.object({limit:T.number().min(1).max(100).default(30),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional(),dateStart:T.union([T.string(),T.number()]).optional(),dateEnd:T.union([T.string(),T.number()]).optional()}),handler:async e=>{let t=ha.get_recent_context;return await ga(t,e)}},{name:"get_context_timeline",description:"Timeline around ID",inputSchema:T.object({anchor:T.number(),depth_before:T.number().min(0).max(100).default(10),depth_after:T.number().min(0).max(100).default(10),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional()}),handler:async e=>{let t=ha.get_context_timeline;return await ga(t,e)}},{name:"progressive_description",description:"Usage help",inputSchema:T.object({topic:T.enum(["workflow","search_params","examples","all"]).default("all")}),handler:async e=>{let t=ha.progressive_description;return await ga(t,e)}},{name:"get_observation",description:"Fetch by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/observation",e.id)},{name:"get_batch_observations",description:"Batch fetch",inputSchema:T.object({ids:T.array(T.number()),orderBy:T.enum(["date_desc","date_asc"]).optional(),limit:T.number().optional(),project:T.string().optional()}),handler:async e=>await uN("/api/observations/batch",e)},{name:"get_session",description:"Session by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/session",e.id)},{name:"get_prompt",description:"Prompt by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/prompt",e.id)}],cg=new wl({name:"claude-mem-search-server",version:"1.0.0"},{capabilities:{tools:{}}});cg.setRequestHandler(Yp,async()=>({tools:rk.map(e=>({name:e.name,description:e.description,inputSchema:Cu(e.inputSchema)}))}));cg.setRequestHandler(Zi,async e=>{let t=rk.find(n=>n.name===e.params.name);if(!t)throw new Error(`Unknown tool: ${e.params.name}`);try{return await t.handler(e.params.arguments||{})}catch(n){return{content:[{type:"text",text:`Tool execution failed: ${n.message}`}],isError:!0}}});async function nk(){be.info("SYSTEM","MCP server shutting down"),process.exit(0)}process.on("SIGTERM",nk);process.on("SIGINT",nk);async function dN(){let e=new Il;await cg.connect(e),be.info("SYSTEM","Claude-mem search server started"),setTimeout(async()=>{await lN()?be.info("SYSTEM","Worker available",void 0,{workerUrl:mo}):(be.warn("SYSTEM","Worker not available",void 0,{workerUrl:mo}),be.warn("SYSTEM","Tools will fail until Worker is started"),be.warn("SYSTEM","Start Worker with: npm run worker:restart"))},0)}dN().catch(e=>{be.error("SYSTEM","Fatal error",void 0,e),process.exit(1)}); +`)[2]||"").match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/),l=u?`${u[1].split("/").pop()}:${u[2]}`:"unknown",d={...o,location:l};return this.warn(t,`[HAPPY-PATH] ${n}`,d,r),i}},be=new ng;var El=va(require("path"),1),ag=require("os");var og={DEFAULT:5e3,HEALTH_CHECK:1e3,WORKER_STARTUP_WAIT:1e3,WORKER_STARTUP_RETRIES:15,PRE_RESTART_SETTLE_DELAY:2e3,WINDOWS_MULTIPLIER:1.5};function Gx(e){return process.platform==="win32"?Math.round(e*og.WINDOWS_MULTIPLIER):e}var Pl=require("path");var Qx=require("os");var Je=require("path"),Xx=require("os");var Yx=require("url");var aN={};function iN(){return typeof __dirname<"u"?__dirname:(0,Je.dirname)((0,Yx.fileURLToPath)(aN.url))}var EM=iN(),Zt=zt.get("CLAUDE_MEM_DATA_DIR"),ig=process.env.CLAUDE_CONFIG_DIR||(0,Je.join)((0,Xx.homedir)(),".claude"),OM=(0,Je.join)(Zt,"archives"),TM=(0,Je.join)(Zt,"logs"),jM=(0,Je.join)(Zt,"trash"),NM=(0,Je.join)(Zt,"backups"),RM=(0,Je.join)(Zt,"settings.json"),DM=(0,Je.join)(Zt,"claude-mem.db"),AM=(0,Je.join)(Zt,"vector-db"),ZM=(0,Je.join)(ig,"settings.json"),UM=(0,Je.join)(ig,"commands"),CM=(0,Je.join)(ig,"CLAUDE.md");var WM=(0,Pl.join)(Zt,"worker.pid"),KM=(0,Pl.join)(Zt,"logs"),HM=(0,Pl.join)((0,Qx.homedir)(),".claude","plugins","marketplaces","thedotmack");var o6=El.default.join((0,ag.homedir)(),".claude","plugins","marketplaces","thedotmack"),i6=Gx(og.HEALTH_CHECK),po=null;function ek(){if(po!==null)return po;try{let e=El.default.join(zt.get("CLAUDE_MEM_DATA_DIR"),"settings.json"),t=zt.loadFromFile(e);return po=parseInt(t.CLAUDE_MEM_WORKER_PORT,10),po}catch(e){return be.debug("SYSTEM","Failed to load port from settings, using default",{error:e}),po=parseInt(zt.get("CLAUDE_MEM_WORKER_PORT"),10),po}}function tk(){let e=El.default.join((0,ag.homedir)(),".claude-mem","settings.json");return zt.loadFromFile(e).CLAUDE_MEM_WORKER_HOST}var sN=ek(),cN=tk(),mo=`http://${cN}:${sN}`,ha={search:"/api/search",timeline:"/api/timeline",get_recent_context:"/api/context/recent",get_context_timeline:"/api/context/timeline",help:"/api/instructions"};async function ga(e,t){be.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:e,params:t});try{let n=new URLSearchParams;for(let[a,s]of Object.entries(t))s!=null&&n.append(a,String(s));let o=`${mo}${e}?${n}`,r=await fetch(o);if(!r.ok){let a=await r.text();throw new Error(`Worker API error (${r.status}): ${a}`)}let i=await r.json();return be.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:e}),i}catch(n){return be.error("SYSTEM","\u2190 Worker API error",void 0,{endpoint:e,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function sg(e,t){be.debug("HTTP","Worker API request (path)",void 0,{endpoint:e,id:t});try{let n=`${mo}${e}/${t}`,o=await fetch(n);if(!o.ok){let i=await o.text();throw new Error(`Worker API error (${o.status}): ${i}`)}let r=await o.json();return be.debug("HTTP","Worker API success (path)",void 0,{endpoint:e,id:t}),{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(n){return be.error("HTTP","Worker API error (path)",void 0,{endpoint:e,id:t,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function uN(e,t){be.debug("HTTP","Worker API request (POST)",void 0,{endpoint:e});try{let n=`${mo}${e}`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!o.ok){let i=await o.text();throw new Error(`Worker API error (${o.status}): ${i}`)}let r=await o.json();return be.debug("HTTP","Worker API success (POST)",void 0,{endpoint:e}),{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(n){return be.error("HTTP","Worker API error (POST)",void 0,{endpoint:e,error:n.message}),{content:[{type:"text",text:`Error calling Worker API: ${n.message}`}],isError:!0}}}async function lN(){try{return(await fetch(`${mo}/api/health`)).ok}catch{return!1}}var rk=[{name:"search",description:"Search memory",inputSchema:T.object({query:T.string().optional(),type:T.enum(["observations","sessions","prompts"]).optional(),obs_type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional(),dateStart:T.union([T.string(),T.number()]).optional(),dateEnd:T.union([T.string(),T.number()]).optional(),limit:T.number().min(1).max(100).default(20),offset:T.number().min(0).default(0),orderBy:T.enum(["relevance","date_desc","date_asc"]).default("date_desc")}),handler:async e=>{let t=ha.search;return await ga(t,e)}},{name:"timeline",description:"Timeline context",inputSchema:T.object({query:T.string().optional(),anchor:T.number().optional(),depth_before:T.number().min(0).max(100).default(10),depth_after:T.number().min(0).max(100).default(10),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional()}),handler:async e=>{let t=ha.timeline;return await ga(t,e)}},{name:"get_recent_context",description:"Recent context",inputSchema:T.object({limit:T.number().min(1).max(100).default(30),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional(),dateStart:T.union([T.string(),T.number()]).optional(),dateEnd:T.union([T.string(),T.number()]).optional()}),handler:async e=>{let t=ha.get_recent_context;return await ga(t,e)}},{name:"get_context_timeline",description:"Timeline around ID",inputSchema:T.object({anchor:T.number(),depth_before:T.number().min(0).max(100).default(10),depth_after:T.number().min(0).max(100).default(10),type:T.string().optional(),concepts:T.string().optional(),files:T.string().optional(),project:T.string().optional()}),handler:async e=>{let t=ha.get_context_timeline;return await ga(t,e)}},{name:"help",description:"Usage help",inputSchema:T.object({topic:T.enum(["workflow","search_params","examples","all"]).default("all")}),handler:async e=>{let t=ha.help;return await ga(t,e)}},{name:"get_observation",description:"Fetch by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/observation",e.id)},{name:"get_observations",description:"Batch fetch",inputSchema:T.object({ids:T.array(T.number()),orderBy:T.enum(["date_desc","date_asc"]).optional(),limit:T.number().optional(),project:T.string().optional()}),handler:async e=>await uN("/api/observations/batch",e)},{name:"get_session",description:"Session by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/session",e.id)},{name:"get_prompt",description:"Prompt by ID",inputSchema:T.object({id:T.number()}),handler:async e=>await sg("/api/prompt",e.id)}],cg=new wl({name:"mem-search-server",version:"1.0.0"},{capabilities:{tools:{}}});cg.setRequestHandler(Yp,async()=>({tools:rk.map(e=>({name:e.name,description:e.description,inputSchema:Cu(e.inputSchema)}))}));cg.setRequestHandler(Zi,async e=>{let t=rk.find(n=>n.name===e.params.name);if(!t)throw new Error(`Unknown tool: ${e.params.name}`);try{return await t.handler(e.params.arguments||{})}catch(n){return{content:[{type:"text",text:`Tool execution failed: ${n.message}`}],isError:!0}}});async function nk(){be.info("SYSTEM","MCP server shutting down"),process.exit(0)}process.on("SIGTERM",nk);process.on("SIGINT",nk);async function dN(){let e=new Il;await cg.connect(e),be.info("SYSTEM","Claude-mem search server started"),setTimeout(async()=>{await lN()?be.info("SYSTEM","Worker available",void 0,{workerUrl:mo}):(be.warn("SYSTEM","Worker not available",void 0,{workerUrl:mo}),be.warn("SYSTEM","Tools will fail until Worker is started"),be.warn("SYSTEM","Start Worker with: npm run worker:restart"))},0)}dN().catch(e=>{be.error("SYSTEM","Fatal error",void 0,e),process.exit(1)}); diff --git a/plugin/scripts/worker-wrapper.cjs b/plugin/scripts/worker-wrapper.cjs old mode 100644 new mode 100755 diff --git a/plugin/skills/mem-search.zip b/plugin/skills/mem-search.zip index 49d88123..e65648ba 100644 Binary files a/plugin/skills/mem-search.zip and b/plugin/skills/mem-search.zip differ