claude-mem 13.5.4 → 13.5.7

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.
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Claude-Mem SDK - TypeScript Declarations
3
+ *
4
+ * Standalone module for external consumers to parse claude-mem observation XML
5
+ * and build prompts for the memory worker.
6
+ */
7
+
8
+ export interface ParsedObservation {
9
+ type: string;
10
+ title: string | null;
11
+ subtitle: string | null;
12
+ facts: string[];
13
+ narrative: string | null;
14
+ concepts: string[];
15
+ files_read: string[];
16
+ files_modified: string[];
17
+ }
18
+
19
+ export interface ParsedSummary {
20
+ request: string | null;
21
+ investigated: string | null;
22
+ learned: string | null;
23
+ completed: string | null;
24
+ next_steps: string | null;
25
+ notes: string | null;
26
+ }
27
+
28
+ export interface Observation {
29
+ id: number;
30
+ tool_name: string;
31
+ tool_input: string;
32
+ tool_output: string;
33
+ created_at_epoch: number;
34
+ cwd?: string;
35
+ }
36
+
37
+ export interface ParseObservationsOptions {
38
+ /** Array of valid observation types. If provided, validates types against this list. */
39
+ validTypes?: string[];
40
+ /** Type to use if type is missing or invalid. Defaults to 'observation'. */
41
+ fallbackType?: string;
42
+ }
43
+
44
+ /**
45
+ * Parse observation XML blocks from text
46
+ * Returns all observations found in the text
47
+ *
48
+ * @param text - The text containing observation XML blocks
49
+ * @param options - Optional configuration for type validation
50
+ * @returns Array of parsed observations
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const text = `<observation>
55
+ * <type>code_change</type>
56
+ * <title>Added login feature</title>
57
+ * <facts><fact>New auth module</fact></facts>
58
+ * </observation>`;
59
+ *
60
+ * const observations = parseObservations(text);
61
+ * // => [{ type: 'code_change', title: 'Added login feature', ... }]
62
+ * ```
63
+ */
64
+ export function parseObservations(
65
+ text: string,
66
+ options?: ParseObservationsOptions
67
+ ): ParsedObservation[];
68
+
69
+ /**
70
+ * Parse summary XML block from text
71
+ * Returns null if no valid summary found or if summary was skipped
72
+ *
73
+ * @param text - The text containing summary XML block
74
+ * @returns Parsed summary or null
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const text = `<summary>
79
+ * <request>Implement auth</request>
80
+ * <completed>Added JWT tokens</completed>
81
+ * </summary>`;
82
+ *
83
+ * const summary = parseSummary(text);
84
+ * // => { request: 'Implement auth', completed: 'Added JWT tokens', ... }
85
+ * ```
86
+ */
87
+ export function parseSummary(text: string): ParsedSummary | null;
88
+
89
+ /**
90
+ * Build prompt to send tool observation to SDK agent
91
+ *
92
+ * @param obs - The observation object containing tool data
93
+ * @returns Formatted XML prompt string
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const obs = {
98
+ * id: 1,
99
+ * tool_name: 'Read',
100
+ * tool_input: '{"file_path": "/src/index.ts"}',
101
+ * tool_output: '{"content": "..."}',
102
+ * created_at_epoch: Date.now()
103
+ * };
104
+ *
105
+ * const prompt = buildObservationPrompt(obs);
106
+ * // => '<observed_from_primary_session>...'
107
+ * ```
108
+ */
109
+ export function buildObservationPrompt(obs: Observation): string;
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Claude-Mem SDK - Standalone module for external consumers
3
+ *
4
+ * This is a self-contained module that exports parsing and prompt utilities
5
+ * without internal dependencies on the main claude-mem codebase.
6
+ *
7
+ * Usage:
8
+ * import { parseObservations, buildObservationPrompt } from 'claude-mem/sdk';
9
+ */
10
+
11
+ // ============================================================================
12
+ // Parser Functions
13
+ // ============================================================================
14
+
15
+ /**
16
+ * Parse observation XML blocks from text
17
+ * Returns all observations found in the text
18
+ *
19
+ * @param {string} text - The text containing observation XML blocks
20
+ * @param {Object} [options] - Optional configuration
21
+ * @param {string[]} [options.validTypes] - Array of valid observation types. If provided, validates types.
22
+ * @param {string} [options.fallbackType='observation'] - Type to use if type is missing or invalid
23
+ * @returns {ParsedObservation[]} Array of parsed observations
24
+ */
25
+ export function parseObservations(text, options = {}) {
26
+ const observations = [];
27
+ const { validTypes, fallbackType = 'observation' } = options;
28
+
29
+ // Match <observation>...</observation> blocks (non-greedy)
30
+ const observationRegex = /<observation>([\s\S]*?)<\/observation>/g;
31
+
32
+ let match;
33
+ while ((match = observationRegex.exec(text)) !== null) {
34
+ const obsContent = match[1];
35
+
36
+ // Extract all fields
37
+ const type = extractField(obsContent, 'type');
38
+ const title = extractField(obsContent, 'title');
39
+ const subtitle = extractField(obsContent, 'subtitle');
40
+ const narrative = extractField(obsContent, 'narrative');
41
+ const facts = extractArrayElements(obsContent, 'facts', 'fact');
42
+ const concepts = extractArrayElements(obsContent, 'concepts', 'concept');
43
+ const files_read = extractArrayElements(obsContent, 'files_read', 'file');
44
+ const files_modified = extractArrayElements(obsContent, 'files_modified', 'file');
45
+
46
+ // Determine final type
47
+ let finalType = fallbackType;
48
+ if (type) {
49
+ const trimmedType = type.trim();
50
+ if (validTypes) {
51
+ finalType = validTypes.includes(trimmedType) ? trimmedType : fallbackType;
52
+ } else {
53
+ finalType = trimmedType;
54
+ }
55
+ }
56
+
57
+ // Filter out type from concepts array (types and concepts are separate dimensions)
58
+ const cleanedConcepts = concepts.filter(c => c !== finalType);
59
+
60
+ observations.push({
61
+ type: finalType,
62
+ title,
63
+ subtitle,
64
+ facts,
65
+ narrative,
66
+ concepts: cleanedConcepts,
67
+ files_read,
68
+ files_modified
69
+ });
70
+ }
71
+
72
+ return observations;
73
+ }
74
+
75
+ /**
76
+ * Parse summary XML block from text
77
+ * Returns null if no valid summary found or if summary was skipped
78
+ *
79
+ * @param {string} text - The text containing summary XML block
80
+ * @returns {ParsedSummary|null} Parsed summary or null
81
+ */
82
+ export function parseSummary(text) {
83
+ // Check for skip_summary first
84
+ const skipRegex = /<skip_summary\s+reason="([^"]+)"\s*\/>/;
85
+ const skipMatch = skipRegex.exec(text);
86
+
87
+ if (skipMatch) {
88
+ return null;
89
+ }
90
+
91
+ // Match <summary>...</summary> block (non-greedy)
92
+ const summaryRegex = /<summary>([\s\S]*?)<\/summary>/;
93
+ const summaryMatch = summaryRegex.exec(text);
94
+
95
+ if (!summaryMatch) {
96
+ return null;
97
+ }
98
+
99
+ const summaryContent = summaryMatch[1];
100
+
101
+ return {
102
+ request: extractField(summaryContent, 'request'),
103
+ investigated: extractField(summaryContent, 'investigated'),
104
+ learned: extractField(summaryContent, 'learned'),
105
+ completed: extractField(summaryContent, 'completed'),
106
+ next_steps: extractField(summaryContent, 'next_steps'),
107
+ notes: extractField(summaryContent, 'notes')
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Extract a simple field value from XML content
113
+ * Returns null for missing or empty/whitespace-only fields
114
+ */
115
+ function extractField(content, fieldName) {
116
+ const regex = new RegExp(`<${fieldName}>([^<]*)</${fieldName}>`);
117
+ const match = regex.exec(content);
118
+ if (!match) return null;
119
+
120
+ const trimmed = match[1].trim();
121
+ return trimmed === '' ? null : trimmed;
122
+ }
123
+
124
+ /**
125
+ * Extract array of elements from XML content
126
+ */
127
+ function extractArrayElements(content, arrayName, elementName) {
128
+ const elements = [];
129
+
130
+ // Match the array block
131
+ const arrayRegex = new RegExp(`<${arrayName}>(.*?)</${arrayName}>`, 's');
132
+ const arrayMatch = arrayRegex.exec(content);
133
+
134
+ if (!arrayMatch) {
135
+ return elements;
136
+ }
137
+
138
+ const arrayContent = arrayMatch[1];
139
+
140
+ // Extract individual elements
141
+ const elementRegex = new RegExp(`<${elementName}>([^<]+)</${elementName}>`, 'g');
142
+ let elementMatch;
143
+ while ((elementMatch = elementRegex.exec(arrayContent)) !== null) {
144
+ elements.push(elementMatch[1].trim());
145
+ }
146
+
147
+ return elements;
148
+ }
149
+
150
+ // ============================================================================
151
+ // Prompt Building Functions
152
+ // ============================================================================
153
+
154
+ /**
155
+ * Build prompt to send tool observation to SDK agent
156
+ *
157
+ * @param {Observation} obs - The observation object containing tool data
158
+ * @returns {string} Formatted XML prompt string
159
+ */
160
+ export function buildObservationPrompt(obs) {
161
+ // Safely parse tool_input and tool_output - they may be JSON strings
162
+ let toolInput;
163
+ let toolOutput;
164
+
165
+ try {
166
+ toolInput = typeof obs.tool_input === 'string' ? JSON.parse(obs.tool_input) : obs.tool_input;
167
+ } catch {
168
+ toolInput = obs.tool_input;
169
+ }
170
+
171
+ try {
172
+ toolOutput = typeof obs.tool_output === 'string' ? JSON.parse(obs.tool_output) : obs.tool_output;
173
+ } catch {
174
+ toolOutput = obs.tool_output;
175
+ }
176
+
177
+ return `<observed_from_primary_session>
178
+ <what_happened>${obs.tool_name}</what_happened>
179
+ <occurred_at>${new Date(obs.created_at_epoch).toISOString()}</occurred_at>${obs.cwd ? `\n <working_directory>${obs.cwd}</working_directory>` : ''}
180
+ <parameters>${JSON.stringify(toolInput, null, 2)}</parameters>
181
+ <outcome>${JSON.stringify(toolOutput, null, 2)}</outcome>
182
+ </observed_from_primary_session>`;
183
+ }
@@ -3,7 +3,7 @@
3
3
  "name": "Claude-Mem (Persistent Memory)",
4
4
  "description": "OpenClaw plugin for Claude-Mem. Records observations from embedded runner sessions and streams them to messaging channels.",
5
5
  "kind": "memory",
6
- "version": "13.5.4",
6
+ "version": "13.5.7",
7
7
  "license": "Apache-2.0",
8
8
  "author": "thedotmack",
9
9
  "homepage": "https://claude-mem.ai",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "13.5.4",
3
+ "version": "13.5.7",
4
4
  "description": "Memory compression system for Claude Code - persist context across sessions",
5
5
  "keywords": [
6
6
  "claude",
@@ -64,7 +64,7 @@
64
64
  "scripts": {
65
65
  "dev": "npm run build-and-sync",
66
66
  "build": "node scripts/sync-plugin-manifests.js && node scripts/build-hooks.js && node scripts/gen-plugin-lockfile.cjs",
67
- "build-and-sync": "npm run build && npm run sync-marketplace && sleep 1 && (cd ~/.claude/plugins/marketplaces/thedotmack && npm run worker:restart)",
67
+ "build-and-sync": "npm run build && npm run sync-marketplace && (cd ~/.claude/plugins/marketplaces/thedotmack && npm run worker:restart)",
68
68
  "sync-marketplace": "node scripts/sync-marketplace.cjs",
69
69
  "sync-marketplace:force": "node scripts/sync-marketplace.cjs --force",
70
70
  "build:binaries": "node scripts/build-worker-binary.js",
@@ -125,22 +125,22 @@
125
125
  "2fa": false
126
126
  },
127
127
  "dependencies": {
128
- "@anthropic-ai/claude-agent-sdk": "^0.2.138",
129
- "@better-auth/api-key": "^1.6.9",
128
+ "@anthropic-ai/claude-agent-sdk": "^0.3.172",
129
+ "@better-auth/api-key": "^1.6.16",
130
130
  "@clack/prompts": "^1.3.0",
131
131
  "@modelcontextprotocol/sdk": "^1.29.0",
132
132
  "ansi-to-html": "^0.7.2",
133
- "better-auth": "^1.6.9",
133
+ "better-auth": "^1.6.16",
134
134
  "bullmq": "^5.76.6",
135
135
  "cors": "^2.8.6",
136
- "dompurify": "^3.4.2",
136
+ "dompurify": "^3.4.9",
137
137
  "express": "^5.2.1",
138
138
  "glob": "^13.0.6",
139
139
  "handlebars": "^4.7.9",
140
140
  "ioredis": "^5.10.1",
141
141
  "pg": "^8.20.0",
142
142
  "picocolors": "^1.1.1",
143
- "posthog-node": "^5.36.8",
143
+ "posthog-node": "^5.36.15",
144
144
  "react": "^19.2.6",
145
145
  "react-dom": "^19.2.6",
146
146
  "shell-quote": "^1.8.3",
@@ -148,6 +148,9 @@
148
148
  "zod": "^4.4.3",
149
149
  "zod-to-json-schema": "^3.25.2"
150
150
  },
151
+ "overrides": {
152
+ "tmp": "^0.2.7"
153
+ },
151
154
  "devDependencies": {
152
155
  "@derekstride/tree-sitter-sql": "^0.3.11",
153
156
  "@tree-sitter-grammars/tree-sitter-lua": "^0.4.1",
@@ -157,11 +160,10 @@
157
160
  "@tree-sitter-grammars/tree-sitter-zig": "^1.1.2",
158
161
  "@types/bun": "^1.3.13",
159
162
  "@types/cors": "^2.8.19",
160
- "@types/dompurify": "^3.2.0",
161
163
  "@types/express": "^5.0.6",
162
- "@types/node": "^25.6.2",
164
+ "@types/node": "^25.9.2",
163
165
  "@types/pg": "^8.20.0",
164
- "@types/react": "^19.2.14",
166
+ "@types/react": "^19.2.17",
165
167
  "@types/react-dom": "^19.2.3",
166
168
  "esbuild": "^0.28.0",
167
169
  "jimp": "^1.6.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "13.5.4",
3
+ "version": "13.5.7",
4
4
  "description": "Memory compression system for Claude Code - persist context across sessions",
5
5
  "author": {
6
6
  "name": "Alex Newman"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "13.5.4",
3
+ "version": "13.5.7",
4
4
  "description": "Memory compression system for Claude Code - persist context across sessions",
5
5
  "author": {
6
6
  "name": "Alex Newman",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-plugin",
3
- "version": "13.5.4",
3
+ "version": "13.5.7",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for claude-mem bundled hooks",
6
6
  "type": "module",
@@ -718,7 +718,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
718
718
  content_session_id, prompt_number, prompt_text,
719
719
  created_at, created_at_epoch
720
720
  ) VALUES (?, ?, ?, ?, ?)
721
- `).run(e.content_session_id,e.prompt_number,e.prompt_text,e.created_at,e.created_at_epoch).lastInsertRowid}}};var N=require("fs"),P=require("path"),pe=require("os");var ce={DEFAULT:3e5,HEALTH_CHECK:3e3,API_REQUEST:3e4,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,WORKER_STARTUP_WAIT:1e3,PRE_RESTART_SETTLE_DELAY:2e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function Ye(r){return process.platform==="win32"?Math.round(r*ce.WINDOWS_MULTIPLIER):r}var V=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(Ye(ce.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_GEMINI_MAX_CONTEXT_MESSAGES:"20",CLAUDE_MEM_GEMINI_MAX_TOKENS:"100000",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_OPENROUTER_MAX_CONTEXT_MESSAGES:"20",CLAUDE_MEM_OPENROUTER_MAX_TOKENS:"100000",CLAUDE_MEM_DATA_DIR:(0,P.join)((0,pe.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,P.join)((0,pe.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_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_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 getBool(e){let t=this.get(e);return t==="true"||t===!0}static applyEnvOverrides(e){let t={...e};for(let s of Object.keys(this.DEFAULTS))process.env[s]!==void 0&&(t[s]=process.env[s]);return t}static loadFromFile(e,t=!0){try{if(!(0,N.existsSync)(e)){let a=this.getAllDefaults();try{let d=(0,P.dirname)(e);(0,N.existsSync)(d)||(0,N.mkdirSync)(d,{recursive:!0}),(0,N.writeFileSync)(e,JSON.stringify(a,null,2),"utf-8"),console.log("[SETTINGS] Created settings file with defaults:",e)}catch(d){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,d instanceof Error?d.message:String(d))}return t?this.applyEnvOverrides(a):a}let s=(0,N.readFileSync)(e,"utf-8"),n=JSON.parse(s.replace(/^\uFEFF/,"")),o=n;if(n.env&&typeof n.env=="object"){o=n.env;try{(0,N.writeFileSync)(e,JSON.stringify(o,null,2),"utf-8"),console.log("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(a){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,a instanceof Error?a.message:String(a))}}let i={...this.DEFAULTS};for(let a of Object.keys(this.DEFAULTS))o[a]!==void 0&&(i[a]=o[a]);return t?this.applyEnvOverrides(i):i}catch(s){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,s instanceof Error?s.message:String(s));let n=this.getAllDefaults();return t?this.applyEnvOverrides(n):n}}};var k=require("fs"),K=require("path");var C=class r{static instance=null;activeMode=null;modesDir;constructor(){let e=ve(),t=[...process.env.CLAUDE_MEM_MODES_DIR?[process.env.CLAUDE_MEM_MODES_DIR]:[],(0,K.join)(e,"modes"),(0,K.join)(e,"..","plugin","modes")],s=t.find(n=>(0,k.existsSync)(n));this.modesDir=s||t[0]}static getInstance(){return r.instance||(r.instance=new r),r.instance}parseInheritance(e){let t=e.split("--");if(t.length===1)return{hasParent:!1,parentId:"",overrideId:""};if(t.length>2)throw new Error(`Invalid mode inheritance: ${e}. Only one level of inheritance supported (parent--override)`);return{hasParent:!0,parentId:t[0],overrideId:e}}isPlainObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}deepMerge(e,t){let s={...e};for(let n in t){let o=t[n],i=e[n];this.isPlainObject(o)&&this.isPlainObject(i)?s[n]=this.deepMerge(i,o):s[n]=o}return s}loadModeFile(e){let t=(0,K.join)(this.modesDir,`${e}.json`);if(!(0,k.existsSync)(t))throw new Error(`Mode file not found: ${t}`);let s=(0,k.readFileSync)(t,"utf-8");return JSON.parse(s)}loadMode(e){let t=this.parseInheritance(e);if(!t.hasParent)try{let d=this.loadModeFile(e);return this.activeMode=d,u.debug("SYSTEM",`Loaded mode: ${d.name} (${e})`,void 0,{types:d.observation_types.map(c=>c.id),concepts:d.observation_concepts.map(c=>c.id)}),d}catch(d){if(d instanceof Error?u.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{message:d.message}):u.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{error:String(d)}),e==="code")throw new Error("Critical: code.json mode file missing");return this.loadMode("code")}let{parentId:s,overrideId:n}=t,o;try{o=this.loadMode(s)}catch(d){d instanceof Error?u.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{message:d.message}):u.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{error:String(d)}),o=this.loadMode("code")}let i;try{i=this.loadModeFile(n),u.debug("SYSTEM",`Loaded override file: ${n} for parent ${s}`)}catch(d){return d instanceof Error?u.warn("WORKER",`Override file '${n}' not found, using parent mode '${s}' only`,{message:d.message}):u.warn("WORKER",`Override file '${n}' not found, using parent mode '${s}' only`,{error:String(d)}),this.activeMode=o,o}if(!i)return u.warn("SYSTEM",`Invalid override file: ${n}, using parent mode '${s}' only`),this.activeMode=o,o;let a=this.deepMerge(o,i);return this.activeMode=a,u.debug("SYSTEM",`Loaded mode with inheritance: ${a.name} (${e} = ${s} + ${n})`,void 0,{parent:s,override:n,types:a.observation_types.map(d=>d.id),concepts:a.observation_concepts.map(d=>d.id)}),a}getActiveMode(){if(!this.activeMode)throw new Error("No mode loaded. Call loadMode() first.");return this.activeMode}getObservationTypes(){return this.getActiveMode().observation_types}getObservationConcepts(){return this.getActiveMode().observation_concepts}getTypeIcon(e){return this.getObservationTypes().find(s=>s.id===e)?.emoji||"\u{1F4DD}"}getWorkEmoji(e){return this.getObservationTypes().find(s=>s.id===e)?.work_emoji||"\u{1F4DD}"}validateType(e){return this.getObservationTypes().some(t=>t.id===e)}getTypeLabel(e){return this.getObservationTypes().find(s=>s.id===e)?.label||e}};function me(){let r=x.settings(),e=V.loadFromFile(r),t=C.getInstance().getActiveMode(),s=new Set(t.observation_types.map(o=>o.id)),n=new Set(t.observation_concepts.map(o=>o.id));return{totalObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_OBSERVATIONS,10),fullObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_FULL_COUNT,10),sessionCount:parseInt(e.CLAUDE_MEM_CONTEXT_SESSION_COUNT,10),showReadTokens:e.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS==="true",showWorkTokens:e.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS==="true",showSavingsAmount:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT==="true",showSavingsPercent:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT==="true",observationTypes:s,observationConcepts:n,fullObservationField:e.CLAUDE_MEM_CONTEXT_FULL_FIELD,showLastSummary:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY==="true",showLastMessage:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE==="true"}}var _={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"},Ve=4,le=1;function Ee(r){let e=(r.title?.length||0)+(r.subtitle?.length||0)+(r.narrative?.length||0)+JSON.stringify(r.facts||[]).length;return Math.ceil(e/Ve)}function q(r){let e=r.length,t=r.reduce((i,a)=>i+Ee(a),0),s=r.reduce((i,a)=>i+(a.discovery_tokens||0),0),n=s-t,o=s>0?Math.round(n/s*100):0;return{totalObservations:e,totalReadTokens:t,totalDiscoveryTokens:s,savings:n,savingsPercent:o}}function ps(r){return C.getInstance().getWorkEmoji(r)}function F(r,e){let t=Ee(r),s=r.discovery_tokens||0,n=ps(r.type),o=s>0?`${n} ${s.toLocaleString()}`:"-";return{readTokens:t,discoveryTokens:s,discoveryDisplay:o,workEmoji:n}}function J(r){return r.showReadTokens||r.showWorkTokens||r.showSavingsAmount||r.showSavingsPercent}var Ke=U(require("path"),1),Q=require("fs");function ge(r,e,t){let s=Array.from(t.observationTypes),n=s.map(()=>"?").join(","),o=Array.from(t.observationConcepts),i=o.map(()=>"?").join(",");return r.db.prepare(`
721
+ `).run(e.content_session_id,e.prompt_number,e.prompt_text,e.created_at,e.created_at_epoch).lastInsertRowid}}};var N=require("fs"),P=require("path"),pe=require("os");var ce={DEFAULT:3e5,HEALTH_CHECK:3e3,API_REQUEST:3e4,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,WORKER_STARTUP_WAIT:1e3,PRE_RESTART_SETTLE_DELAY:2e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function Ye(r){return process.platform==="win32"?Math.round(r*ce.WINDOWS_MULTIPLIER):r}var V=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(Ye(ce.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_GEMINI_MAX_CONTEXT_MESSAGES:"20",CLAUDE_MEM_GEMINI_MAX_TOKENS:"100000",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_OPENROUTER_MAX_CONTEXT_MESSAGES:"20",CLAUDE_MEM_OPENROUTER_MAX_TOKENS:"100000",CLAUDE_MEM_DATA_DIR:(0,P.join)((0,pe.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,P.join)((0,pe.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_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_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 getBool(e){let t=this.get(e);return t==="true"||t===!0}static applyEnvOverrides(e){let t={...e};for(let s of Object.keys(this.DEFAULTS))process.env[s]!==void 0&&(t[s]=process.env[s]);return t}static loadFromFile(e,t=!0){try{if(!(0,N.existsSync)(e)){let a=this.getAllDefaults();try{let d=(0,P.dirname)(e);(0,N.existsSync)(d)||(0,N.mkdirSync)(d,{recursive:!0}),(0,N.writeFileSync)(e,JSON.stringify(a,null,2),"utf-8"),console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(d){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,d instanceof Error?d.message:String(d))}return t?this.applyEnvOverrides(a):a}let s=(0,N.readFileSync)(e,"utf-8"),n=JSON.parse(s.replace(/^\uFEFF/,"")),o=n;if(n.env&&typeof n.env=="object"){o=n.env;try{(0,N.writeFileSync)(e,JSON.stringify(o,null,2),"utf-8"),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(a){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,a instanceof Error?a.message:String(a))}}let i={...this.DEFAULTS};for(let a of Object.keys(this.DEFAULTS))o[a]!==void 0&&(i[a]=o[a]);return t?this.applyEnvOverrides(i):i}catch(s){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,s instanceof Error?s.message:String(s));let n=this.getAllDefaults();return t?this.applyEnvOverrides(n):n}}};var k=require("fs"),K=require("path");var C=class r{static instance=null;activeMode=null;modesDir;constructor(){let e=ve(),t=[...process.env.CLAUDE_MEM_MODES_DIR?[process.env.CLAUDE_MEM_MODES_DIR]:[],(0,K.join)(e,"modes"),(0,K.join)(e,"..","plugin","modes")],s=t.find(n=>(0,k.existsSync)(n));this.modesDir=s||t[0]}static getInstance(){return r.instance||(r.instance=new r),r.instance}parseInheritance(e){let t=e.split("--");if(t.length===1)return{hasParent:!1,parentId:"",overrideId:""};if(t.length>2)throw new Error(`Invalid mode inheritance: ${e}. Only one level of inheritance supported (parent--override)`);return{hasParent:!0,parentId:t[0],overrideId:e}}isPlainObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}deepMerge(e,t){let s={...e};for(let n in t){let o=t[n],i=e[n];this.isPlainObject(o)&&this.isPlainObject(i)?s[n]=this.deepMerge(i,o):s[n]=o}return s}loadModeFile(e){let t=(0,K.join)(this.modesDir,`${e}.json`);if(!(0,k.existsSync)(t))throw new Error(`Mode file not found: ${t}`);let s=(0,k.readFileSync)(t,"utf-8");return JSON.parse(s)}loadMode(e){let t=this.parseInheritance(e);if(!t.hasParent)try{let d=this.loadModeFile(e);return this.activeMode=d,u.debug("SYSTEM",`Loaded mode: ${d.name} (${e})`,void 0,{types:d.observation_types.map(c=>c.id),concepts:d.observation_concepts.map(c=>c.id)}),d}catch(d){if(d instanceof Error?u.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{message:d.message}):u.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{error:String(d)}),e==="code")throw new Error("Critical: code.json mode file missing");return this.loadMode("code")}let{parentId:s,overrideId:n}=t,o;try{o=this.loadMode(s)}catch(d){d instanceof Error?u.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{message:d.message}):u.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{error:String(d)}),o=this.loadMode("code")}let i;try{i=this.loadModeFile(n),u.debug("SYSTEM",`Loaded override file: ${n} for parent ${s}`)}catch(d){return d instanceof Error?u.warn("WORKER",`Override file '${n}' not found, using parent mode '${s}' only`,{message:d.message}):u.warn("WORKER",`Override file '${n}' not found, using parent mode '${s}' only`,{error:String(d)}),this.activeMode=o,o}if(!i)return u.warn("SYSTEM",`Invalid override file: ${n}, using parent mode '${s}' only`),this.activeMode=o,o;let a=this.deepMerge(o,i);return this.activeMode=a,u.debug("SYSTEM",`Loaded mode with inheritance: ${a.name} (${e} = ${s} + ${n})`,void 0,{parent:s,override:n,types:a.observation_types.map(d=>d.id),concepts:a.observation_concepts.map(d=>d.id)}),a}getActiveMode(){if(!this.activeMode)throw new Error("No mode loaded. Call loadMode() first.");return this.activeMode}getObservationTypes(){return this.getActiveMode().observation_types}getObservationConcepts(){return this.getActiveMode().observation_concepts}getTypeIcon(e){return this.getObservationTypes().find(s=>s.id===e)?.emoji||"\u{1F4DD}"}getWorkEmoji(e){return this.getObservationTypes().find(s=>s.id===e)?.work_emoji||"\u{1F4DD}"}validateType(e){return this.getObservationTypes().some(t=>t.id===e)}getTypeLabel(e){return this.getObservationTypes().find(s=>s.id===e)?.label||e}};function me(){let r=x.settings(),e=V.loadFromFile(r),t=C.getInstance().getActiveMode(),s=new Set(t.observation_types.map(o=>o.id)),n=new Set(t.observation_concepts.map(o=>o.id));return{totalObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_OBSERVATIONS,10),fullObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_FULL_COUNT,10),sessionCount:parseInt(e.CLAUDE_MEM_CONTEXT_SESSION_COUNT,10),showReadTokens:e.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS==="true",showWorkTokens:e.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS==="true",showSavingsAmount:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT==="true",showSavingsPercent:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT==="true",observationTypes:s,observationConcepts:n,fullObservationField:e.CLAUDE_MEM_CONTEXT_FULL_FIELD,showLastSummary:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY==="true",showLastMessage:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE==="true"}}var _={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"},Ve=4,le=1;function Ee(r){let e=(r.title?.length||0)+(r.subtitle?.length||0)+(r.narrative?.length||0)+JSON.stringify(r.facts||[]).length;return Math.ceil(e/Ve)}function q(r){let e=r.length,t=r.reduce((i,a)=>i+Ee(a),0),s=r.reduce((i,a)=>i+(a.discovery_tokens||0),0),n=s-t,o=s>0?Math.round(n/s*100):0;return{totalObservations:e,totalReadTokens:t,totalDiscoveryTokens:s,savings:n,savingsPercent:o}}function ps(r){return C.getInstance().getWorkEmoji(r)}function F(r,e){let t=Ee(r),s=r.discovery_tokens||0,n=ps(r.type),o=s>0?`${n} ${s.toLocaleString()}`:"-";return{readTokens:t,discoveryTokens:s,discoveryDisplay:o,workEmoji:n}}function J(r){return r.showReadTokens||r.showWorkTokens||r.showSavingsAmount||r.showSavingsPercent}var Ke=U(require("path"),1),Q=require("fs");function ge(r,e,t){let s=Array.from(t.observationTypes),n=s.map(()=>"?").join(","),o=Array.from(t.observationConcepts),i=o.map(()=>"?").join(",");return r.db.prepare(`
722
722
  SELECT
723
723
  o.id,
724
724
  o.memory_session_id,