@bjlee2024/claude-mem 13.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +20 -0
- package/.codex-plugin/plugin.json +46 -0
- package/LICENSE +202 -0
- package/README.md +419 -0
- package/dist/npx-cli/index.js +10001 -0
- package/dist/opencode-plugin/index.js +67 -0
- package/openclaw/Dockerfile.e2e +46 -0
- package/openclaw/SKILL.md +462 -0
- package/openclaw/TESTING.md +279 -0
- package/openclaw/dist/index.js +15 -0
- package/openclaw/e2e-verify.sh +222 -0
- package/openclaw/install.sh +1653 -0
- package/openclaw/openclaw.plugin.json +98 -0
- package/openclaw/package.json +21 -0
- package/openclaw/src/index.test.ts +1124 -0
- package/openclaw/src/index.ts +1092 -0
- package/openclaw/test-e2e.sh +40 -0
- package/openclaw/test-install.sh +2086 -0
- package/openclaw/test-sse-consumer.js +98 -0
- package/openclaw/tsconfig.json +26 -0
- package/package.json +211 -0
- package/plugin/.claude-plugin/plugin.json +24 -0
- package/plugin/.codex-plugin/plugin.json +46 -0
- package/plugin/.mcp.json +12 -0
- package/plugin/hooks/bugfixes-2026-01-10.md +92 -0
- package/plugin/hooks/codex-hooks.json +74 -0
- package/plugin/hooks/hooks.json +87 -0
- package/plugin/modes/code--ar.json +24 -0
- package/plugin/modes/code--bn.json +24 -0
- package/plugin/modes/code--chill.json +8 -0
- package/plugin/modes/code--cs.json +24 -0
- package/plugin/modes/code--da.json +24 -0
- package/plugin/modes/code--de.json +24 -0
- package/plugin/modes/code--el.json +24 -0
- package/plugin/modes/code--es.json +24 -0
- package/plugin/modes/code--fi.json +24 -0
- package/plugin/modes/code--fr.json +24 -0
- package/plugin/modes/code--he.json +24 -0
- package/plugin/modes/code--hi.json +24 -0
- package/plugin/modes/code--hu.json +24 -0
- package/plugin/modes/code--id.json +24 -0
- package/plugin/modes/code--it.json +24 -0
- package/plugin/modes/code--ja.json +24 -0
- package/plugin/modes/code--ko.json +24 -0
- package/plugin/modes/code--nl.json +24 -0
- package/plugin/modes/code--no.json +24 -0
- package/plugin/modes/code--pl.json +24 -0
- package/plugin/modes/code--pt-br.json +24 -0
- package/plugin/modes/code--ro.json +24 -0
- package/plugin/modes/code--ru.json +24 -0
- package/plugin/modes/code--sv.json +24 -0
- package/plugin/modes/code--th.json +24 -0
- package/plugin/modes/code--tr.json +24 -0
- package/plugin/modes/code--uk.json +24 -0
- package/plugin/modes/code--ur.json +25 -0
- package/plugin/modes/code--vi.json +24 -0
- package/plugin/modes/code--zh.json +24 -0
- package/plugin/modes/code.json +139 -0
- package/plugin/modes/email-investigation.json +120 -0
- package/plugin/modes/law-study--chill.json +7 -0
- package/plugin/modes/law-study-CLAUDE.md +85 -0
- package/plugin/modes/law-study.json +120 -0
- package/plugin/modes/meme-tokens.json +125 -0
- package/plugin/package.json +46 -0
- package/plugin/scripts/bun-runner.js +216 -0
- package/plugin/scripts/context-generator.cjs +795 -0
- package/plugin/scripts/mcp-server.cjs +239 -0
- package/plugin/scripts/server-beta-service.cjs +9856 -0
- package/plugin/scripts/statusline-counts.js +40 -0
- package/plugin/scripts/version-check.js +69 -0
- package/plugin/scripts/worker-cli.js +19 -0
- package/plugin/scripts/worker-service.cjs +2368 -0
- package/plugin/scripts/worker-wrapper.cjs +2 -0
- package/plugin/skills/babysit/SKILL.md +87 -0
- package/plugin/skills/design-is/SKILL.md +312 -0
- package/plugin/skills/do/SKILL.md +45 -0
- package/plugin/skills/how-it-works/SKILL.md +22 -0
- package/plugin/skills/how-it-works/onboarding-explainer.md +17 -0
- package/plugin/skills/knowledge-agent/SKILL.md +80 -0
- package/plugin/skills/learn-codebase/SKILL.md +21 -0
- package/plugin/skills/make-plan/SKILL.md +67 -0
- package/plugin/skills/mem-search/SKILL.md +131 -0
- package/plugin/skills/oh-my-issues/SKILL.md +226 -0
- package/plugin/skills/pathfinder/SKILL.md +111 -0
- package/plugin/skills/smart-explore/SKILL.md +190 -0
- package/plugin/skills/timeline-report/SKILL.md +211 -0
- package/plugin/skills/version-bump/SKILL.md +68 -0
- package/plugin/skills/version-bump/scripts/generate_changelog.js +34 -0
- package/plugin/skills/weekly-digests/SKILL.md +262 -0
- package/plugin/skills/wowerpoint/SKILL.md +205 -0
- package/plugin/ui/assets/fonts/monaspace-radon-var.woff +0 -0
- package/plugin/ui/assets/fonts/monaspace-radon-var.woff2 +0 -0
- package/plugin/ui/claude-mem-logo-for-dark-mode.webp +0 -0
- package/plugin/ui/claude-mem-logo-stylized.png +0 -0
- package/plugin/ui/claude-mem-logomark.webp +0 -0
- package/plugin/ui/icon-thick-completed.svg +8 -0
- package/plugin/ui/icon-thick-investigated.svg +8 -0
- package/plugin/ui/icon-thick-learned.svg +12 -0
- package/plugin/ui/icon-thick-next-steps.svg +8 -0
- package/plugin/ui/viewer-bundle.js +65 -0
- package/plugin/ui/viewer.html +3145 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Database } from "bun:sqlite";
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join, basename } from "path";
|
|
6
|
+
|
|
7
|
+
const cwd = process.argv[2] || process.env.CLAUDE_CWD || process.cwd();
|
|
8
|
+
const project = basename(cwd);
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
let dataDir = process.env.CLAUDE_MEM_DATA_DIR || join(homedir(), ".claude-mem");
|
|
12
|
+
if (!process.env.CLAUDE_MEM_DATA_DIR) {
|
|
13
|
+
const settingsPath = join(dataDir, "settings.json");
|
|
14
|
+
if (existsSync(settingsPath)) {
|
|
15
|
+
try {
|
|
16
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
17
|
+
if (settings.CLAUDE_MEM_DATA_DIR) dataDir = settings.CLAUDE_MEM_DATA_DIR;
|
|
18
|
+
} catch { /* use default */ }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const dbPath = join(dataDir, "claude-mem.db");
|
|
23
|
+
if (!existsSync(dbPath)) {
|
|
24
|
+
console.log(JSON.stringify({ observations: 0, prompts: 0, project }));
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const db = new Database(dbPath, { readonly: true });
|
|
29
|
+
|
|
30
|
+
const obs = db.query("SELECT COUNT(*) as c FROM observations WHERE project = ?").get(project);
|
|
31
|
+
const prompts = db.query(
|
|
32
|
+
`SELECT COUNT(*) as c FROM user_prompts up
|
|
33
|
+
JOIN sdk_sessions s ON s.content_session_id = up.content_session_id
|
|
34
|
+
WHERE s.project = ?`
|
|
35
|
+
).get(project);
|
|
36
|
+
console.log(JSON.stringify({ observations: obs.c, prompts: prompts.c, project }));
|
|
37
|
+
db.close();
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.log(JSON.stringify({ observations: 0, prompts: 0, project, error: e.message }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
function resolveRoot() {
|
|
7
|
+
if (process.env.CLAUDE_PLUGIN_ROOT) {
|
|
8
|
+
const root = process.env.CLAUDE_PLUGIN_ROOT;
|
|
9
|
+
if (existsSync(join(root, 'package.json'))) return root;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const candidate = dirname(scriptDir);
|
|
14
|
+
if (existsSync(join(candidate, 'package.json'))) return candidate;
|
|
15
|
+
} catch {}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ROOT = resolveRoot();
|
|
20
|
+
if (!ROOT) process.exit(0);
|
|
21
|
+
|
|
22
|
+
function emitUpgradeHint(message) {
|
|
23
|
+
if (process.env.CLAUDE_MEM_CODEX_HOOK === '1') {
|
|
24
|
+
console.log(JSON.stringify({
|
|
25
|
+
hookSpecificOutput: {
|
|
26
|
+
hookEventName: 'SessionStart',
|
|
27
|
+
additionalContext: message,
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
} else {
|
|
31
|
+
console.error(message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const LEGACY_VERSION_MARKER_RE =
|
|
36
|
+
/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
37
|
+
|
|
38
|
+
function readInstallMarkerVersion(markerPath) {
|
|
39
|
+
const content = readFileSync(markerPath, 'utf-8');
|
|
40
|
+
try {
|
|
41
|
+
const marker = JSON.parse(content);
|
|
42
|
+
return marker && typeof marker === 'object' && typeof marker.version === 'string'
|
|
43
|
+
? marker.version
|
|
44
|
+
: null;
|
|
45
|
+
} catch {
|
|
46
|
+
const legacyVersion = content.trim();
|
|
47
|
+
return LEGACY_VERSION_MARKER_RE.test(legacyVersion)
|
|
48
|
+
? legacyVersion.replace(/^v/i, '')
|
|
49
|
+
: null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
|
55
|
+
const markerPath = join(ROOT, '.install-version');
|
|
56
|
+
if (!existsSync(markerPath)) {
|
|
57
|
+
emitUpgradeHint('claude-mem: runtime not yet set up - run: npx claude-mem@latest install');
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
const markerVersion = readInstallMarkerVersion(markerPath);
|
|
61
|
+
if (!markerVersion) {
|
|
62
|
+
emitUpgradeHint('claude-mem: install marker unreadable - run: npx claude-mem@latest install');
|
|
63
|
+
} else if (markerVersion !== pkg.version) {
|
|
64
|
+
emitUpgradeHint(`claude-mem: upgraded to v${pkg.version} - run: npx claude-mem@latest install`);
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
emitUpgradeHint('claude-mem: install marker unreadable - run: npx claude-mem@latest install');
|
|
68
|
+
}
|
|
69
|
+
process.exit(0);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import{existsSync as w,readFileSync as rt,writeFileSync as nt,unlinkSync as st,mkdirSync as $}from"fs";import{createWriteStream as ot}from"fs";import{join as S}from"path";import{spawn as it,spawnSync as at}from"child_process";import{homedir as ct}from"os";import{join as E,dirname as q,basename as Lt}from"path";import{homedir as z}from"os";import{fileURLToPath as Q}from"url";import{readFileSync as V,writeFileSync as j,existsSync as X}from"fs";import{join as Y}from"path";import{homedir as J}from"os";var b="bugfix,feature,refactor,discovery,decision,change",k="how-it-works,why-it-exists,what-changed,problem-solution,gotcha,pattern,trade-off";var D=(s=>(s[s.DEBUG=0]="DEBUG",s[s.INFO=1]="INFO",s[s.WARN=2]="WARN",s[s.ERROR=3]="ERROR",s[s.SILENT=4]="SILENT",s))(D||{}),C=class{level=null;useColor;constructor(){this.useColor=process.stdout.isTTY??!1}getLevel(){if(this.level===null){let t=l.get("CLAUDE_MEM_LOG_LEVEL").toUpperCase();this.level=D[t]??1}return this.level}correlationId(t,e){return`obs-${t}-${e}`}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}
|
|
3
|
+
${t.stack}`:t.message;if(Array.isArray(t))return`[${t.length} items]`;let e=Object.keys(t);return e.length===0?"{}":e.length<=3?JSON.stringify(t):`{${e.length} keys: ${e.slice(0,3).join(", ")}...}`}return String(t)}formatTool(t,e){if(!e)return t;let r=typeof e=="string"?JSON.parse(e):e;if(t==="Bash"&&r.command)return`${t}(${r.command})`;if(r.file_path)return`${t}(${r.file_path})`;if(r.notebook_path)return`${t}(${r.notebook_path})`;if(t==="Glob"&&r.pattern)return`${t}(${r.pattern})`;if(t==="Grep"&&r.pattern)return`${t}(${r.pattern})`;if(r.url)return`${t}(${r.url})`;if(r.query)return`${t}(${r.query})`;if(t==="Task"){if(r.subagent_type)return`${t}(${r.subagent_type})`;if(r.description)return`${t}(${r.description})`}return t==="Skill"&&r.skill?`${t}(${r.skill})`:t==="LSP"&&r.operation?`${t}(${r.operation})`:t}formatTimestamp(t){let e=t.getFullYear(),r=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0"),s=String(t.getHours()).padStart(2,"0"),o=String(t.getMinutes()).padStart(2,"0"),a=String(t.getSeconds()).padStart(2,"0"),c=String(t.getMilliseconds()).padStart(3,"0");return`${e}-${r}-${n} ${s}:${o}:${a}.${c}`}log(t,e,r,n,s){if(t<this.getLevel())return;let o=this.formatTimestamp(new Date),a=D[t].padEnd(5),c=e.padEnd(6),p="";n?.correlationId?p=`[${n.correlationId}] `:n?.sessionId&&(p=`[session-${n.sessionId}] `);let _="";s!=null&&(this.getLevel()===0&&typeof s=="object"?_=`
|
|
4
|
+
`+JSON.stringify(s,null,2):_=" "+this.formatData(s));let f="";if(n){let{sessionId:h,sdkSessionId:gt,correlationId:_t,...U}=n;Object.keys(U).length>0&&(f=` {${Object.entries(U).map(([K,B])=>`${K}=${B}`).join(", ")}}`)}let m=`[${o}] [${a}] [${c}] ${p}${r}${f}${_}`;t===3?console.error(m):console.log(m)}debug(t,e,r,n){this.log(0,t,e,r,n)}info(t,e,r,n){this.log(1,t,e,r,n)}warn(t,e,r,n){this.log(2,t,e,r,n)}error(t,e,r,n){this.log(3,t,e,r,n)}dataIn(t,e,r,n){this.info(t,`\u2192 ${e}`,r,n)}dataOut(t,e,r,n){this.info(t,`\u2190 ${e}`,r,n)}success(t,e,r,n){this.info(t,`\u2713 ${e}`,r,n)}failure(t,e,r,n){this.error(t,`\u2717 ${e}`,r,n)}timing(t,e,r,n){this.info(t,`\u23F1 ${e}`,n,{duration:`${r}ms`})}happyPathError(t,e,r,n,s=""){let p=((new Error().stack||"").split(`
|
|
5
|
+
`)[2]||"").match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/),_=p?`${p[1].split("/").pop()}:${p[2]}`:"unknown",f={...r,location:_};return this.warn(t,`[HAPPY-PATH] ${e}`,f,n),s}},T=new C;var l=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_PROVIDER:"claude",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:"anthropic/claude-3.5-sonnet",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_OPENROUTER_MAX_CONTEXT_MESSAGES:"20",CLAUDE_MEM_OPENROUTER_MAX_TOKENS:"100000",CLAUDE_MEM_DATA_DIR:Y(J(),".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:"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:b,CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS:k,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 e=this.get(t);return parseInt(e,10)}static getBool(t){return this.get(t)==="true"}static loadFromFile(t){try{if(!X(t))return this.getAllDefaults();let e=V(t,"utf-8"),r=JSON.parse(e),n=r;if(r.env&&typeof r.env=="object"){n=r.env;try{j(t,JSON.stringify(n,null,2),"utf-8"),T.info("SETTINGS","Migrated settings file from nested to flat schema",{settingsPath:t})}catch(o){T.warn("SETTINGS","Failed to auto-migrate settings file",{settingsPath:t},o)}}let s={...this.DEFAULTS};for(let o of Object.keys(this.DEFAULTS))n[o]!==void 0&&(s[o]=n[o]);return s}catch(e){return T.warn("SETTINGS","Failed to load settings, using defaults",{settingsPath:t},e),this.getAllDefaults()}}};function Z(){return typeof __dirname<"u"?__dirname:q(Q(import.meta.url))}var Ut=Z(),u=l.get("CLAUDE_MEM_DATA_DIR"),L=process.env.CLAUDE_CONFIG_DIR||E(z(),".claude"),bt=E(u,"archives"),kt=E(u,"logs"),yt=E(u,"trash"),vt=E(u,"backups"),Nt=E(u,"modes"),$t=E(u,"settings.json"),xt=E(u,"claude-mem.db"),Wt=E(u,"vector-db"),Ft=E(L,"settings.json"),Ht=E(L,"commands"),Gt=E(L,"CLAUDE.md");import{spawnSync as tt}from"child_process";import{existsSync as et}from"fs";import{join as y}from"path";import{homedir as v}from"os";function R(){let i=process.platform==="win32";try{if(tt("bun",["--version"],{encoding:"utf-8",stdio:["pipe","pipe","pipe"],shell:!1}).status===0)return"bun"}catch{}let t=i?[y(v(),".bun","bin","bun.exe")]:[y(v(),".bun","bin","bun"),"/usr/local/bin/bun","/opt/homebrew/bin/bun","/home/linuxbrew/.linuxbrew/bin/bun"];for(let e of t)if(et(e))return e;return null}function N(){return R()!==null}var d=S(u,"worker.pid"),x=S(u,"logs"),P=S(ct(),".claude","plugins","marketplaces","bjlee2024"),g=class{static async start(t){if(isNaN(t)||t<1024||t>65535)return{success:!1,error:`Invalid port ${t}. Must be between 1024 and 65535`};if(await this.isRunning())return{success:!0,pid:this.getPidInfo()?.pid};$(x,{recursive:!0});let e=process.platform==="win32"?"worker-wrapper.cjs":"worker-service.cjs",r=S(P,"plugin","scripts",e);if(!w(r))return{success:!1,error:`Worker script not found at ${r}`};let n=this.getLogFilePath();return this.startWithBun(r,n,t)}static isBunAvailable(){return N()}static escapePowerShellString(t){return t.replace(/'/g,"''")}static async startWithBun(t,e,r){let n=R();if(!n)return{success:!1,error:"Bun is required but not found in PATH or common installation paths. Install from https://bun.sh"};try{if(process.platform==="win32"){let o=this.escapePowerShellString(n),a=this.escapePowerShellString(t),c=this.escapePowerShellString(P),p=this.escapePowerShellString(e),f=`${`$env:CLAUDE_MEM_WORKER_PORT='${r}'`}; Start-Process -FilePath '${o}' -ArgumentList '${a}' -WorkingDirectory '${c}' -WindowStyle Hidden -RedirectStandardOutput '${p}' -RedirectStandardError '${p}.err' -PassThru | Select-Object -ExpandProperty Id`,m=at("powershell",["-Command",f],{stdio:"pipe",timeout:1e4,windowsHide:!0});if(m.status!==0)return{success:!1,error:`PowerShell spawn failed: ${m.stderr?.toString()||"unknown error"}`};let h=parseInt(m.stdout.toString().trim(),10);return isNaN(h)?{success:!1,error:"Failed to get PID from PowerShell"}:(this.writePidFile({pid:h,port:r,startedAt:new Date().toISOString(),version:process.env.npm_package_version||"unknown"}),this.waitForHealth(h,r))}else{let o=it(n,[t],{detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,CLAUDE_MEM_WORKER_PORT:String(r)},cwd:P}),a=ot(e,{flags:"a"});return o.stdout?.pipe(a),o.stderr?.pipe(a),o.unref(),o.pid?(this.writePidFile({pid:o.pid,port:r,startedAt:new Date().toISOString(),version:process.env.npm_package_version||"unknown"}),this.waitForHealth(o.pid,r)):{success:!1,error:"Failed to get PID from spawned process"}}}catch(s){return{success:!1,error:s instanceof Error?s.message:String(s)}}}static async stop(t=5e3){let e=this.getPidInfo();if(process.platform==="win32"){let r=e?.port??this.getPortFromSettings();if(await this.tryHttpShutdown(r))return this.removePidFile(),!0;if(!e)return!0;let{execSync:s}=await import("child_process");try{s(`taskkill /PID ${e.pid} /T /F`,{timeout:1e4,stdio:"ignore"})}catch{}try{await this.waitForExit(e.pid,t)}catch{}return this.isProcessAlive(e.pid)||this.removePidFile(),!0}else{if(!e)return!0;try{process.kill(e.pid,"SIGTERM"),await this.waitForExit(e.pid,t)}catch{try{process.kill(e.pid,"SIGKILL")}catch{}}return this.removePidFile(),!0}}static async restart(t){return await this.stop(),this.start(t)}static async status(){let t=this.getPidInfo();if(!t)return{running:!1};let e=this.isProcessAlive(t.pid);return{running:e,pid:e?t.pid:void 0,port:e?t.port:void 0,uptime:e?this.formatUptime(t.startedAt):void 0}}static async isRunning(){let t=this.getPidInfo();if(!t)return!1;let e=this.isProcessAlive(t.pid);return e||this.removePidFile(),e}static getPortFromSettings(){try{let t=S(u,"settings.json"),e=l.loadFromFile(t);return parseInt(e.CLAUDE_MEM_WORKER_PORT,10)}catch{return parseInt(l.get("CLAUDE_MEM_WORKER_PORT"),10)}}static async tryHttpShutdown(t){try{return(await fetch(`http://127.0.0.1:${t}/api/admin/shutdown`,{method:"POST",signal:AbortSignal.timeout(2e3)})).ok?await this.waitForWorkerDown(t,5e3):!1}catch{return!1}}static async waitForWorkerDown(t,e){let r=Date.now();for(;Date.now()-r<e;)try{await fetch(`http://127.0.0.1:${t}/api/health`,{signal:AbortSignal.timeout(500)}),await new Promise(n=>setTimeout(n,100))}catch{return!0}return!1}static getPidInfo(){try{if(!w(d))return null;let t=rt(d,"utf-8"),e=JSON.parse(t);return typeof e.pid!="number"||typeof e.port!="number"?(logger.warn("PROCESS","Malformed PID file: missing or invalid pid/port fields",{},{parsed:e}),null):e}catch(t){return logger.warn("PROCESS","Failed to read PID file",{},{error:t instanceof Error?t.message:String(t),path:d}),null}}static writePidFile(t){$(u,{recursive:!0}),nt(d,JSON.stringify(t,null,2))}static removePidFile(){try{w(d)&&st(d)}catch{}}static isProcessAlive(t){try{return process.kill(t,0),!0}catch{return!1}}static async waitForHealth(t,e,r=1e4){let n=Date.now(),s=process.platform==="win32",o=s?r*2:r;for(;Date.now()-n<o;){if(!this.isProcessAlive(t))return{success:!1,error:s?`Process died during startup
|
|
6
|
+
|
|
7
|
+
Troubleshooting:
|
|
8
|
+
1. Check Task Manager for zombie 'bun.exe' or 'node.exe' processes
|
|
9
|
+
2. Verify port ${e} is not in use: netstat -ano | findstr ${e}
|
|
10
|
+
3. Check worker logs in ~/.claude-mem/logs/
|
|
11
|
+
4. See GitHub issues: #363, #367, #371, #373
|
|
12
|
+
5. Docs: https://docs.claude-mem.ai/troubleshooting/windows-issues`:"Process died during startup"};try{if((await fetch(`http://127.0.0.1:${e}/api/readiness`,{signal:AbortSignal.timeout(1e3)})).ok)return{success:!0,pid:t}}catch{}await new Promise(c=>setTimeout(c,200))}return{success:!1,error:s?`Worker failed to start on Windows (readiness check timed out after ${o}ms)
|
|
13
|
+
|
|
14
|
+
Troubleshooting:
|
|
15
|
+
1. Check Task Manager for zombie 'bun.exe' or 'node.exe' processes
|
|
16
|
+
2. Verify port ${e} is not in use: netstat -ano | findstr ${e}
|
|
17
|
+
3. Check worker logs in ~/.claude-mem/logs/
|
|
18
|
+
4. See GitHub issues: #363, #367, #371, #373
|
|
19
|
+
5. Docs: https://docs.claude-mem.ai/troubleshooting/windows-issues`:`Readiness check timed out after ${o}ms`}}static async waitForExit(t,e){let r=Date.now();for(;Date.now()-r<e;){if(!this.isProcessAlive(t))return;await new Promise(n=>setTimeout(n,100))}throw new Error("Process did not exit within timeout")}static getLogFilePath(){let t=new Date().toISOString().slice(0,10);return S(x,`worker-${t}.log`)}static formatUptime(t){let e=new Date(t).getTime(),n=Date.now()-e,s=Math.floor(n/1e3),o=Math.floor(s/60),a=Math.floor(o/60),c=Math.floor(a/24);return c>0?`${c}d ${a%24}h`:a>0?`${a}h ${o%60}m`:o>0?`${o}m ${s%60}s`:`${s}s`}};import F from"path";import{homedir as ut}from"os";var I={DEFAULT:12e4,HEALTH_CHECK:1e3,WORKER_STARTUP_WAIT:1e3,WORKER_STARTUP_RETRIES:15,PRE_RESTART_SETTLE_DELAY:2e3,WINDOWS_MULTIPLIER:1.5};function W(i){return process.platform==="win32"?Math.round(i*I.WINDOWS_MULTIPLIER):i}var ge=F.join(ut(),".claude","plugins","marketplaces","bjlee2024"),_e=W(I.HEALTH_CHECK),M=null;function H(){if(M!==null)return M;let i=F.join(l.get("CLAUDE_MEM_DATA_DIR"),"settings.json"),t=l.loadFromFile(i);return M=parseInt(t.CLAUDE_MEM_WORKER_PORT,10),M}import{stdin as lt}from"process";var Et=process.argv[2],G=H(),O='{"continue": true, "suppressOutput": true}',A=lt.isTTY;async function pt(){switch(Et){case"start":{let i=await g.start(G);if(i.success){if(A){console.log(`Worker started (PID: ${i.pid})`);let t=new Date().toISOString().slice(0,10);console.log(`Logs: ~/.claude-mem/logs/worker-${t}.log`)}else console.log(O);process.exit(0)}else console.error(`Failed to start: ${i.error}`),process.exit(1)}case"stop":await g.stop(),console.log(A?"Worker stopped":O),process.exit(0);case"restart":{let i=await g.restart(G);i.success?(console.log(A?`Worker restarted (PID: ${i.pid})`:O),process.exit(0)):(console.error(`Failed to restart: ${i.error}`),process.exit(1))}case"status":{let i=await g.status();A?i.running?(console.log("Worker is running"),console.log(` PID: ${i.pid}`),console.log(` Port: ${i.port}`),console.log(` Uptime: ${i.uptime}`)):console.log("Worker is not running"):console.log(O),process.exit(0)}default:console.log("Usage: worker-cli.js <start|stop|restart|status>"),process.exit(1)}}pt().catch(i=>{console.error(i),process.exit(1)});
|