mirror of
https://github.com/thedotmack/claude-mem.git
synced 2026-07-06 05:56:45 +08:00
27 lines
70 KiB
JavaScript
Executable File
27 lines
70 KiB
JavaScript
Executable File
#!/usr/bin/env bun
|
|
"use strict";var Gr=Object.create;var St=Object.defineProperty;var Kr=Object.getOwnPropertyDescriptor;var Yr=Object.getOwnPropertyNames;var Br=Object.getPrototypeOf,Jr=Object.prototype.hasOwnProperty;var Vr=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Yr(e))!Jr.call(r,o)&&o!==t&&St(r,o,{get:()=>e[o],enumerable:!(n=Kr(e,o))||n.enumerable});return r};var H=(r,e,t)=>(t=r!=null?Gr(Br(r)):{},Vr(e||!r||!r.__esModule?St(t,"default",{value:r,enumerable:!0}):t,r));var P=require("fs"),je=require("os"),re=require("path");var p=require("path"),He=require("os"),te=require("fs"),_t=require("url"),Zr={};function Xr(){return typeof __dirname<"u"?__dirname:(0,p.dirname)((0,_t.fileURLToPath)(Zr.url))}var yo=Xr();function X(){if(process.env.CLAUDE_MEM_DATA_DIR)return process.env.CLAUDE_MEM_DATA_DIR;let r=(0,p.join)((0,He.homedir)(),".claude-mem"),e=(0,p.join)(r,"settings.json");try{if((0,te.existsSync)(e)){let t=JSON.parse((0,te.readFileSync)(e,"utf-8")),n=t.env??t;if(n.CLAUDE_MEM_DATA_DIR)return n.CLAUDE_MEM_DATA_DIR}}catch{}return r}var m=X(),qr=process.env.CLAUDE_CONFIG_DIR||(0,p.join)((0,He.homedir)(),".claude"),ce=(0,p.join)(qr,"plugins","marketplaces","thedotmack"),zr=(0,p.join)(m,"logs"),ue=(0,p.join)(m,"settings.json"),Mo=(0,p.join)(m,"claude-mem.db"),$e=(0,p.join)(m,"observer-sessions"),Qr=(0,p.basename)($e);var E={dataDir:()=>m,workerPid:()=>(0,p.join)(m,"worker.pid"),serverPid:()=>(0,p.join)(m,".server-beta.pid"),serverPort:()=>(0,p.join)(m,".server-beta.port"),serverRuntime:()=>(0,p.join)(m,".server-beta.runtime.json"),settings:()=>(0,p.join)(m,"settings.json"),database:()=>(0,p.join)(m,"claude-mem.db"),chroma:()=>(0,p.join)(m,"chroma"),combinedCerts:()=>(0,p.join)(m,"combined_certs.pem"),transcriptsConfig:()=>(0,p.join)(m,"transcript-watch.json"),transcriptsState:()=>(0,p.join)(m,"transcript-watch-state.json"),corpora:()=>(0,p.join)(m,"corpora"),supervisorRegistry:()=>(0,p.join)(m,"supervisor.json"),envFile:()=>(0,p.join)(m,".env"),logsDir:()=>zr};var q=E.transcriptsConfig(),le=E.transcriptsState(),en={version:1,schemas:{},watches:[],stateFile:le};function tn(r){let e=typeof r.schema=="string"?r.schema:r.schema?.name;if(!(r.name==="codex"||e==="codex")||!r.path)return!1;let n=T(r.path).replace(/\\/g,"/"),o=(0,re.join)((0,je.homedir)(),".codex","sessions").replace(/\\/g,"/");return n===`${o}/**/*.jsonl`}function ht(r){let e=typeof r.schema=="string"?r.schema:r.schema?.name,t=r.name==="codex"&&(!e||e==="codex");return r.context?.mode==="agents"&&t&&tn(r)}function T(r){return r&&(r.startsWith("~")?(0,re.join)((0,je.homedir)(),r.slice(1)):r)}function ne(r=q){let e=T(r);if(!(0,P.existsSync)(e))throw new Error(`Transcript watch config not found: ${e}`);let t=(0,P.readFileSync)(e,"utf-8"),n=JSON.parse(t);if(!n.version||!n.watches)throw new Error(`Invalid transcript watch config: ${e}`);return n.stateFile||(n.stateFile=le),n}function de(r=q){let e=T(r),t=(0,re.dirname)(e);(0,P.existsSync)(t)||(0,P.mkdirSync)(t,{recursive:!0}),(0,P.writeFileSync)(e,JSON.stringify(en,null,2))}var h=require("fs"),A=require("path");var D=require("fs"),wt=require("path");var rn=null;function Ge(r){return(rn??process.stderr.write.bind(process.stderr))(r)}var pe=null;function Ke(r){Ge(r)}function Tt(r,e={}){pe&&pe.length>0&&(Ge(pe.join("")),pe=[]),Ge(r.endsWith(`
|
|
`)?r:`${r}
|
|
`),e.skipExit||process.exit(2)}var Be=(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))(Be||{}),Ye=null,Je=class{level=null;useColor;logFilePath=null;logFileInitialized=!1;constructor(){this.useColor=process.stdout.isTTY??!1}ensureLogFileInitialized(){if(!this.logFileInitialized){this.logFileInitialized=!0;try{let e=E.logsDir();(0,D.existsSync)(e)||(0,D.mkdirSync)(e,{recursive:!0});let t=new Date().toISOString().split("T")[0];this.logFilePath=(0,wt.join)(e,`claude-mem-${t}.log`)}catch(e){console.error("[LOGGER] Failed to initialize log file:",e instanceof Error?e.message:String(e)),this.logFilePath=null}}}getLevel(){if(this.level===null)try{let e=E.settings();if((0,D.existsSync)(e)){let t=(0,D.readFileSync)(e,"utf-8"),o=(JSON.parse(t).CLAUDE_MEM_LOG_LEVEL||"INFO").toUpperCase();this.level=Be[o]??1}else this.level=1}catch(e){console.error("[LOGGER] Failed to load log level from settings:",e instanceof Error?e.message:String(e)),this.level=1}return this.level}formatData(e){if(e==null)return"";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="object"){if(e instanceof Error)return this.getLevel()===0?`${e.message}
|
|
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?JSON.stringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=t}if(e==="Bash"&&n.command)return`${e}(${n.command})`;if(n.file_path)return`${e}(${n.file_path})`;if(n.notebook_path)return`${e}(${n.notebook_path})`;if(e==="Glob"&&n.pattern)return`${e}(${n.pattern})`;if(e==="Grep"&&n.pattern)return`${e}(${n.pattern})`;if(n.url)return`${e}(${n.url})`;if(n.query)return`${e}(${n.query})`;if(e==="Task"){if(n.subagent_type)return`${e}(${n.subagent_type})`;if(n.description)return`${e}(${n.description})`}return e==="Skill"&&n.skill?`${e}(${n.skill})`:e==="LSP"&&n.operation?`${e}(${n.operation})`:e}formatTimestamp(e){let t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),o=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),s=String(e.getMinutes()).padStart(2,"0"),c=String(e.getSeconds()).padStart(2,"0"),u=String(e.getMilliseconds()).padStart(3,"0");return`${t}-${n}-${o} ${i}:${s}:${c}.${u}`}log(e,t,n,o,i){if(e<this.getLevel())return;this.ensureLogFileInitialized();let s=this.formatTimestamp(new Date),c=Be[e].padEnd(5),u=t.padEnd(6),d="";o?.correlationId?d=`[${o.correlationId}] `:o?.sessionId&&(d=`[session-${o.sessionId}] `);let l="";if(i!=null)if(i instanceof Error)l=this.getLevel()===0?`
|
|
${i.message}
|
|
${i.stack}`:` ${i.message}`;else if(this.getLevel()===0&&typeof i=="object")try{l=`
|
|
`+JSON.stringify(i,null,2)}catch{l=" "+this.formatData(i)}else l=" "+this.formatData(i);let S="";if(o){let{sessionId:_,memorySessionId:f,correlationId:W,...ae}=o;Object.keys(ae).length>0&&(S=` {${Object.entries(ae).map(([K,jr])=>`${K}=${jr}`).join(", ")}}`)}let g=`[${s}] [${c}] [${u}] ${d}${n}${S}${l}`;if(this.logFilePath)try{(0,D.appendFileSync)(this.logFilePath,g+`
|
|
`,"utf8")}catch(_){let f=_ instanceof Error?_:new Error(String(_));Ke(`[LOGGER] Failed to write to log file: ${f.message}
|
|
${f.stack??""}
|
|
`)}else Ke(g+`
|
|
`)}debug(e,t,n,o){this.log(0,e,t,n,o)}info(e,t,n,o){this.log(1,e,t,n,o)}warn(e,t,n,o){this.log(2,e,t,n,o)}setErrorSink(e){Ye=e}error(e,t,n,o){this.log(3,e,t,n,o),this.routeErrorToSink(t,n,o)}routeErrorToSink(e,t,n){try{if(!Ye||!(n instanceof Error))return;Ye(n)}catch{}}dataIn(e,t,n,o){this.info(e,`\u2192 ${t}`,n,o)}dataOut(e,t,n,o){this.info(e,`\u2190 ${t}`,n,o)}success(e,t,n,o){this.info(e,`\u2713 ${t}`,n,o)}failure(e,t,n,o){this.error(e,`\u2717 ${t}`,n,o)}},a=new Je;var L=require("fs"),yt=require("path");function Mt(r){try{if(!(0,L.existsSync)(r))return{offsets:{}};let e=(0,L.readFileSync)(r,"utf-8"),t=JSON.parse(e);return t.offsets?t:{offsets:{}}}catch(e){return a.warn("TRANSCRIPT","Failed to load watch state, starting fresh",{statePath:r,error:e instanceof Error?e.message:String(e)}),{offsets:{}}}}function vt(r,e){try{let t=(0,yt.dirname)(r);(0,L.existsSync)(t)||(0,L.mkdirSync)(t,{recursive:!0}),(0,L.writeFileSync)(r,JSON.stringify(e,null,2))}catch(t){a.warn("TRANSCRIPT","Failed to save watch state",{statePath:r,error:t instanceof Error?t.message:String(t)})}}var ie=H(require("path"),1);var Z=H(require("path"),1),v=require("fs");var Rt=require("node:child_process");function fe(r,e,t){return(0,Rt.spawn)(r,e??[],{windowsHide:!0,...t})}var M={HEALTH_CHECK:3e3,API_REQUEST:3e4,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5},$={SUCCESS:0,BLOCKING_ERROR:2};function j(r){return process.platform==="win32"?Math.round(r*M.WINDOWS_MULTIPLIER):r}var C=require("fs"),oe=require("path"),Ve=require("os");var k=class{static DEFAULTS={CLAUDE_MEM_MODEL:"claude-haiku-4-5-20251001",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_WORKER_PORT:String(37700+(process.getuid?.()??77)%100),CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_API_TIMEOUT_MS:String(j(M.API_REQUEST)),CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_PROVIDER:"claude",CLAUDE_MEM_CLAUDE_AUTH_METHOD:"subscription",CLAUDE_MEM_GEMINI_API_KEY:"",CLAUDE_MEM_GEMINI_MODEL:"gemini-2.5-flash-lite",CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED:"true",CLAUDE_MEM_OPENROUTER_API_KEY:"",CLAUDE_MEM_OPENROUTER_MODEL:"xiaomi/mimo-v2-flash:free",CLAUDE_MEM_OPENROUTER_BASE_URL:"",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_DATA_DIR:(0,oe.join)((0,Ve.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",CLAUDE_MEM_MODE:"code",CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT:"true",CLAUDE_MEM_CONTEXT_FULL_COUNT:"0",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",CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT:"true",CLAUDE_MEM_WELCOME_HINT_ENABLED:"true",CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED:"false",CLAUDE_MEM_FOLDER_USE_LOCAL_MD:"false",CLAUDE_MEM_TRANSCRIPTS_ENABLED:"true",CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH:(0,oe.join)((0,Ve.homedir)(),".claude-mem","transcript-watch.json"),CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION:"false",CLAUDE_MEM_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD:"3",CLAUDE_MEM_EXCLUDED_PROJECTS:"",CLAUDE_MEM_FOLDER_MD_EXCLUDE:"[]",CLAUDE_MEM_FOLDER_MD_SKELETON_DENYLIST:"[]",CLAUDE_MEM_SEMANTIC_INJECT:"false",CLAUDE_MEM_SEMANTIC_INJECT_LIMIT:"5",CLAUDE_MEM_TIER_ROUTING_ENABLED:"true",CLAUDE_MEM_TIER_SIMPLE_MODEL:"haiku",CLAUDE_MEM_TIER_SUMMARY_MODEL:"",CLAUDE_MEM_TIER_FAST_MODEL:"haiku",CLAUDE_MEM_TIER_SMART_MODEL:"sonnet",CLAUDE_MEM_CHROMA_ENABLED:"true",CLAUDE_MEM_CHROMA_MODE:"local",CLAUDE_MEM_CHROMA_HOST:"127.0.0.1",CLAUDE_MEM_CHROMA_PORT:"8000",CLAUDE_MEM_CHROMA_SSL:"false",CLAUDE_MEM_CHROMA_API_KEY:"",CLAUDE_MEM_CHROMA_TENANT:"default_tenant",CLAUDE_MEM_CHROMA_DATABASE:"default_database",CLAUDE_MEM_CHROMA_PREWARM_TIMEOUT_MS:"120000",CLAUDE_MEM_TELEGRAM_ENABLED:"true",CLAUDE_MEM_TELEGRAM_BOT_TOKEN:"",CLAUDE_MEM_TELEGRAM_CHAT_ID:"",CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:"security_alert",CLAUDE_MEM_TELEGRAM_TRIGGER_CONCEPTS:"",CLAUDE_MEM_QUEUE_ENGINE:"sqlite",CLAUDE_MEM_REDIS_URL:"",CLAUDE_MEM_REDIS_HOST:"127.0.0.1",CLAUDE_MEM_REDIS_PORT:"6379",CLAUDE_MEM_REDIS_MODE:"external",CLAUDE_MEM_QUEUE_REDIS_PREFIX:`claude_mem_${process.env.CLAUDE_MEM_WORKER_PORT??String(37700+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_AUTH_MODE:"api-key",CLAUDE_MEM_RUNTIME:"worker",CLAUDE_MEM_SERVER_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_API_KEY:"",CLAUDE_MEM_SERVER_PROJECT_ID:"",CLAUDE_MEM_SERVER_BETA_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_BETA_API_KEY:"",CLAUDE_MEM_SERVER_BETA_PROJECT_ID:""};static getAllDefaults(){return{...this.DEFAULTS}}static get(e){return process.env[e]??this.DEFAULTS[e]}static getInt(e){let t=this.get(e);return parseInt(t,10)}static applyEnvOverrides(e){let t={...e};for(let n of Object.keys(this.DEFAULTS))process.env[n]!==void 0&&(t[n]=process.env[n]);return t}static loadFromFile(e,t=!0){try{if(!(0,C.existsSync)(e)){let c=this.getAllDefaults();try{let u=(0,oe.dirname)(e);(0,C.existsSync)(u)||(0,C.mkdirSync)(u,{recursive:!0}),(0,C.writeFileSync)(e,JSON.stringify(c,null,2),"utf-8"),console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(u){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,u instanceof Error?u.message:String(u))}return t?this.applyEnvOverrides(c):c}let n=(0,C.readFileSync)(e,"utf-8"),o=JSON.parse(n.replace(/^\uFEFF/,"")),i=o;if(o.env&&typeof o.env=="object"){i=o.env;try{(0,C.writeFileSync)(e,JSON.stringify(i,null,2),"utf-8"),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(c){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,c instanceof Error?c.message:String(c))}}let s={...this.DEFAULTS};for(let c of Object.keys(this.DEFAULTS))i[c]!==void 0&&(s[c]=i[c]);return t?this.applyEnvOverrides(s):s}catch(n){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,n instanceof Error?n.message:String(n));let o=this.getAllDefaults();return t?this.applyEnvOverrides(o):o}}};var me=null;function x(){return me!==null||(me=k.loadFromFile(ue)),me}var Y=require("fs");var Ze=require("child_process");var O=require("fs"),ze=H(require("path"),1);var nn=["CLAUDECODE_","CLAUDE_CODE_"],on=new Set(["CLAUDECODE","CLAUDE_CODE_SESSION","CLAUDE_CODE_ENTRYPOINT","MCP_SESSION_ID","HTTP_PROXY","HTTPS_PROXY","ALL_PROXY","NO_PROXY","http_proxy","https_proxy","all_proxy","no_proxy","npm_config_proxy","npm_config_https_proxy"]),sn=new Set(["CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_GIT_BASH_PATH","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX","ANTHROPIC_BEDROCK_BASE_URL","AWS_REGION","AWS_PROFILE","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SESSION_TOKEN","ANTHROPIC_VERTEX_PROJECT_ID","CLOUD_ML_REGION","GOOGLE_APPLICATION_CREDENTIALS"]);function ge(r=process.env){let e={};for(let[t,n]of Object.entries(r))if(n!==void 0){if(sn.has(t)){e[t]=n;continue}on.has(t)||nn.some(o=>t.startsWith(o))||(e[t]=n)}return e}var an=5e3,cn=1e3,un=E.supervisorRegistry();function b(r){if(!Number.isInteger(r)||r<0||r===0)return!1;try{return process.kill(r,0),!0}catch(e){if(e instanceof Error){let t=e.code;return t==="EPERM"?!0:(a.debug("SYSTEM","PID check failed",{pid:r,code:t}),!1)}return a.warn("SYSTEM","PID check threw non-Error",{pid:r,error:String(e)}),!1}}async function Ee(r,e){let t=Date.now()+e;for(;Date.now()<t;){if(r.every(n=>!b(n.pid)))return;await new Promise(n=>setTimeout(n,100))}}var ln=5e3,At=new Map;function dn(r){let e=(0,Ze.spawnSync)("powershell.exe",["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId=${r}").CreationDate.ToString('yyyyMMddHHmmss.ffffff')`],{encoding:"utf-8",timeout:5e3,windowsHide:!0,env:{...ge(process.env),LC_ALL:"C",LANG:"C"}});if(e.status===0){let t=e.stdout.trim();return t.length>0?t:null}return null}function pn(r){let e=At.get(r);if(e&&Date.now()-e.capturedAtMs<ln)return e.token;let t=null;try{t=dn(r)}catch(n){a.debug("SYSTEM","captureProcessStartToken: powershell CIM lookup failed",{pid:r,error:n instanceof Error?n.message:String(n)}),t=null}return At.set(r,{token:t,capturedAtMs:Date.now()}),t}function Ct(r){if(!Number.isInteger(r)||r<=0)return null;if(process.platform==="linux")try{let e=(0,O.readFileSync)(`/proc/${r}/stat`,"utf-8"),t=e.lastIndexOf(") ");if(t<0)return null;let o=e.slice(t+2).split(" ")[19];return o&&/^\d+$/.test(o)?o:null}catch(e){return a.debug("SYSTEM","captureProcessStartToken: /proc read failed",{pid:r,error:e instanceof Error?e.message:String(e)}),null}if(process.platform==="win32")return pn(r);try{let e=(0,Ze.spawnSync)("ps",["-p",String(r),"-o","lstart="],{encoding:"utf-8",timeout:2e3,env:{...ge(process.env),LC_ALL:"C",LANG:"C"}});if(e.status!==0)return null;let t=e.stdout.trim();return t.length>0?t:null}catch(e){return a.debug("SYSTEM","captureProcessStartToken: ps exec failed",{pid:r,error:e instanceof Error?e.message:String(e)}),null}}function et(r){if(!r||!b(r.pid))return!1;if(!r.startToken)return!0;let e=Ct(r.pid);if(e===null)return!0;let t=e===r.startToken;return t||a.debug("SYSTEM","verifyPidFileOwnership: start-token mismatch (PID reused)",{pid:r.pid,stored:r.startToken,current:e}),t}var Qe=class{registryPath;entries=new Map;runtimeProcesses=new Map;initialized=!1;constructor(e=un){this.registryPath=e}initialize(){if(this.initialized)return;if(this.initialized=!0,(0,O.mkdirSync)(ze.default.dirname(this.registryPath),{recursive:!0}),!(0,O.existsSync)(this.registryPath)){this.persist();return}try{let n=JSON.parse((0,O.readFileSync)(this.registryPath,"utf-8")).processes??{};for(let[o,i]of Object.entries(n))this.entries.set(o,i)}catch(t){t instanceof Error?a.warn("SYSTEM","Failed to parse supervisor registry, rebuilding",{path:this.registryPath},t):a.warn("SYSTEM","Failed to parse supervisor registry, rebuilding",{path:this.registryPath,error:String(t)}),this.entries.clear()}let e=this.pruneDeadEntries();e>0&&a.info("SYSTEM","Removed dead processes from supervisor registry",{removed:e}),this.persist()}register(e,t,n){this.initialize(),this.entries.set(e,t),n&&this.runtimeProcesses.set(e,n),this.persist()}unregister(e){this.initialize();let t=this.entries.get(e);this.entries.delete(e),this.runtimeProcesses.delete(e),this.persist(),t?.type==="sdk"&&qe()}clear(){this.entries.clear(),this.runtimeProcesses.clear(),this.persist()}getAll(){return this.initialize(),Array.from(this.entries.entries()).map(([e,t])=>({id:e,...t})).sort((e,t)=>{let n=Date.parse(e.startedAt),o=Date.parse(t.startedAt);return(Number.isNaN(n)?0:n)-(Number.isNaN(o)?0:o)})}getBySession(e){let t=String(e);return this.getAll().filter(n=>n.sessionId!==void 0&&String(n.sessionId)===t)}getRuntimeProcess(e){return this.runtimeProcesses.get(e)}pruneDeadEntries(){this.initialize();let e=0,t=0;for(let[n,o]of this.entries)b(o.pid)||(this.entries.delete(n),this.runtimeProcesses.delete(n),e+=1,o.type==="sdk"&&(t+=1));e>0&&this.persist();for(let n=0;n<t;n+=1)qe();return e}async reapSession(e){this.initialize();let t=this.getBySession(e);if(t.length===0)return 0;let n=typeof e=="number"?e:Number(e)||void 0;a.info("SYSTEM",`Reaping ${t.length} process(es) for session ${e}`,{sessionId:n,pids:t.map(s=>s.pid)});let o=t.filter(s=>b(s.pid));for(let s of o)try{typeof s.pgid=="number"&&process.platform!=="win32"?process.kill(-s.pgid,"SIGTERM"):process.kill(s.pid,"SIGTERM")}catch(c){c instanceof Error?c.code!=="ESRCH"&&a.debug("SYSTEM",`Failed to SIGTERM session process PID ${s.pid}`,{pid:s.pid,pgid:s.pgid},c):a.warn("SYSTEM",`Failed to SIGTERM session process PID ${s.pid} (non-Error)`,{pid:s.pid,pgid:s.pgid,error:String(c)})}await Ee(o,an);let i=o.filter(s=>b(s.pid));for(let s of i){a.warn("SYSTEM",`Session process PID ${s.pid} did not exit after SIGTERM, sending SIGKILL`,{pid:s.pid,pgid:s.pgid,sessionId:n});try{typeof s.pgid=="number"&&process.platform!=="win32"?process.kill(-s.pgid,"SIGKILL"):process.kill(s.pid,"SIGKILL")}catch(c){c instanceof Error?c.code!=="ESRCH"&&a.debug("SYSTEM",`Failed to SIGKILL session process PID ${s.pid}`,{pid:s.pid,pgid:s.pgid},c):a.warn("SYSTEM",`Failed to SIGKILL session process PID ${s.pid} (non-Error)`,{pid:s.pid,pgid:s.pgid,error:String(c)})}}if(i.length>0){let s=Date.now()+cn;for(;Date.now()<s&&i.filter(u=>b(u.pid)).length!==0;)await new Promise(u=>setTimeout(u,100))}for(let s of t)this.entries.delete(s.id),this.runtimeProcesses.delete(s.id);this.persist();for(let s of t)s.type==="sdk"&&qe();return a.info("SYSTEM",`Reaped ${t.length} process(es) for session ${e}`,{sessionId:n,reaped:t.length}),t.length}persist(){let e={processes:Object.fromEntries(this.entries.entries())};(0,O.mkdirSync)(ze.default.dirname(this.registryPath),{recursive:!0}),(0,O.writeFileSync)(this.registryPath,JSON.stringify(e,null,2))}},Xe=null;function Se(){return Xe||(Xe=new Qe),Xe}var fn=[];function qe(){let r=fn.shift();r&&r()}var bt=require("child_process"),z=require("fs"),Ot=require("util");var mn=(0,Ot.promisify)(bt.execFile),gn=E.workerPid();async function It(r){let e=r.currentPid??process.pid,t=r.pidFilePath??gn,n=r.registry.getAll(),o=[...n].filter(s=>s.pid!==e).sort((s,c)=>Date.parse(c.startedAt)-Date.parse(s.startedAt));for(let s of o){if(!b(s.pid)){r.registry.unregister(s.id);continue}try{await kt(s,"SIGTERM")}catch(c){c instanceof Error?a.debug("SYSTEM","Failed to send SIGTERM to child process",{pid:s.pid,pgid:s.pgid,type:s.type},c):a.warn("SYSTEM","Failed to send SIGTERM to child process (non-Error)",{pid:s.pid,pgid:s.pgid,type:s.type,error:String(c)})}}await Ee(o,5e3);let i=o.filter(s=>b(s.pid));for(let s of i)try{await kt(s,"SIGKILL")}catch(c){c instanceof Error?a.debug("SYSTEM","Failed to force kill child process",{pid:s.pid,pgid:s.pgid,type:s.type},c):a.warn("SYSTEM","Failed to force kill child process (non-Error)",{pid:s.pid,pgid:s.pgid,type:s.type,error:String(c)})}await Ee(i,1e3);for(let s of o)r.registry.unregister(s.id);for(let s of n.filter(c=>c.pid===e))r.registry.unregister(s.id);Pt(t,e),r.registry.pruneDeadEntries()}function Pt(r,e,t=!1){if(!(0,z.existsSync)(r))return;let n=null;try{let s=JSON.parse((0,z.readFileSync)(r,"utf-8"));n=typeof s.pid=="number"?s.pid:null}catch(s){a.debug("SYSTEM","PID file unreadable \u2014 leaving it (cannot prove ownership)",{pidFilePath:r,error:s instanceof Error?s.message:String(s)});return}let o=e!==null&&n===e,i=n===null||!b(n);if(!o&&!(t&&i)){a.debug("SYSTEM","PID file not owned by this process \u2014 leaving it for its owner (restart successor?)",{pidFilePath:r,recordedPid:n,currentPid:e});return}try{(0,z.rmSync)(r,{force:!0})}catch(s){s instanceof Error?a.debug("SYSTEM","Failed to remove PID file",{pidFilePath:r},s):a.warn("SYSTEM","Failed to remove PID file (non-Error)",{pidFilePath:r,error:String(s)})}}async function kt(r,e){let{pid:t,pgid:n}=r;if(process.platform!=="win32"){if(typeof n=="number")try{process.kill(-n,e);return}catch(i){if((i instanceof Error?i.code:void 0)!=="ESRCH")throw i}try{process.kill(t,e)}catch(i){if((i instanceof Error?i.code:void 0)!=="ESRCH")throw i}return}if(e==="SIGTERM"){try{process.kill(t,e)}catch(i){if(i instanceof Error&&i.code==="ESRCH")return;throw i}return}let o=["/PID",String(t),"/T"];e==="SIGKILL"&&o.push("/F"),await mn("taskkill",o,{timeout:M.POWERSHELL_COMMAND,windowsHide:!0})}var Dt=3e4,Q=null;function En(){let e=Se().pruneDeadEntries();e>0&&a.info("SYSTEM",`Health check: pruned ${e} dead process(es) from registry`)}function Lt(){Q===null&&(Q=setInterval(En,Dt),Q.unref(),a.debug("SYSTEM","Health checker started",{intervalMs:Dt}))}function xt(){Q!==null&&(clearInterval(Q),Q=null,a.debug("SYSTEM","Health checker stopped"))}var Sn=E.workerPid(),tt=class{registry;started=!1;stopPromise=null;signalHandlersRegistered=!1;shutdownInitiated=!1;shutdownHandler=null;constructor(e){this.registry=e}async start(){if(this.started)return;if(this.registry.initialize(),_e({logAlive:!1})==="alive")throw new Error("Worker already running");this.started=!0,Lt()}configureSignalHandlers(e){if(this.shutdownHandler=e,this.signalHandlersRegistered)return;this.signalHandlersRegistered=!0;let t=async n=>{if(this.shutdownInitiated){a.warn("SYSTEM",`Received ${n} but shutdown already in progress`);return}this.shutdownInitiated=!0,a.info("SYSTEM",`Received ${n}, shutting down...`);try{this.shutdownHandler?await this.shutdownHandler():await this.stop()}catch(o){o instanceof Error?a.error("SYSTEM","Error during shutdown",{},o):a.error("SYSTEM","Error during shutdown (non-Error)",{error:String(o)});try{await this.stop()}catch(i){i instanceof Error?a.debug("SYSTEM","Supervisor shutdown fallback failed",{},i):a.debug("SYSTEM","Supervisor shutdown fallback failed",{error:String(i)})}}process.exit(0)};process.on("SIGTERM",()=>{t("SIGTERM")}),process.on("SIGINT",()=>{t("SIGINT")}),process.platform!=="win32"&&(process.argv.includes("--daemon")?process.on("SIGHUP",()=>{a.debug("SYSTEM","Ignoring SIGHUP in daemon mode")}):process.on("SIGHUP",()=>{t("SIGHUP")}))}async stop(){if(this.stopPromise){await this.stopPromise;return}xt(),this.stopPromise=It({registry:this.registry,currentPid:process.pid}).finally(()=>{this.started=!1,this.stopPromise=null}),await this.stopPromise}assertCanSpawn(e){if(this.stopPromise!==null)throw new Error(`Supervisor is shutting down, refusing to spawn ${e}`)}registerProcess(e,t,n){this.registry.register(e,t,n)}unregisterProcess(e){this.registry.unregister(e)}getRegistry(){return this.registry}},is=new tt(Se());function _e(r={}){let e=r.pidFilePath??Sn;if(!(0,Y.existsSync)(e))return"missing";let t=null;try{t=JSON.parse((0,Y.readFileSync)(e,"utf-8"))}catch(o){return o instanceof Error?a.warn("SYSTEM","Failed to parse worker PID file, removing it",{path:e},o):a.warn("SYSTEM","Failed to parse worker PID file, removing it",{path:e,error:String(o)}),(0,Y.rmSync)(e,{force:!0}),"invalid"}return et(t)&&t?((r.logAlive??!0)&&a.info("SYSTEM","Worker already running (PID alive)",{existingPid:t.pid,existingPort:t.port,startedAt:t.startedAt}),"alive"):(a.info("SYSTEM","Removing stale PID file (worker process is dead or PID has been reused)",{pid:t?.pid,port:t?.port,startedAt:t?.startedAt}),(0,Y.rmSync)(e,{force:!0}),"stale")}var rt=require("path"),Te=require("fs"),Ut=require("crypto");var he=require("fs");function Nt(r,e){if(!(0,he.existsSync)(r))return e;try{return JSON.parse((0,he.readFileSync)(r,"utf-8"))}catch(t){throw new Error(`Corrupt JSON file, refusing to overwrite: ${r}: ${t instanceof Error?t.message:String(t)}`)}}var Ft="telemetry.json";function _n(r){let e=r.DO_NOT_TRACK;return e===void 0||e===""?!1:e!=="0"&&e!=="false"}function hn(r,e){if(_n(r))return{enabled:!1,source:"DO_NOT_TRACK"};let t=r.CLAUDE_MEM_TELEMETRY?.toLowerCase();return t==="0"||t==="false"||t==="off"?{enabled:!1,source:"env"}:t==="1"||t==="true"||t==="on"?{enabled:!0,source:"env"}:e?.enabled===!0?{enabled:!0,source:"config"}:e?.enabled===!1?{enabled:!1,source:"config"}:{enabled:!0,source:"default"}}function Wt(r,e){return hn(r,e).enabled}function Tn(){return(0,rt.join)(X(),Ft)}function nt(){let r;try{r=Nt(Tn(),null)}catch(e){let t=e instanceof Error?e:new Error(String(e));return a.warn("SYSTEM","Telemetry: corrupt telemetry.json; treating as no recorded consent",void 0,t),null}return!r||typeof r!="object"||typeof r.installId!="string"||r.enabled!==void 0&&typeof r.enabled!="boolean"?null:{enabled:r.enabled,installId:r.installId,decidedAt:typeof r.decidedAt=="string"?r.decidedAt:""}}function wn(r){let e=X();(0,Te.mkdirSync)(e,{recursive:!0}),(0,Te.writeFileSync)((0,rt.join)(e,Ft),JSON.stringify(r,null,2)+`
|
|
`)}function Ht(){let r=nt();if(r?.installId)return r.installId;let e=(0,Ut.randomUUID)();return wn({installId:e,decidedAt:""}),e}var yn=new Set(["version","os","os_version","is_wsl","arch","runtime","runtime_version","node_version","duration_ms","outcome","error_category","locale","is_ci","endpoint","ide","provider","runtime_mode","trigger","count","has_summary","is_update","install_method","interactive","bun_version","uv_version","claude_code_version","observation_count","session_count","timeline_depth_days","has_session_summary","obs_type_bugfix","obs_type_discovery","obs_type_decision","obs_type_refactor","obs_type_other","tokens_injected","tokens_saved_vs_naive","mode","search_strategy","observation_type","hook","compression_ms","tokens_input","tokens_output","compression_ratio","model","cost_usd","endpoint_class","db_observation_count","db_session_count","db_summary_count","db_project_count","db_size_mb","install_age_days","obs_count_7d","obs_count_30d","days_since_last_obs","result_count","chroma_available","fallback_reason","invalid_output_class","consecutive_invalid_outputs","respawn_triggered","abort_reason","previous_shutdown","previous_uptime_seconds","uptime_seconds","shutdown_reason","process_rss_mb","heap_used_mb","hook_type","error_mode","consecutive_failures","threshold_tripped","discovery_tokens","read_tokens","summary_count","prompt_count","project_count","backfilled","first_active_date","session_completed_count","session_failed_count","sessions_claude_count","sessions_codex_count","sessions_gemini_count","sessions_other_platform_count","subagent_obs_count","total_tokens_input","total_tokens_output","total_cost_usd","avg_duration_ms","avg_compression_ms","outcomes_ok","outcomes_error","outcomes_aborted","outcomes_invalid_output","top_model","window_start_ts","rollup_reason","window_seq","total_tokens","avg_tokens","observations_created","total_observations_injected","total_tokens_saved_vs_naive"]),$t=200;function Mn(r,e){if(!(!r||typeof r!="object"))for(let t of Object.keys(r)){if(!yn.has(t))continue;let n=r[t];typeof n=="string"?e[t]=n.length>$t?n.slice(0,$t):n:(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean")&&(e[t]=n)}}function jt(r){let e={};try{Mn(r,e)}catch{}return e}var ot=H(require("os"),1);var vn="13.10.1",Rn="phc_BKJAeNbpj932N9qEiU6qhutZEiu6LLfRpXfTbLM9MLaG",An="https://us.i.posthog.com";function Gt(){return process.env.CLAUDE_MEM_TELEMETRY_KEY||Rn}function Kt(){return process.env.CLAUDE_MEM_TELEMETRY_HOST||An}var Cn=["version","os","os_version","is_wsl","arch","runtime","locale","ide","provider","runtime_mode","install_method","claude_code_version","first_active_date","db_observation_count","db_session_count","db_summary_count","db_project_count","db_size_mb","install_age_days","obs_count_7d","obs_count_30d","days_since_last_obs"];function Yt(r){let e={};for(let t of Cn)r[t]!==void 0&&(e[t]=r[t]);return e}function kn(){if(process.platform!=="linux")return!1;try{return!!process.env.WSL_DISTRO_NAME||ot.default.release().toLowerCase().includes("microsoft")}catch(r){let e=r instanceof Error?r:new Error(String(r));return a.warn("SYSTEM","Telemetry: WSL detection failed; reporting is_wsl=false",void 0,e),!1}}function Bt(){return{version:vn,os:process.platform,os_version:ot.default.release(),is_wsl:kn(),arch:process.arch,runtime:process.versions.bun?"bun":"node",runtime_version:process.versions.bun??process.versions.node,node_version:process.versions.node,is_ci:!!process.env.CI,locale:Intl.DateTimeFormat().resolvedOptions().locale}}var bn=2e3;async function Jt(r,e,t){try{if(!Wt(process.env,nt()))return;let n=jt({...Bt(),...e??{}});if(t?.person?n.$set=Yt(n):n.$process_person_profile=!1,process.env.CLAUDE_MEM_TELEMETRY_DEBUG==="1"){process.stderr.write("[telemetry] "+JSON.stringify({event:r,properties:n})+`
|
|
`);return}let o=Gt(),i=new AbortController,s=setTimeout(()=>i.abort(),bn);try{await On(o,r,n,i.signal)}finally{clearTimeout(s)}}catch{}}async function On(r,e,t,n){await fetch(`${Kt()}/capture/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:r,event:e,distinct_id:Ht(),properties:t}),signal:n})}var B=H(require("path"),1),Xt=require("os"),N=require("fs"),it=require("child_process");var As=E.dataDir(),Cs=E.workerPid();function Vt(r){return r?/(^|[\\/])bun(\.exe)?$/i.test(r.trim()):!1}function Pn(r,e){let t=e==="win32"?`where ${r}`:`which ${r}`,n;try{n=(0,it.execSync)(t,{stdio:["ignore","pipe","ignore"],encoding:"utf-8",windowsHide:!0})}catch(i){return i instanceof Error?a.debug("SYSTEM",`Binary lookup failed for ${r}`,{command:t},i):a.debug("SYSTEM",`Binary lookup failed for ${r}`,{command:t},new Error(String(i))),null}return n.split(/\r?\n/).map(i=>i.trim()).find(i=>i.length>0)||null}var st;function qt(r={}){let e=Object.keys(r).length===0;if(e&&st!==void 0)return st;let t=Dn(r);return e&&t!==null&&(st=t),t}function Dn(r){let e=r.platform??process.platform,t=r.execPath??process.execPath;if(Vt(t))return t;let n=r.env??process.env,o=r.homeDirectory??(0,Xt.homedir)(),i=r.pathExists??N.existsSync,s=r.lookupInPath??Pn,c=e==="win32"?[n.BUN,n.BUN_PATH,B.default.join(o,".bun","bin","bun.exe"),B.default.join(o,".bun","bin","bun"),n.USERPROFILE?B.default.join(n.USERPROFILE,".bun","bin","bun.exe"):void 0,n.LOCALAPPDATA?B.default.join(n.LOCALAPPDATA,"bun","bun.exe"):void 0,n.LOCALAPPDATA?B.default.join(n.LOCALAPPDATA,"bun","bin","bun.exe"):void 0]:[n.BUN,n.BUN_PATH,B.default.join(o,".bun","bin","bun"),"/usr/local/bin/bun","/opt/homebrew/bin/bun","/home/linuxbrew/.linuxbrew/bin/bun","/usr/bin/bun","/snap/bin/bun"];for(let u of c){let d=u?.trim();if(d&&(Vt(d)&&i(d)||d.toLowerCase()==="bun"))return d}return s("bun",e)}var zt=H(require("path"),1);var Qt=require("fs");async function Ln(r,e,t="GET"){let n=await fetch(`http://127.0.0.1:${r}${e}`,{method:t}),o="";try{o=await n.text()}catch{}return{ok:n.ok,statusCode:n.status,body:o}}function xn(){try{let r=zt.default.join(ce,"package.json");return JSON.parse((0,Qt.readFileSync)(r,"utf-8")).version}catch(r){if(r instanceof Error){let e=r.code;if(e==="ENOENT"||e==="EBUSY")return a.debug("SYSTEM","Could not read plugin version (shutdown race)",{code:e}),"unknown";throw r}throw r}}async function Nn(r){try{let e=await Ln(r,"/api/version");return e.ok?JSON.parse(e.body).version:null}catch{return a.debug("SYSTEM","Could not fetch worker version",{}),null}}async function Zt(r){let e=xn(),t=await Nn(r);return!t||e==="unknown"?{matches:!0,pluginVersion:e,workerVersion:t}:{matches:e===t,pluginVersion:e,workerVersion:t}}var we=require("path"),w=require("fs");var Un=6e4;function er(){return(0,we.join)(X(),"spawn.lock")}function tr(){let r=er(),e=JSON.stringify({pid:process.pid,startedAt:new Date().toISOString()});for(let t=0;t<2;t++)try{return(0,w.mkdirSync)((0,we.dirname)(r),{recursive:!0}),(0,w.writeFileSync)(r,e,{flag:"wx"}),!0}catch(n){let o=n instanceof Error?n:new Error(String(n)),i=o.code;if(i!=="EEXIST")return a.warn("SYSTEM","Spawn lock write failed for a non-contention reason; failing open (spawning unlocked)",{lockPath:r,code:i},o),!0;if(t>0)return!1;let s;try{s=(0,w.statSync)(r).mtimeMs}catch{continue}if(Date.now()-s<=Un)return!1;let c;try{c=(0,w.statSync)(r).mtimeMs}catch{continue}if(c!==s)return!1;try{(0,w.unlinkSync)(r)}catch{return!1}}return!1}function rr(){let r=er();try{if(JSON.parse((0,w.readFileSync)(r,"utf-8")).pid!==process.pid)return;(0,w.unlinkSync)(r)}catch{}}function ar(r,e,t){let n=process.env[r];if(n){let o=parseInt(n,10);if(Number.isFinite(o)&&o>=t.min&&o<=t.max)return o;a.warn("SYSTEM",`Invalid ${r}, using default`,{value:n,min:t.min,max:t.max})}return e}var Ce=ar("CLAUDE_MEM_HEALTH_TIMEOUT_MS",j(M.HEALTH_CHECK),{min:500,max:3e5}),cr=ar("CLAUDE_MEM_HOOK_READINESS_TIMEOUT_MS",j(M.HOOK_READINESS_WAIT),{min:0,max:3e5}),Fn={min:500,max:3e5};async function lt(r,e={},t){try{return await fetch(r,{...e,signal:AbortSignal.timeout(t)})}catch(n){throw n instanceof DOMException&&n.name==="TimeoutError"?new Error(`Request timed out after ${t}ms`):n}}var ye=null,Me=null,ve=null,Re=null;function Wn(){return Z.default.join(k.get("CLAUDE_MEM_DATA_DIR"),"settings.json")}function dt(){return ve!==null||(ve=k.loadFromFile(Wn())),ve}function nr(r,e){if(!r)return null;let t=parseInt(r,10);return Number.isFinite(t)&&t>=e.min&&t<=e.max?t:null}function Hn(r,e,t){let n=process.env[r];if(n!==void 0){let s=nr(n,t);return s!==null?s:(a.warn("SYSTEM",`Invalid ${r}, using default`,{value:n,min:t.min,max:t.max}),e)}let o=dt()[r],i=nr(o,t);return i!==null?i:(a.warn("SYSTEM",`Invalid ${r} in settings.json, using default`,{value:o,min:t.min,max:t.max}),e)}function ur(){if(ye!==null)return ye;let r=dt();return ye=parseInt(r.CLAUDE_MEM_WORKER_PORT,10),ye}function $n(){return Me!==null||(Me=dt().CLAUDE_MEM_WORKER_HOST),Me}function jn(){return Re!==null||(Re=Hn("CLAUDE_MEM_API_TIMEOUT_MS",j(M.API_REQUEST),Fn)),Re}function Gn(r){return`http://${$n()}:${ur()}${r}`}function U(r,e={}){let t=e.method??"GET",n=e.timeoutMs??jn(),o=Gn(r),i={method:t};return e.headers&&(i.headers=e.headers),e.body&&(i.body=e.body),n>0?lt(o,i,n):fetch(o,i)}async function Kn(){return(await U("/api/health",{timeoutMs:Ce})).ok}async function or(){return(await U("/api/readiness",{timeoutMs:Ce})).ok}function Yn(){let r=[Z.default.join(ce,"plugin","scripts","worker-service.cjs"),Z.default.join(process.cwd(),"plugin","scripts","worker-service.cjs")];for(let e of r)if((0,v.existsSync)(e))return e;return null}async function Bn(r){let e=r.backoffMs;for(let t=1;t<=r.attempts;t++){if(await dr())return!0;t<r.attempts&&(await new Promise(n=>setTimeout(n,e)),e*=2)}return!1}async function at(r=cr){if(r<=0)try{return await or()}catch(t){let n=t instanceof Error?t:new Error(String(t));return a.debug("SYSTEM","Worker readiness check threw",{},n),!1}let e=Date.now();for(;Date.now()-e<r;){try{if(await or())return!0}catch(n){a.debug("SYSTEM","Worker readiness check threw",{error:n instanceof Error?n.message:String(n)})}let t=r-(Date.now()-e);if(t<=0)break;await new Promise(n=>setTimeout(n,Math.min(250,t)))}return!1}async function lr(){try{let e=await(await U("/api/health",{timeoutMs:Ce})).json();return typeof e.version=="string"?e.version:null}catch(r){let e=r instanceof Error?r:new Error(String(r));return a.debug("SYSTEM","Worker health-version fetch failed",{},e),null}}async function Jn(r,e=cr){let t=Date.now();for(;Date.now()-t<e;){if(await lr()===r)return!0;let o=e-(Date.now()-t);if(o<=0)break;await new Promise(i=>setTimeout(i,Math.min(500,o)))}return!1}async function ct(r){let e=await lr();e!==null&&e!==r&&a.warn("SYSTEM","Worker is ready but still reports a stale version; not recycling again in this hook invocation (one recycle per hook event)",{pluginVersion:r,workerVersion:e})}async function dr(){let r;try{r=await Kn()}catch(t){return a.debug("SYSTEM","Worker health check threw",{error:t instanceof Error?t.message:String(t)}),!1}if(!r)return!1;let e=_e({logAlive:!1});return e==="missing"||e==="alive"}async function ke(){let r=null;if(await dr()){let{matches:i,pluginVersion:s,workerVersion:c}=await Zt(ur());if(s!=="unknown"&&(r=s),i)return await at()?(r!==null&&await ct(r),!0):(a.warn("SYSTEM","Worker is healthy but not ready; skipping hook API call"),!1);a.info("SYSTEM","Worker version mismatch \u2014 recycling stale worker",{pluginVersion:s,workerVersion:c});let u=!1;try{await U("/api/admin/restart",{method:"POST",timeoutMs:Ce}),u=!0}catch(d){let l=d instanceof Error?d:new Error(String(d));a.debug("SYSTEM","Worker restart request failed; falling through to lazy-spawn",{},l)}if(u){if(await Jn(s))return await at()?(r!==null&&await ct(r),!0):(a.warn("SYSTEM","Recycled worker appeared but did not become ready; skipping hook API call"),!1);a.warn("SYSTEM","No successor worker appeared after recycle; falling through to lazy-spawn",{pluginVersion:s,workerVersion:c})}}let e=qt(),t=Yn();if(!e)return a.warn("SYSTEM","Cannot lazy-spawn worker: Bun runtime not found on PATH"),!1;if(!t)return a.warn("SYSTEM","Cannot lazy-spawn worker: worker-service.cjs not found in plugin/scripts"),!1;let n=tr();try{if(n){a.info("SYSTEM","Worker not running \u2014 lazy-spawning",{runtimePath:e,scriptPath:t});try{fe(e,[t,"--daemon"],{detached:!0,stdio:["ignore","ignore","ignore"]}).unref()}catch(s){return s instanceof Error?a.error("SYSTEM","Lazy-spawn of worker failed",{runtimePath:e,scriptPath:t},s):a.error("SYSTEM","Lazy-spawn of worker failed (non-Error)",{runtimePath:e,scriptPath:t,error:String(s)}),!1}}else a.info("SYSTEM","Another launcher holds the spawn lock \u2014 skipping lazy-spawn and waiting for its worker");if(!await Bn({attempts:6,backoffMs:500}))return a.warn("SYSTEM",n?"Worker port did not open after lazy-spawn within the cold-boot wait (~15s)":"Spawn-lock holder's worker port did not open within the cold-boot wait (~15s)"),!1}finally{n&&rr()}return await at()?(r!==null&&await ct(r),!0):(a.warn("SYSTEM","Worker lazy-spawned but did not become ready before hook readiness timeout"),!1)}var Ae=null;async function Vn(){return Ae!==null||(Ae=await ke()),Ae}var Xn=3;function pr(){return Z.default.join(m,"state")}function fr(){return Z.default.join(pr(),"hook-failures.json")}function qn(r){let e=JSON.parse(r);return{consecutiveFailures:typeof e.consecutiveFailures=="number"&&Number.isFinite(e.consecutiveFailures)?Math.max(0,Math.floor(e.consecutiveFailures)):0,lastFailureAt:typeof e.lastFailureAt=="number"&&Number.isFinite(e.lastFailureAt)?e.lastFailureAt:0}}function mr(){try{return qn((0,v.readFileSync)(fr(),"utf-8"))}catch{return{consecutiveFailures:0,lastFailureAt:0}}}function gr(r){let e=pr(),t=fr(),n=`${t}.tmp`;try{(0,v.existsSync)(e)||(0,v.mkdirSync)(e,{recursive:!0}),(0,v.writeFileSync)(n,JSON.stringify(r),"utf-8"),(0,v.renameSync)(n,t)}catch(o){a.debug("SYSTEM","Failed to persist hook-failure counter",{error:o instanceof Error?o.message:String(o)})}}function zn(){try{let e=x().CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD,t=parseInt(e,10);if(Number.isFinite(t)&&t>=1)return t}catch{}return Xn}var sr=null;async function Qn(){let e={consecutiveFailures:mr().consecutiveFailures+1,lastFailureAt:Date.now()};gr(e);let t=zn();return e.consecutiveFailures>=t&&(e.consecutiveFailures===t&&await Jt("hook_failed",{...sr!==null?{hook_type:sr}:{},error_mode:"worker_unavailable",consecutive_failures:e.consecutiveFailures,threshold_tripped:!0}),Tt(`claude-mem worker unreachable for ${e.consecutiveFailures} consecutive hooks.`)),e.consecutiveFailures}function ir(){mr().consecutiveFailures!==0&&gr({consecutiveFailures:0,lastFailureAt:0})}var ut=Symbol.for("claude-mem/worker-fallback");function be(r){return typeof r=="object"&&r!==null&&r[ut]===!0}async function Oe(r,e,t,n={}){if(!await Vn())return await Qn(),{continue:!0,reason:"worker_unreachable",[ut]:!0};let i={method:e};t!==void 0&&(i.headers={"Content-Type":"application/json"},i.body=JSON.stringify(t)),n.timeoutMs!==void 0&&(i.timeoutMs=n.timeoutMs);let s=await U(r,i);if(!s.ok){let u=await s.text().catch(()=>"");if(ir(),s.status===429||s.status>=500)return a.warn("SYSTEM",`Worker API ${e} ${r} returned ${s.status}; skipping hook API call`,{body:u.substring(0,200)}),{continue:!0,reason:`worker_api_${s.status}`,[ut]:!0};let d=u;try{d=JSON.parse(u)}catch{}return d}ir();let c=await s.text();if(c.length!==0)try{return JSON.parse(c)}catch{return c}}var Sr=require("os"),_r=H(require("path"),1),hr=require("child_process");var Pe=require("fs"),Ie=H(require("path"),1);var se={isWorktree:!1,worktreeName:null,parentRepoPath:null,parentProjectName:null};function Er(r){let e=Ie.default.join(r,".git"),t;try{t=(0,Pe.statSync)(e)}catch(l){return l instanceof Error&&l.code!=="ENOENT"&&a.warn("GIT","Unexpected error checking .git",{error:l instanceof Error?l.message:String(l)}),se}if(!t.isFile())return se;let n;try{n=(0,Pe.readFileSync)(e,"utf-8").trim()}catch(l){return a.warn("GIT","Failed to read .git file",{error:l instanceof Error?l.message:String(l)}),se}let o=n.match(/^gitdir:\s*(.+)$/);if(!o)return se;let s=o[1].match(/^(.+)[/\\]\.git[/\\]worktrees[/\\]([^/\\]+)$/);if(!s)return se;let c=s[1],u=Ie.default.basename(r),d=Ie.default.basename(c);return{isWorktree:!0,worktreeName:u,parentRepoPath:c,parentProjectName:d}}function Tr(r){return r==="~"||r.startsWith("~/")?r.replace(/^~/,(0,Sr.homedir)()):r}function Zn(r){try{return(0,hr.execFileSync)("git",["rev-parse","--show-toplevel"],{cwd:r,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch(e){let t=e instanceof Error?e:new Error(String(e));return a.debug("PROJECT_NAME","git rev-parse failed, falling back to basename",{dir:r},t),null}}function eo(r){if(!r||r.trim()==="")return a.warn("PROJECT_NAME","Empty cwd provided, using fallback",{cwd:r}),"unknown-project";let e=Tr(r),n=Zn(e)??e,o=_r.default.basename(n);if(o===""){if(process.platform==="win32"){let s=r.match(/^([A-Z]):\\/i);if(s){let u=`drive-${s[1].toUpperCase()}`;return a.info("PROJECT_NAME","Drive root detected",{cwd:r,projectName:u}),u}}return a.warn("PROJECT_NAME","Root directory detected, using fallback",{cwd:r}),"unknown-project"}return o}function J(r){let e=eo(r);if(!r)return{primary:e,parent:null,isWorktree:!1,allProjects:[e]};let t=Tr(r),n=Er(t);if(n.isWorktree&&n.parentProjectName){let o=`${n.parentProjectName}/${e}`;return{primary:o,parent:n.parentProjectName,isWorktree:!0,allProjects:[n.parentProjectName,o]}}return{primary:e,parent:null,isWorktree:!1,allProjects:[e]}}var V=require("path");var wr=require("os"),yr=require("path");function to(r){let e=r.startsWith("~")?(0,wr.homedir)()+r.slice(1):r;e=e.replace(/\\/g,"/");let t=e.replace(/[.+^${}()|[\]\\]/g,"\\$&");return t=t.replace(/\*\*/g,"<<<GLOBSTAR>>>").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/<<<GLOBSTAR>>>/g,".*"),new RegExp(`^${t}$`)}function De(r,e){if(!e||!e.trim())return!1;let t=r.replace(/\\/g,"/"),n=(0,yr.basename)(t),o=e.split(",").map(i=>i.trim()).filter(Boolean);for(let i of o)try{let s=to(i);if(s.test(t)||s.test(n))return!0}catch(s){a.warn("PROJECT_NAME","Invalid exclusion pattern",{pattern:i,error:s instanceof Error?s.message:String(s)});continue}return!1}function ro(r,e){let t=(0,V.normalize)(r),n=(0,V.normalize)(e);if(t===n)return!0;let o=(0,V.relative)(n,t);return o.length>0&&!o.startsWith("..")&&!(0,V.isAbsolute)(o)}function Le(r){if(process.env.CLAUDE_MEM_INTERNAL==="1")return!1;if(!r)return!0;if(ro(r,$e))return!1;let e=x();return!De(r,e.CLAUDE_MEM_EXCLUDED_PROJECTS)}var Mr="claude";function no(r){return r.trim().toLowerCase().replace(/\s+/g,"-")}function I(r){if(!r)return Mr;let e=no(r);return e?e==="transcript"||e.includes("codex")?"codex":e.includes("cursor")?"cursor":e.includes("claude")?"claude":e:Mr}var Ar=["private","claude-mem-context","system_instruction","system-instruction","persisted-output","system-reminder"],vr=new RegExp(`<(${Ar.join("|")})\\b[^>]*>[\\s\\S]*?</\\1>`,"g");var Rr=100;function oo(r){let e=Object.fromEntries(Ar.map(o=>[o,0]));vr.lastIndex=0;let t=0,n=r.replace(vr,(o,i)=>(e[i]=(e[i]??0)+1,t+=1,""));return t>Rr&&a.warn("SYSTEM","tag count exceeds limit",void 0,{tagCount:t,maxAllowed:Rr,contentLength:r.length}),{stripped:n.trim(),counts:e}}function pt(r){return oo(r).stripped}var so=["task-notification"],io=new RegExp(`^\\s*<(${so.join("|")})\\b[^>]*>(?:(?!<\\1\\b|</\\1\\b)[\\s\\S])*</\\1>\\s*$`),ao=256*1024;function Cr(r){return!r||r.length>ao?!1:io.test(r)}var co=j(M.API_REQUEST),F=class extends Error{kind;status;cause;constructor(e,t,n={}){super(t),this.name="ServerClientError",this.kind=e,this.status=n.status??null,this.cause=n.cause}isFallbackEligible(){return this.kind==="transport"||this.kind==="timeout"||this.kind==="missing_api_key"||this.kind==="http_error"&&(this.status!==null&&this.status>=500||this.status===429)}},xe=class{baseUrl;apiKey;timeoutMs;constructor(e){this.baseUrl=uo(e.serverBaseUrl),this.apiKey=e.apiKey,this.timeoutMs=e.timeoutMs??co}async startSession(e){let t=this.buildStartSessionPayload(e);return this.request("POST","/v1/sessions/start",t)}async recordEvent(e){let t=this.buildEventPayload(e),n=e.generate===!1?"/v1/events?generate=false":"/v1/events";return this.request("POST",n,t)}async endSession(e){if(!e.sessionId)throw new F("invalid_response","sessionId is required for endSession");return this.request("POST",`/v1/sessions/${encodeURIComponent(e.sessionId)}/end`,{})}async addObservation(e){return this.request("POST","/v1/memories",this.buildAddObservationPayload(e))}async searchObservations(e){return this.request("POST","/v1/search",this.buildSearchPayload(e))}async contextObservations(e){return this.request("POST","/v1/context",this.buildSearchPayload(e))}async getJobStatus(e){if(!e)throw new F("invalid_response","jobId is required for getJobStatus");return this.request("GET",`/v1/jobs/${encodeURIComponent(e)}`)}buildAddObservationPayload(e){let t=e.content,n=e.kind??"manual",o=typeof e.metadata?.title=="string"?e.metadata.title:void 0;return{projectId:e.projectId,kind:n,type:n,narrative:t,...o?{title:o}:{},...e.serverSessionId!==void 0?{serverSessionId:e.serverSessionId}:{},...e.metadata!==void 0?{metadata:e.metadata}:{}}}buildSearchPayload(e){return{projectId:e.projectId,query:e.query,...e.limit!==void 0?{limit:e.limit}:{},...e.platformSource!==void 0?{platformSource:ft(e.platformSource)}:{}}}buildStartSessionPayload(e){return{projectId:e.projectId,...e.externalSessionId!==void 0?{externalSessionId:e.externalSessionId}:{},...e.contentSessionId!==void 0?{contentSessionId:e.contentSessionId}:{},...e.agentId!==void 0?{agentId:e.agentId}:{},...e.agentType!==void 0?{agentType:e.agentType}:{},...e.platformSource!==void 0?{platformSource:ft(e.platformSource)}:{},...e.metadata!==void 0?{metadata:e.metadata}:{}}}buildEventPayload(e){return{projectId:e.projectId,sourceType:e.sourceType,eventType:e.eventType,occurredAtEpoch:e.occurredAtEpoch,...e.serverSessionId!==void 0?{serverSessionId:e.serverSessionId}:{},...e.contentSessionId!==void 0?{contentSessionId:e.contentSessionId}:{},...e.memorySessionId!==void 0?{memorySessionId:e.memorySessionId}:{},...e.platformSource!==void 0?{platformSource:ft(e.platformSource)}:{},...e.payload!==void 0?{payload:e.payload}:{}}}async request(e,t,n){if(!this.apiKey||!this.apiKey.trim())throw new F("missing_api_key","Server API key is not configured (CLAUDE_MEM_SERVER_API_KEY).");let o=`${this.baseUrl}${t}`,i={method:e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}};n!==void 0&&(i.body=JSON.stringify(n));let s;try{s=await lt(o,i,this.timeoutMs)}catch(u){let d=u instanceof Error?u.message:String(u),l=/timed out|timeout/i.test(d);throw new F(l?"timeout":"transport",`Server ${e} ${t} failed: ${d}`,{cause:u})}if(!s.ok){let u=await s.text().catch(()=>"");throw new F("http_error",`Server ${e} ${t} returned ${s.status}: ${lo(u,200)}`,{status:s.status})}let c=await s.text();if(!c||c.length===0)return{};try{return JSON.parse(c)}catch(u){let d=u instanceof Error?u:new Error(String(u));throw new F("invalid_response",`Server ${e} ${t} returned non-JSON response`,{cause:d})}}};function kr(r){return r instanceof F}function uo(r){return r.replace(/\/+$/,"")}function ft(r){return typeof r=="string"?I(r):null}function lo(r,e){return r.length<=e?r:`${r.slice(0,e)}\u2026`}function po(){let e=(x().CLAUDE_MEM_RUNTIME??"worker").trim().toLowerCase();return e==="server"||e==="server-beta"?"server":"worker"}function fo(){let r=x(),e=(...s)=>{for(let c of s){let u=(c??"").trim();if(u.length>0)return u}return""},t=e(r.CLAUDE_MEM_SERVER_URL,r.CLAUDE_MEM_SERVER_BETA_URL),n=e(r.CLAUDE_MEM_SERVER_API_KEY,r.CLAUDE_MEM_SERVER_BETA_API_KEY),o=e(r.CLAUDE_MEM_SERVER_PROJECT_ID,r.CLAUDE_MEM_SERVER_BETA_PROJECT_ID);if(!t)return a.warn("HOOK","[server-fallback] reason=missing_base_url"),null;if(!n)return a.warn("HOOK","[server-fallback] reason=missing_api_key"),null;if(!o)return a.warn("HOOK","[server-fallback] reason=missing_project_id"),null;let i={serverBaseUrl:t,apiKey:n};return{runtime:"server",client:new xe(i),projectId:o,serverBaseUrl:t}}function br(){if(po()!=="server")return{runtime:"worker"};let r=fo();return r||{runtime:"worker"}}function Or(r,e){a.warn("HOOK",`[server-fallback] reason=${r}`,e??{})}var mo={executeWithWorkerFallback:Oe,isWorkerFallback:be,loadFromFileOnce:x,resolveRuntimeContext:br,logServerFallback:Or,shouldTrackProject:Le},G=mo;var Ir={async execute(r){let{sessionId:e,prompt:t}=r,n=r.cwd??process.cwd();if(!e)return a.warn("HOOK","session-init: No sessionId provided, skipping (Codex CLI or unknown platform)"),{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS};if(!G.shouldTrackProject(n))return a.info("HOOK","Project excluded from tracking",{cwd:n}),{continue:!0,suppressOutput:!0};if(t&&Cr(t))return a.debug("HOOK","session-init: skipping internal protocol payload",{preview:t.slice(0,80)}),{continue:!0,suppressOutput:!0};let o=!t||!t.trim()?"[media prompt]":t,i=J(n).primary,s=I(r.platform),c=G.loadFromFileOnce(),u=String(c.CLAUDE_MEM_SEMANTIC_INJECT).toLowerCase()==="true",d=G.resolveRuntimeContext();if(d.runtime==="server")try{return await go(d,r,e,s,i,o),{continue:!0,suppressOutput:!0}}catch(f){if(kr(f)&&f.isFallbackEligible())G.logServerFallback(f.kind,{status:f.status,message:f.message,route:"/v1/sessions/start"});else return a.error("HOOK","Server session-start failed (non-recoverable)",{error:f instanceof Error?f.message:String(f)}),{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS}}a.debug("HOOK","session-init: Calling /api/sessions/init",{contentSessionId:e,project:i});let l=await G.executeWithWorkerFallback("/api/sessions/init","POST",{contentSessionId:e,project:i,prompt:o,platformSource:s});if(G.isWorkerFallback(l))return{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS};if(typeof l?.sessionDbId!="number")return a.failure("HOOK","Session initialization returned malformed response",{contentSessionId:e,project:i}),{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS};let S=l.sessionDbId,g=l.promptNumber;if(a.debug("HOOK","session-init: Received from /api/sessions/init",{sessionDbId:S,promptNumber:g,skipped:l.skipped,contextInjected:l.contextInjected}),a.debug("HOOK",`[ALIGNMENT] Hook Entry | contentSessionId=${e} | prompt#=${g} | sessionDbId=${S}`),l.skipped&&l.reason==="private")return a.info("HOOK",`INIT_COMPLETE | sessionDbId=${S} | promptNumber=${g} | skipped=true | reason=private`,{sessionId:S}),{continue:!0,suppressOutput:!0};let _="";if(u&&o&&o.length>=20&&o!=="[media prompt]"){let f=c.CLAUDE_MEM_SEMANTIC_INJECT_LIMIT||"5",W=await G.executeWithWorkerFallback("/api/context/semantic","POST",{q:o,project:i,limit:f,platformSource:s});!G.isWorkerFallback(W)&&W?.context&&(a.debug("HOOK",`Semantic injection: ${W.count} observations for prompt`,{sessionId:S,count:W.count}),_=W.context)}return a.info("HOOK",`INIT_COMPLETE | sessionDbId=${S} | promptNumber=${g} | project=${i}`,{sessionId:S}),_?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:_}}:{continue:!0,suppressOutput:!0}}};async function go(r,e,t,n,o,i){await r.client.startSession({projectId:r.projectId,externalSessionId:t,contentSessionId:t,agentId:e.agentId??null,agentType:e.agentType??null,platformSource:n,metadata:{project:o,prompt:i}}),a.info("HOOK","session-init: server session started",{contentSessionId:t,project:o})}var Pr={async execute(r){let{sessionId:e,cwd:t,filePath:n,edits:o}=r,i=I(r.platform);if(!n)throw new Error("fileEditHandler requires filePath");if(a.dataIn("HOOK",`FileEdit: ${n}`,{editCount:o?.length??0}),!t)throw new Error(`Missing cwd in FileEdit hook input for session ${e}, file ${n}`);if(!Le(t))return a.debug("HOOK","Project excluded from tracking, skipping file edit observation",{cwd:t,filePath:n}),{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS};let s=await Oe("/api/sessions/observations","POST",{contentSessionId:e,platformSource:i,tool_name:"write_file",tool_input:{filePath:n,edits:o},tool_response:{success:!0},cwd:t});return be(s)?{continue:!0,suppressOutput:!0,exitCode:$.SUCCESS}:(a.debug("HOOK","File edit observation sent successfully",{filePath:n}),{continue:!0,suppressOutput:!0})}};var R=require("fs"),Ne=require("path");var ta=E.settings();function Dr(r,e){let t="<claude-mem-context>",n="</claude-mem-context>";if(!r)return`${t}
|
|
${e}
|
|
${n}`;let o=r.indexOf(t),i=r.indexOf(n);return o!==-1&&i!==-1?r.substring(0,o)+`${t}
|
|
${e}
|
|
${n}`+r.substring(i+n.length):r+`
|
|
|
|
${t}
|
|
${e}
|
|
${n}`}function Lr(r,e){if(!r)return;let t=(0,Ne.resolve)(r);if(t.includes("/.git/")||t.includes("\\.git\\")||t.endsWith("/.git")||t.endsWith("\\.git"))return;let n=(0,Ne.dirname)(r);(0,R.existsSync)(n)||(0,R.mkdirSync)(n,{recursive:!0});let o="";(0,R.existsSync)(r)&&(o=(0,R.readFileSync)(r,"utf-8"));let i=`# Memory Context
|
|
|
|
${e}`,s=Dr(o,i),c=`${r}.tmp`;try{(0,R.writeFileSync)(c,s),(0,R.renameSync)(c,r)}catch(u){a.error("AGENTS_MD","Failed to write AGENTS.md",{agentsPath:r},u instanceof Error?u:new Error(String(u)))}}function Eo(r){let e=r.trim().replace(/^\$\.?/,"");if(!e)return[];let t=[],n=e.split(".");for(let o of n){let i=/([^[\]]+)|\[(\d+)\]/g,s;for(;(s=i.exec(o))!==null;)s[1]?t.push(s[1]):s[2]&&t.push(parseInt(s[2],10))}return t}function mt(r,e){if(!e)return;let t=Eo(e),n=r;for(let o of t){if(n==null)return;n=n[o]}return n}function xr(r){return r==null||r===""}function Nr(r,e){if(r.startsWith("$watch.")){let t=r.slice(7);return e.watch[t]}if(r.startsWith("$schema.")){let t=r.slice(8);return e.schema[t]}if(r.startsWith("$session.")){let t=r.slice(9);return e.session?e.session[t]:void 0}if(r==="$cwd")return e.watch.workspace;if(r==="$project")return e.watch.project}function ee(r,e,t){if(r!==void 0){if(typeof r=="string"){let n=Nr(r,t);return n!==void 0?n:mt(e,r)}if(r.coalesce&&Array.isArray(r.coalesce))for(let n of r.coalesce){let o=ee(n,e,t);if(!xr(o))return o}if(r.path){let n=Nr(r.path,t);if(n!==void 0)return n;let o=mt(e,r.path);if(!xr(o))return o}if(r.value!==void 0)return r.value;if(r.default!==void 0)return r.default}}function Ur(r,e,t){let n={};if(!r)return n;for(let[o,i]of Object.entries(r))n[o]=ee(i,e,t);return n}function Fr(r,e,t){if(!e)return!0;let n=e.path||t.eventTypePath||"type",o=n?mt(r,n):void 0,i=o==null||o==="";if(e.exists!==void 0&&(e.exists&&i||!e.exists&&!i)||e.equals!==void 0&&o!==e.equals||e.not_equals!==void 0&&o===e.not_equals||e.in&&Array.isArray(e.in)&&!e.in.includes(o)||e.not_in&&Array.isArray(e.not_in)&&e.not_in.includes(o)||e.contains!==void 0&&(typeof o!="string"||!o.includes(e.contains))||e.not_contains!==void 0&&typeof o=="string"&&o.includes(e.not_contains))return!1;if(e.regex)try{if(!new RegExp(e.regex).test(String(o??"")))return!1}catch(s){return a.debug("WORKER","Invalid regex in match rule",{regex:e.regex},s instanceof Error?s:void 0),!1}return!0}var Ue=class{static checkUserPromptPrivacy(e,t,n,o,i,s){let c=e.getUserPrompt(t,n,i);return c===null?(a.warn("HOOK",`${o}: no user_prompts row for prompt #${n} \u2014 ingesting anyway (session-init likely raced worker boot; see #2794/#2795)`,{sessionId:i,contentSessionId:t,promptNumber:n,...s}),{allow:!0,prompt:""}):c.trim()===""?(a.debug("HOOK",`Skipping ${o} - user prompt was entirely private`,{sessionId:i,promptNumber:n,...s}),{allow:!1,reason:"private"}):{allow:!0,prompt:c}}};var Wr=null;function So(){if(!Wr)throw new Error("ingest helpers used before setIngestContext() \u2014 wiring bug");return Wr}async function Hr(r){let{sessionManager:e,dbManager:t,eventBroadcaster:n,ensureGeneratorRunning:o}=So(),i=I(r.platformSource),s=typeof r.cwd=="string"?r.cwd:"",c=s.trim()?J(s).primary:"",u=k.loadFromFile(ue);if(s&&De(s,u.CLAUDE_MEM_EXCLUDED_PROJECTS))return{ok:!0,status:"skipped",reason:"project_excluded"};if(new Set(u.CLAUDE_MEM_SKIP_TOOLS.split(",").map(y=>y.trim()).filter(Boolean)).has(r.toolName))return{ok:!0,status:"skipped",reason:"tool_excluded"};if(new Set(["Edit","Write","Read","NotebookEdit"]).has(r.toolName)&&r.toolInput&&typeof r.toolInput=="object"){let y=r.toolInput,K=y.file_path||y.notebook_path;if(K&&K.includes("session-memory"))return{ok:!0,status:"skipped",reason:"session_memory_meta"}}let S=t.getSessionStore(),g,_;try{g=S.createSDKSession(r.contentSessionId,c,"",void 0,i),_=S.getPromptNumberFromUserPrompts(r.contentSessionId,g)}catch(y){let K=y instanceof Error?y.message:String(y);return a.error("INGEST","Observation session resolution failed",{contentSessionId:r.contentSessionId,toolName:r.toolName},y instanceof Error?y:new Error(K)),{ok:!1,reason:K,status:500}}if(!Ue.checkUserPromptPrivacy(S,r.contentSessionId,_,"observation",g,{tool_name:r.toolName}).allow)return{ok:!0,status:"skipped",reason:"private"};let W=r.toolInput!==void 0?pt(JSON.stringify(r.toolInput)):"{}",ae=r.toolResponse!==void 0?pt(JSON.stringify(r.toolResponse)):"{}";return await e.queueObservation(g,{tool_name:r.toolName,tool_input:W,tool_response:ae,prompt_number:_,cwd:s||(a.error("INGEST","Missing cwd when ingesting observation",{sessionId:g,toolName:r.toolName}),""),agentId:typeof r.agentId=="string"?r.agentId:void 0,agentType:typeof r.agentType=="string"?r.agentType:void 0,toolUseId:typeof r.toolUseId=="string"?r.toolUseId:void 0}),await o?.(g,"observation"),n.broadcastObservationQueued(g),{ok:!0,sessionDbId:g}}var Fe=class{sessions=new Map;async processEntry(e,t,n,o){for(let i of n.events)Fr(e,i.match,n)&&await this.handleEvent(e,t,n,i,o??void 0)}getSessionKey(e,t){return`${e.name}:${t}`}getOrCreateSession(e,t){let n=this.getSessionKey(e,t),o=this.sessions.get(n);return o||(o={sessionId:t,platformSource:I(e.name)},this.sessions.set(n,o)),o}resolveSessionId(e,t,n,o,i){let s={watch:t,schema:n},c=o.fields?.sessionId??(n.sessionIdPath?{path:n.sessionIdPath}:void 0),u=ee(c,e,s);return typeof u=="string"&&u.trim()?u:typeof u=="number"?String(u):i&&i.trim()?i:null}resolveCwd(e,t,n,o,i){let s={watch:t,schema:n,session:i},c=o.fields?.cwd??(n.cwdPath?{path:n.cwdPath}:void 0),u=ee(c,e,s);return typeof u=="string"&&u.trim()?u:t.workspace?t.workspace:i.cwd}resolveProject(e,t,n,o,i){let s={watch:t,schema:n,session:i},c=o.fields?.project??(n.projectPath?{path:n.projectPath}:void 0),u=ee(c,e,s);return typeof u=="string"&&u.trim()?u:t.project?t.project:i.cwd?J(i.cwd).primary:i.project}async handleEvent(e,t,n,o,i){let s=this.resolveSessionId(e,t,n,o,i);if(!s){a.debug("TRANSCRIPT","Skipping event without sessionId",{event:o.name,watch:t.name});return}let c=this.getOrCreateSession(t,s),u=this.resolveCwd(e,t,n,o,c);u&&(c.cwd=u);let d=this.resolveProject(e,t,n,o,c);d&&(c.project=d);let l=Ur(o.fields,e,{watch:t,schema:n,session:c});switch(o.action){case"session_context":this.applySessionContext(c,l);break;case"session_init":await this.handleSessionInit(c,l),t.context?.updateOn?.includes("session_start")&&await this.updateContext(c,t);break;case"user_message":typeof l.message=="string"&&(c.lastUserMessage=l.message),typeof l.prompt=="string"&&(c.lastUserMessage=l.prompt);break;case"assistant_message":typeof l.message=="string"&&(c.lastAssistantMessage=l.message);break;case"tool_use":await this.handleToolUse(c,l);break;case"tool_result":await this.handleToolResult(c,l);break;case"observation":await this.sendObservation(c,l);break;case"file_edit":await this.sendFileEdit(c,l);break;case"session_end":await this.handleSessionEnd(c,t);break;default:break}}applySessionContext(e,t){let n=typeof t.cwd=="string"?t.cwd:void 0,o=typeof t.project=="string"?t.project:void 0;n&&(e.cwd=n),o&&(e.project=o)}async handleSessionInit(e,t){let n=typeof t.prompt=="string"?t.prompt:"",o=e.cwd??process.cwd();n&&(e.lastUserMessage=n),await Ir.execute({sessionId:e.sessionId,cwd:o,prompt:n,platform:e.platformSource})}async handleToolUse(e,t){let n=typeof t.toolId=="string"?t.toolId:void 0,o=typeof t.toolName=="string"?t.toolName:void 0,i=this.maybeParseJson(t.toolInput),s=this.maybeParseJson(t.toolResponse);if(o==="apply_patch"&&typeof i=="string"){let c=this.parseApplyPatchFiles(i);for(let u of c)await this.sendFileEdit(e,{filePath:u,edits:[{type:"apply_patch",patch:i}]})}o&&s!==void 0?await this.sendObservation(e,{toolName:o,toolInput:i,toolResponse:s,toolUseId:n}):o&&n&&(e.pendingTools||(e.pendingTools=new Map),e.pendingTools.set(n,{toolName:o,toolInput:i}))}async handleToolResult(e,t){let n=typeof t.toolId=="string"?t.toolId:void 0,o=typeof t.toolName=="string"?t.toolName:void 0,i=this.maybeParseJson(t.toolResponse),s=this.maybeParseJson(t.toolInput);if(n&&e.pendingTools){let c=e.pendingTools.get(n);c&&(o||(o=c.toolName),s===void 0&&(s=c.toolInput),e.pendingTools.delete(n))}o?await this.sendObservation(e,{toolName:o,toolInput:s,toolResponse:i,toolUseId:n}):a.debug("TRANSCRIPT","Dropping tool_result with no resolvable toolName",{sessionId:e.sessionId,toolId:n})}async sendObservation(e,t){let n=typeof t.toolName=="string"?t.toolName:void 0;if(!n)return;let o=await Hr({contentSessionId:e.sessionId,cwd:e.cwd??process.cwd(),toolName:n,toolInput:this.maybeParseJson(t.toolInput),toolResponse:this.maybeParseJson(t.toolResponse),platformSource:e.platformSource,toolUseId:typeof t.toolUseId=="string"?t.toolUseId:void 0});if(!o.ok)throw new Error(`ingestObservation failed: ${o.reason}`)}async sendFileEdit(e,t){let n=typeof t.filePath=="string"?t.filePath:void 0;n&&await Pr.execute({sessionId:e.sessionId,cwd:e.cwd??process.cwd(),filePath:n,edits:Array.isArray(t.edits)?t.edits:void 0,platform:e.platformSource})}maybeParseJson(e){if(typeof e!="string")return e;let t=e.trim();if(!t||!(t.startsWith("{")||t.startsWith("[")))return e;try{return JSON.parse(t)}catch(n){return a.debug("TRANSCRIPT","Field looked like JSON but did not parse; using raw string",{preview:t.slice(0,120)},n instanceof Error?n:void 0),e}}parseApplyPatchFiles(e){let t=[],n=e.split(`
|
|
`);for(let o of n){let i=o.trim();if(i.startsWith("*** Update File: "))t.push(i.replace("*** Update File: ","").trim());else if(i.startsWith("*** Add File: "))t.push(i.replace("*** Add File: ","").trim());else if(i.startsWith("*** Delete File: "))t.push(i.replace("*** Delete File: ","").trim());else if(i.startsWith("*** Move to: "))t.push(i.replace("*** Move to: ","").trim());else if(i.startsWith("+++ ")){let s=i.replace("+++ ","").replace(/^b\//,"").trim();s&&s!=="/dev/null"&&t.push(s)}}return Array.from(new Set(t))}async handleSessionEnd(e,t){await this.queueSummary(e),await this.updateContext(e,t),e.pendingTools?.clear();let n=this.getSessionKey(t,e.sessionId);this.sessions.delete(n)}async queueSummary(e){if(!await ke())return;let n=e.lastAssistantMessage??"",o=JSON.stringify({contentSessionId:e.sessionId,last_assistant_message:n,platformSource:e.platformSource});try{await U("/api/sessions/summarize",{method:"POST",headers:{"Content-Type":"application/json"},body:o})}catch(i){a.warn("TRANSCRIPT","Summary request failed",{error:i instanceof Error?i.message:String(i)})}}async updateContext(e,t){if(!t.context||t.context.mode!=="agents"||ht(t)||!await ke())return;let o=e.cwd??t.workspace;if(!o)return;let s=J(o).allProjects.join(","),c=`/api/context/inject?projects=${encodeURIComponent(s)}&platformSource=${encodeURIComponent(e.platformSource)}`,u=T(t.context.path??`${o}/AGENTS.md`),d=ie.default.resolve(u),l=[ie.default.resolve(o),ie.default.resolve(m)];if(!l.some(f=>d.startsWith(f+ie.default.sep)||d===f)){a.warn("SECURITY","Rejected path traversal attempt in watch.context.path",{original:t.context.path,resolved:d,allowedRoots:l});return}let g;try{g=await U(c)}catch(f){a.warn("TRANSCRIPT","Failed to fetch AGENTS.md context",{error:f instanceof Error?f.message:String(f)});return}if(!g.ok)return;let _=(await g.text()).trim();_&&(Lr(u,_),a.debug("TRANSCRIPT","Updated AGENTS.md context",{agentsPath:u,watch:t.name}))}};var gt=class{constructor(e,t,n,o){this.filePath=e;this.onLine=n;this.onOffset=o;this.tailState={offset:t,partial:""}}filePath;onLine;onOffset;watcher=null;tailState;start(){this.readNewData().catch(()=>{}),this.watcher=(0,h.watch)(this.filePath,{persistent:!0},()=>{this.readNewData().catch(()=>{})})}close(){this.watcher?.close(),this.watcher=null}poke(){this.readNewData().catch(()=>{})}async readNewData(){if(!(0,h.existsSync)(this.filePath))return;let e=0;try{e=(0,h.statSync)(this.filePath).size}catch(s){a.debug("WORKER","Failed to stat transcript file",{file:this.filePath},s instanceof Error?s:void 0);return}if(e<this.tailState.offset&&(this.tailState.offset=0),e===this.tailState.offset)return;let t=(0,h.createReadStream)(this.filePath,{start:this.tailState.offset,end:e-1,encoding:"utf8"}),n="";for await(let s of t)n+=s;this.tailState.offset=e,this.onOffset(this.tailState.offset);let i=(this.tailState.partial+n).split(`
|
|
`);this.tailState.partial=i.pop()??"";for(let s of i){let c=s.trim();c&&await this.onLine(c)}}},We=class{constructor(e,t){this.config=e;this.statePath=t;this.state=Mt(t)}config;statePath;processor=new Fe;tailers=new Map;state;rootWatchers=[];async start(){for(let e of this.config.watches)await this.setupWatch(e)}stop(){for(let e of this.tailers.values())e.close();this.tailers.clear();for(let e of this.rootWatchers)e.close();this.rootWatchers=[]}async setupWatch(e){let t=this.resolveSchema(e);if(!t){a.warn("TRANSCRIPT","Missing schema for watch",{watch:e.name});return}let n=T(e.path),o=this.resolveWatchFiles(n);for(let s of o)await this.addTailer(s,e,t);let i=this.deepestNonGlobAncestor(n);if(!i||!(0,h.existsSync)(i)){a.debug("TRANSCRIPT","Watch root does not exist, skipping fs.watch",{watch:e.name,watchRoot:i});return}try{let s=(0,h.watch)(i,{recursive:!0,persistent:!0},(c,u)=>{this.handleRootWatchEvent(i,n,e,t,u)});this.rootWatchers.push(s),a.info("TRANSCRIPT","Watching transcript root recursively",{watch:e.name,watchRoot:i})}catch(s){a.warn("TRANSCRIPT","Failed to start recursive fs.watch on transcript root",{watch:e.name,watchRoot:i},s instanceof Error?s:void 0)}}handleRootWatchEvent(e,t,n,o,i){if(!i)return;let s=(0,A.resolve)(e,i).replace(/\\/g,"/"),c=this.tailers.get(s);if(c){c.poke();return}let u=this.resolveWatchFiles(t);for(let d of u)this.tailers.has(d)||this.addTailer(d,n,o)}deepestNonGlobAncestor(e){if(!this.hasGlob(e)){if((0,h.existsSync)(e))try{return(0,h.statSync)(e).isDirectory()?e:(0,A.resolve)(e,"..")}catch(o){return a.debug("TRANSCRIPT","Failed to stat watch path ancestor, falling back to parent directory",{path:e},o instanceof Error?o:new Error(String(o))),(0,A.resolve)(e,"..")}return e}let t=e.split(/[/\\]/),n=[];for(let o of t){if(/[*?[\]{}()]/.test(o))break;n.push(o)}return n.length===0||n.length===1&&n[0]===""?"":n.join(A.sep)}resolveSchema(e){return typeof e.schema=="string"?this.config.schemas?.[e.schema]??null:e.schema}resolveWatchFiles(e){if(this.hasGlob(e))return this.scanGlob(this.normalizeGlobPattern(e));if((0,h.existsSync)(e))try{if((0,h.statSync)(e).isDirectory()){let n=(0,A.join)(e,"**","*.jsonl");return this.scanGlob(this.normalizeGlobPattern(n))}return[e]}catch(t){return a.debug("WORKER","Failed to stat watch path",{path:e},t instanceof Error?t:void 0),[]}return[]}scanGlob(e){return Array.from(new Bun.Glob(e).scanSync({absolute:!0,onlyFiles:!0}))}normalizeGlobPattern(e){return e.replace(/\\/g,"/")}hasGlob(e){return/[*?[\]{}()]/.test(e)}async addTailer(e,t,n){if(this.tailers.has(e))return;let o=this.extractSessionIdFromPath(e),i=this.state.offsets[e]??0;if(i===0&&t.startAtEnd)try{i=(0,h.statSync)(e).size}catch(c){a.debug("WORKER","Failed to stat file for startAtEnd offset",{file:e},c instanceof Error?c:void 0),i=0}let s=new gt(e,i,async c=>{await this.handleLine(c,t,n,e,o)},c=>{this.state.offsets[e]=c,vt(this.statePath,this.state)});s.start(),this.tailers.set(e,s),a.info("TRANSCRIPT","Watching transcript file",{file:e,watch:t.name,schema:n.name})}async handleLine(e,t,n,o,i){try{let s=JSON.parse(e);await this.processor.processEntry(s,t,n,i??void 0)}catch(s){s instanceof Error?a.debug("TRANSCRIPT","Failed to parse transcript line",{watch:t.name,file:(0,A.basename)(o)},s):a.warn("TRANSCRIPT","Failed to parse transcript line (non-Error thrown)",{watch:t.name,file:(0,A.basename)(o),error:String(s)})}}extractSessionIdFromPath(e){let t=e.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);return t?t[0]:null}};function Et(r,e){let t=r.indexOf(e);return t===-1?null:r[t+1]??null}async function $r(r,e){switch(r){case"init":{let t=Et(e,"--config")??q;return de(t),console.log(`Created sample config: ${T(t)}`),0}case"watch":{let t=Et(e,"--config")??q,n;try{n=ne(t)}catch(c){if(c instanceof Error&&c.message.includes("not found"))de(t),console.log(`Created sample config: ${T(t)}`),n=ne(t);else throw c}let o=T(n.stateFile??le),i=new We(n,o);await i.start(),console.log("Transcript watcher running. Press Ctrl+C to stop.");let s=()=>{i.stop(),process.exit(0)};return process.on("SIGINT",s),process.on("SIGTERM",s),await new Promise(()=>{})}case"validate":{let t=Et(e,"--config")??q;try{ne(t)}catch(n){if(n instanceof Error&&n.message.includes("not found"))de(t),console.log(`Created sample config: ${T(t)}`),ne(t);else throw n}return console.log(`Config OK: ${T(t)}`),0}default:return console.log("Usage: claude-mem transcript <init|watch|validate> [--config <path>]"),1}}var _o=process.argv[2],ho=process.argv.slice(3);$r(_o,ho).then(r=>{process.exit(r)}).catch(r=>{console.error(r),process.exit(1)});
|