keepmind 1.0.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.
Files changed (105) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.codex-plugin/plugin.json +46 -0
  3. package/LICENSE +202 -0
  4. package/README.md +139 -0
  5. package/dist/npx-cli/index.js +1398 -0
  6. package/dist/opencode-plugin/index.js +68 -0
  7. package/openclaw/Dockerfile.e2e +46 -0
  8. package/openclaw/SKILL.md +462 -0
  9. package/openclaw/TESTING.md +279 -0
  10. package/openclaw/dist/index.js +20 -0
  11. package/openclaw/e2e-verify.sh +222 -0
  12. package/openclaw/install.sh +1653 -0
  13. package/openclaw/openclaw.plugin.json +98 -0
  14. package/openclaw/package.json +21 -0
  15. package/openclaw/skills/do/SKILL.md +1 -0
  16. package/openclaw/skills/make-plan/SKILL.md +1 -0
  17. package/openclaw/src/index.test.ts +1178 -0
  18. package/openclaw/src/index.ts +1136 -0
  19. package/openclaw/test-e2e.sh +40 -0
  20. package/openclaw/test-install.sh +2086 -0
  21. package/openclaw/test-sse-consumer.js +98 -0
  22. package/openclaw/tsconfig.json +26 -0
  23. package/package.json +187 -0
  24. package/plugin/.claude-plugin/plugin.json +24 -0
  25. package/plugin/.codex-plugin/plugin.json +46 -0
  26. package/plugin/.mcp.json +12 -0
  27. package/plugin/bun.lock +325 -0
  28. package/plugin/hooks/bugfixes-2026-01-10.md +92 -0
  29. package/plugin/hooks/codex-hooks.json +63 -0
  30. package/plugin/hooks/hooks.json +117 -0
  31. package/plugin/modes/code--ar.json +24 -0
  32. package/plugin/modes/code--bn.json +24 -0
  33. package/plugin/modes/code--chill.json +8 -0
  34. package/plugin/modes/code--cs.json +24 -0
  35. package/plugin/modes/code--da.json +24 -0
  36. package/plugin/modes/code--de.json +24 -0
  37. package/plugin/modes/code--el.json +24 -0
  38. package/plugin/modes/code--es.json +24 -0
  39. package/plugin/modes/code--fi.json +24 -0
  40. package/plugin/modes/code--fr.json +24 -0
  41. package/plugin/modes/code--he.json +24 -0
  42. package/plugin/modes/code--hi.json +24 -0
  43. package/plugin/modes/code--hu.json +24 -0
  44. package/plugin/modes/code--id.json +24 -0
  45. package/plugin/modes/code--it.json +24 -0
  46. package/plugin/modes/code--ja.json +24 -0
  47. package/plugin/modes/code--ko.json +24 -0
  48. package/plugin/modes/code--nl.json +24 -0
  49. package/plugin/modes/code--no.json +24 -0
  50. package/plugin/modes/code--pl.json +24 -0
  51. package/plugin/modes/code--pt-br.json +24 -0
  52. package/plugin/modes/code--ro.json +24 -0
  53. package/plugin/modes/code--ru.json +24 -0
  54. package/plugin/modes/code--sv.json +24 -0
  55. package/plugin/modes/code--th.json +24 -0
  56. package/plugin/modes/code--tr.json +24 -0
  57. package/plugin/modes/code--uk.json +24 -0
  58. package/plugin/modes/code--ur.json +25 -0
  59. package/plugin/modes/code--vi.json +24 -0
  60. package/plugin/modes/code--zh.json +24 -0
  61. package/plugin/modes/code.json +139 -0
  62. package/plugin/modes/email-investigation.json +120 -0
  63. package/plugin/modes/law-study--chill.json +7 -0
  64. package/plugin/modes/law-study-CLAUDE.md +85 -0
  65. package/plugin/modes/law-study.json +120 -0
  66. package/plugin/modes/meme-tokens.json +125 -0
  67. package/plugin/package.json +47 -0
  68. package/plugin/scripts/bun-runner.js +229 -0
  69. package/plugin/scripts/context-generator.cjs +1005 -0
  70. package/plugin/scripts/mcp-server.cjs +247 -0
  71. package/plugin/scripts/statusline-counts.js +45 -0
  72. package/plugin/scripts/transcript-watcher.cjs +27 -0
  73. package/plugin/scripts/version-check.js +193 -0
  74. package/plugin/scripts/worker-cli.js +19 -0
  75. package/plugin/scripts/worker-service.cjs +2638 -0
  76. package/plugin/scripts/worker-wrapper.cjs +2 -0
  77. package/plugin/skills/babysit/SKILL.md +87 -0
  78. package/plugin/skills/design-is/SKILL.md +312 -0
  79. package/plugin/skills/do/SKILL.md +45 -0
  80. package/plugin/skills/how-it-works/SKILL.md +22 -0
  81. package/plugin/skills/how-it-works/onboarding-explainer.md +17 -0
  82. package/plugin/skills/knowledge-agent/SKILL.md +80 -0
  83. package/plugin/skills/learn-codebase/SKILL.md +21 -0
  84. package/plugin/skills/make-plan/SKILL.md +67 -0
  85. package/plugin/skills/mem-search/SKILL.md +131 -0
  86. package/plugin/skills/oh-my-issues/SKILL.md +226 -0
  87. package/plugin/skills/pathfinder/SKILL.md +111 -0
  88. package/plugin/skills/smart-explore/SKILL.md +193 -0
  89. package/plugin/skills/standup/SKILL.md +142 -0
  90. package/plugin/skills/standup/agent-brief.md +47 -0
  91. package/plugin/skills/standup/standup.mjs +662 -0
  92. package/plugin/skills/timeline-report/SKILL.md +211 -0
  93. package/plugin/skills/version-bump/SKILL.md +74 -0
  94. package/plugin/skills/version-bump/scripts/generate_changelog.js +34 -0
  95. package/plugin/skills/weekly-digests/SKILL.md +262 -0
  96. package/plugin/skills/what-the/SKILL.md +6 -0
  97. package/plugin/skills/wowerpoint/SKILL.md +205 -0
  98. package/plugin/ui/assets/fonts/monaspace-radon-var.woff +0 -0
  99. package/plugin/ui/assets/fonts/monaspace-radon-var.woff2 +0 -0
  100. package/plugin/ui/icon-thick-completed.svg +8 -0
  101. package/plugin/ui/icon-thick-investigated.svg +8 -0
  102. package/plugin/ui/icon-thick-learned.svg +12 -0
  103. package/plugin/ui/icon-thick-next-steps.svg +8 -0
  104. package/plugin/ui/viewer-bundle.js +65 -0
  105. package/plugin/ui/viewer.html +3302 -0
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'child_process';
3
+ import { existsSync, readFileSync, rmSync } from 'fs';
4
+ import { homedir } from 'os';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const IS_WINDOWS = process.platform === 'win32';
9
+ const VERSION_CHECK_LOG_PREFIX = '[version-check]';
10
+ const BUN_INSTALL_ARGS = Object.freeze(['install', '--production']);
11
+ const BUN_INSTALL_TIMEOUT_MS = 120_000;
12
+ const NODE_MODULES_DIRNAME = 'node_modules';
13
+
14
+ function findBun() {
15
+ const pathCheck = IS_WINDOWS
16
+ ? spawnSync('where bun', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], shell: true })
17
+ : spawnSync('which', ['bun'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
18
+
19
+ if (pathCheck.status === 0 && pathCheck.stdout.trim()) {
20
+ if (IS_WINDOWS) {
21
+ const bunCmdPath = pathCheck.stdout.split('\n').find((line) => line.trim().endsWith('bun.cmd'));
22
+ if (bunCmdPath) return bunCmdPath.trim();
23
+ }
24
+ return 'bun';
25
+ }
26
+
27
+ const bunPaths = IS_WINDOWS
28
+ ? [join(homedir(), '.bun', 'bin', 'bun.exe')]
29
+ : [
30
+ join(homedir(), '.bun', 'bin', 'bun'),
31
+ '/usr/local/bin/bun',
32
+ '/opt/homebrew/bin/bun',
33
+ '/home/linuxbrew/.linuxbrew/bin/bun',
34
+ ];
35
+
36
+ for (const bunPath of bunPaths) {
37
+ if (existsSync(bunPath)) return bunPath;
38
+ }
39
+
40
+ return null;
41
+ }
42
+
43
+ // Setup-phase auto-install of plugin runtime dependencies.
44
+ //
45
+ // The plugin marketplace extracts files into ~/.claude/plugins/cache/...
46
+ // but does not run `bun install`. On fresh installs the worker crashes
47
+ // with `Cannot find module 'zod/v3'` on the very first hook invocation
48
+ // (gh #2640, #2637). The previous defense-in-depth fix (gh #2644) ran
49
+ // the install on the SessionStart / UserPromptSubmit hot path; review
50
+ // (gh #2649 — YOMXXX) flagged that as the wrong architectural home
51
+ // because it makes proxy / offline / OOM failures land on the user's
52
+ // first prompt instead of at install time.
53
+ //
54
+ // Running it here at Setup keeps the install off the hot path: Setup
55
+ // has a 300s timeout (vs 60s for SessionStart), runs once per Claude
56
+ // Code launch, and is the only standalone hook script — the natural
57
+ // place to materialise plugin runtime state.
58
+ function ensurePluginDependencies(pluginRoot) {
59
+ if (!existsSync(join(pluginRoot, 'package.json'))) return;
60
+
61
+ // Guard on node_modules (package-manager marker) rather than a specific
62
+ // package, so the check stays correct if dependencies are later renamed.
63
+ if (existsSync(join(pluginRoot, NODE_MODULES_DIRNAME))) return;
64
+
65
+ const bunPath = findBun();
66
+ if (!bunPath) {
67
+ console.error(`${VERSION_CHECK_LOG_PREFIX} bun not found on PATH; cannot auto-install plugin dependencies`);
68
+ return;
69
+ }
70
+
71
+ // Progress diagnostic so users understand the (one-time) Setup hang.
72
+ console.error(`${VERSION_CHECK_LOG_PREFIX} installing plugin dependencies (first run, one-time)...`);
73
+
74
+ let result;
75
+ try {
76
+ result = spawnSync(bunPath, BUN_INSTALL_ARGS, {
77
+ cwd: pluginRoot,
78
+ encoding: 'utf-8',
79
+ stdio: ['pipe', 'pipe', 'pipe'],
80
+ timeout: BUN_INSTALL_TIMEOUT_MS,
81
+ windowsHide: true,
82
+ });
83
+ } catch (err) {
84
+ const reason = err && err.message ? err.message : String(err);
85
+ console.error(`${VERSION_CHECK_LOG_PREFIX} bun install threw (${reason}); worker may crash with missing module errors`);
86
+ return;
87
+ }
88
+
89
+ // spawnSync does NOT throw on a failed child. Three distinct failure
90
+ // modes must be surfaced explicitly:
91
+ // 1. result.error set (ENOENT / ETIMEDOUT / ...)
92
+ // 2. non-zero exit code
93
+ // 3. signal-killed (OOM SIGKILL, SIGTERM, ...) where result.status is
94
+ // null AND result.error is undefined — only result.signal is set.
95
+ const killedBySignal = result.status === null && !!result.signal;
96
+ const nonZeroExit = result.status !== null && result.status !== 0;
97
+ if (result.error || nonZeroExit || killedBySignal) {
98
+ let reason;
99
+ if (result.error) {
100
+ reason = result.error.message;
101
+ } else if (killedBySignal) {
102
+ reason = `killed by ${result.signal}`;
103
+ } else {
104
+ reason = `exit ${result.status}`;
105
+ }
106
+ console.error(`${VERSION_CHECK_LOG_PREFIX} bun install failed (${reason}); worker may crash with missing module errors`);
107
+ // `bun install` often creates `node_modules/` BEFORE the failure point
108
+ // (network timeout mid-fetch, OOM kill, registry 5xx after partial
109
+ // resolution). The existence guard above would then permanently skip
110
+ // retry on every subsequent Setup run, leaving the plugin broken with
111
+ // no recovery path short of manual `rm -rf node_modules`. Remove the
112
+ // partial dir so the next Setup invocation can retry automatically
113
+ // (gh #2650 review).
114
+ try {
115
+ rmSync(join(pluginRoot, NODE_MODULES_DIRNAME), { recursive: true, force: true });
116
+ } catch (rmErr) {
117
+ const rmReason = rmErr && rmErr.message ? rmErr.message : String(rmErr);
118
+ console.error(`${VERSION_CHECK_LOG_PREFIX} failed to clean up partial node_modules (${rmReason}); next Setup run may skip retry`);
119
+ }
120
+ } else {
121
+ // Close the diagnostic loop: a Setup hook that can block for up to
122
+ // 120s needs an explicit completion line so users can distinguish a
123
+ // hung install from one that finished silently (gh #2650 review).
124
+ console.error(`${VERSION_CHECK_LOG_PREFIX} plugin dependencies installed successfully`);
125
+ }
126
+ }
127
+
128
+ function resolveRoot() {
129
+ if (process.env.CLAUDE_PLUGIN_ROOT) {
130
+ const root = process.env.CLAUDE_PLUGIN_ROOT;
131
+ if (existsSync(join(root, 'package.json'))) return root;
132
+ }
133
+ try {
134
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
135
+ const candidate = dirname(scriptDir);
136
+ if (existsSync(join(candidate, 'package.json'))) return candidate;
137
+ } catch {}
138
+ return null;
139
+ }
140
+
141
+ const ROOT = resolveRoot();
142
+ if (!ROOT) process.exit(0);
143
+
144
+ ensurePluginDependencies(ROOT);
145
+
146
+ function emitUpgradeHint(message) {
147
+ if (process.env.CLAUDE_MEM_CODEX_HOOK === '1') {
148
+ console.log(JSON.stringify({
149
+ hookSpecificOutput: {
150
+ hookEventName: 'SessionStart',
151
+ additionalContext: message,
152
+ },
153
+ }));
154
+ } else {
155
+ console.error(message);
156
+ }
157
+ }
158
+
159
+ const LEGACY_VERSION_MARKER_RE =
160
+ /^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
161
+
162
+ function readInstallMarkerVersion(markerPath) {
163
+ const content = readFileSync(markerPath, 'utf-8');
164
+ try {
165
+ const marker = JSON.parse(content);
166
+ return marker && typeof marker === 'object' && typeof marker.version === 'string'
167
+ ? marker.version
168
+ : null;
169
+ } catch {
170
+ const legacyVersion = content.trim();
171
+ return LEGACY_VERSION_MARKER_RE.test(legacyVersion)
172
+ ? legacyVersion.replace(/^v/i, '')
173
+ : null;
174
+ }
175
+ }
176
+
177
+ try {
178
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
179
+ const markerPath = join(ROOT, '.install-version');
180
+ if (!existsSync(markerPath)) {
181
+ emitUpgradeHint('keepmind: runtime not yet set up - run: npx keepmind@latest install');
182
+ process.exit(0);
183
+ }
184
+ const markerVersion = readInstallMarkerVersion(markerPath);
185
+ if (!markerVersion) {
186
+ emitUpgradeHint('keepmind: install marker unreadable - run: npx keepmind@latest install');
187
+ } else if (markerVersion !== pkg.version) {
188
+ emitUpgradeHint(`keepmind: upgraded to v${pkg.version} - run: npx keepmind@latest install`);
189
+ }
190
+ } catch {
191
+ emitUpgradeHint('keepmind: install marker unreadable - run: npx keepmind@latest install');
192
+ }
193
+ 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","thedotmack"),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","thedotmack"),_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)});