@memclaw/memclaw 0.9.9

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,338 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration management for MemClaw
4
+ *
5
+ * Handles platform-specific config paths, config file generation,
6
+ * and auto-opening config files for user editing.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.getDataDir = getDataDir;
43
+ exports.getConfigPath = getConfigPath;
44
+ exports.generateConfigTemplate = generateConfigTemplate;
45
+ exports.ensureConfigExists = ensureConfigExists;
46
+ exports.openConfigFile = openConfigFile;
47
+ exports.parseConfig = parseConfig;
48
+ exports.validateConfig = validateConfig;
49
+ exports.updateConfigFromPlugin = updateConfigFromPlugin;
50
+ exports.mergeConfigWithPlugin = mergeConfigWithPlugin;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const os = __importStar(require("os"));
54
+ const child_process_1 = require("child_process");
55
+ // Platform-specific paths
56
+ function getDataDir() {
57
+ const platform = process.platform;
58
+ if (platform === "win32") {
59
+ return path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "memclaw");
60
+ }
61
+ else if (platform === "darwin") {
62
+ return path.join(os.homedir(), "Library", "Application Support", "memclaw");
63
+ }
64
+ else {
65
+ return path.join(os.homedir(), ".local", "share", "memclaw");
66
+ }
67
+ }
68
+ function getConfigPath() {
69
+ return path.join(getDataDir(), "config.toml");
70
+ }
71
+ function generateConfigTemplate() {
72
+ return `# MemClaw Configuration
73
+ #
74
+ # This file was auto-generated. Please fill in the required values below.
75
+ # All sections are required - missing sections will cause config to be ignored.
76
+
77
+ # Qdrant Vector Database Configuration
78
+ [qdrant]
79
+ url = "http://localhost:6334"
80
+ collection_name = "memclaw"
81
+ timeout_secs = 30
82
+
83
+ # LLM Configuration [REQUIRED for memory processing]
84
+ [llm]
85
+ api_base_url = "https://api.openai.com/v1"
86
+ api_key = ""
87
+ model_efficient = "gpt-5-mini"
88
+ temperature = 0.1
89
+ max_tokens = 4096
90
+
91
+ # Embedding Configuration [REQUIRED for vector search]
92
+ [embedding]
93
+ api_base_url = "https://api.openai.com/v1"
94
+ api_key = ""
95
+ model_name = "text-embedding-3-small"
96
+ batch_size = 10
97
+ timeout_secs = 30
98
+
99
+ # Service Configuration
100
+ [server]
101
+ host = "localhost"
102
+ port = 8085
103
+
104
+ # Logging Configuration
105
+ [logging]
106
+ enabled = false
107
+ log_directory = "logs"
108
+ level = "info"
109
+
110
+ # Cortex Memory Settings
111
+ [cortex]
112
+ enable_intent_analysis = false
113
+ `;
114
+ }
115
+ function ensureConfigExists() {
116
+ const dataDir = getDataDir();
117
+ const configPath = getConfigPath();
118
+ if (!fs.existsSync(dataDir)) {
119
+ fs.mkdirSync(dataDir, { recursive: true });
120
+ }
121
+ if (!fs.existsSync(configPath)) {
122
+ const template = generateConfigTemplate();
123
+ fs.writeFileSync(configPath, template, "utf-8");
124
+ return { created: true, path: configPath };
125
+ }
126
+ return { created: false, path: configPath };
127
+ }
128
+ function openConfigFile(configPath) {
129
+ return new Promise((resolve, reject) => {
130
+ const platform = process.platform;
131
+ let command;
132
+ let args = [];
133
+ if (platform === "win32") {
134
+ command = "cmd";
135
+ args = ["/c", "start", '""', configPath];
136
+ }
137
+ else if (platform === "darwin") {
138
+ command = "open";
139
+ args = [configPath];
140
+ }
141
+ else {
142
+ command = "xdg-open";
143
+ args = [configPath];
144
+ }
145
+ const proc = (0, child_process_1.spawn)(command, args, { detached: true, stdio: "ignore" });
146
+ proc.on("error", (err) => {
147
+ reject(err);
148
+ });
149
+ proc.unref();
150
+ resolve();
151
+ });
152
+ }
153
+ function parseConfig(configPath) {
154
+ const content = fs.readFileSync(configPath, "utf-8");
155
+ const config = {};
156
+ let currentSection = "";
157
+ for (const line of content.split("\n")) {
158
+ const trimmed = line.trim();
159
+ // Skip comments and empty lines
160
+ if (trimmed.startsWith("#") || trimmed === "")
161
+ continue;
162
+ // Section header
163
+ const sectionMatch = trimmed.match(/^\[(\w+)\]$/);
164
+ if (sectionMatch) {
165
+ currentSection = sectionMatch[1];
166
+ config[currentSection] = {};
167
+ continue;
168
+ }
169
+ // Key-value pair
170
+ const kvMatch = trimmed.match(/^(\w+)\s*=\s*"([^"]*)"(?:\s*$|\s*#)/) ||
171
+ trimmed.match(/^(\w+)\s*=\s*(\d+(?:\.\d+)?)(?:\s*$|\s*#)/) ||
172
+ trimmed.match(/^(\w+)\s*=\s*(true|false)(?:\s*$|\s*#)/);
173
+ if (kvMatch && currentSection) {
174
+ const key = kvMatch[1];
175
+ let value = kvMatch[2];
176
+ // Convert to appropriate type
177
+ if (value === "true")
178
+ value = true;
179
+ else if (value === "false")
180
+ value = false;
181
+ else if (/^\d+$/.test(value))
182
+ value = parseInt(value, 10);
183
+ else if (/^\d+\.\d+$/.test(value))
184
+ value = parseFloat(value);
185
+ config[currentSection] = config[currentSection] || {};
186
+ config[currentSection][key] = value;
187
+ }
188
+ }
189
+ // Apply defaults
190
+ return {
191
+ qdrant: {
192
+ url: "http://localhost:6334",
193
+ collection_name: "memclaw",
194
+ timeout_secs: 30,
195
+ ...(config.qdrant || {}),
196
+ },
197
+ llm: {
198
+ api_base_url: "https://api.openai.com/v1",
199
+ api_key: "",
200
+ model_efficient: "gpt-5-mini",
201
+ temperature: 0.1,
202
+ max_tokens: 4096,
203
+ ...(config.llm || {}),
204
+ },
205
+ embedding: {
206
+ api_base_url: "https://api.openai.com/v1",
207
+ api_key: "",
208
+ model_name: "text-embedding-3-small",
209
+ batch_size: 10,
210
+ timeout_secs: 30,
211
+ ...(config.embedding || {}),
212
+ },
213
+ server: {
214
+ host: "localhost",
215
+ port: 8085,
216
+ ...(config.server || {}),
217
+ },
218
+ logging: {
219
+ enabled: false,
220
+ log_directory: "logs",
221
+ level: "info",
222
+ ...(config.logging || {}),
223
+ },
224
+ cortex: {
225
+ enable_intent_analysis: false,
226
+ ...(config.cortex || {}),
227
+ },
228
+ };
229
+ }
230
+ function validateConfig(config) {
231
+ const errors = [];
232
+ if (!config.llm.api_key || config.llm.api_key === "") {
233
+ errors.push("llm.api_key is required");
234
+ }
235
+ if (!config.embedding.api_key || config.embedding.api_key === "") {
236
+ // Allow using llm.api_key for embedding if not specified
237
+ if (config.llm.api_key && config.llm.api_key !== "") {
238
+ config.embedding.api_key = config.llm.api_key;
239
+ }
240
+ else {
241
+ errors.push("embedding.api_key is required");
242
+ }
243
+ }
244
+ return {
245
+ valid: errors.length === 0,
246
+ errors,
247
+ };
248
+ }
249
+ /**
250
+ * Update config.toml with values from OpenClaw plugin config
251
+ * Only updates fields that are provided (non-empty) in pluginConfig
252
+ */
253
+ function updateConfigFromPlugin(pluginConfig) {
254
+ const configPath = getConfigPath();
255
+ // Ensure config file exists
256
+ ensureConfigExists();
257
+ // Parse existing config
258
+ const existingConfig = parseConfig(configPath);
259
+ // Track if any changes were made
260
+ let updated = false;
261
+ // Build updated config sections
262
+ const updates = [];
263
+ // LLM config updates
264
+ if (pluginConfig.llmApiKey && pluginConfig.llmApiKey !== "") {
265
+ updates.push({ section: "llm", key: "api_key", value: pluginConfig.llmApiKey });
266
+ updated = true;
267
+ }
268
+ if (pluginConfig.llmApiBaseUrl && pluginConfig.llmApiBaseUrl !== "") {
269
+ updates.push({ section: "llm", key: "api_base_url", value: pluginConfig.llmApiBaseUrl });
270
+ updated = true;
271
+ }
272
+ if (pluginConfig.llmModel && pluginConfig.llmModel !== "") {
273
+ updates.push({ section: "llm", key: "model_efficient", value: pluginConfig.llmModel });
274
+ updated = true;
275
+ }
276
+ // Embedding config updates
277
+ if (pluginConfig.embeddingApiKey && pluginConfig.embeddingApiKey !== "") {
278
+ updates.push({ section: "embedding", key: "api_key", value: pluginConfig.embeddingApiKey });
279
+ updated = true;
280
+ }
281
+ if (pluginConfig.embeddingApiBaseUrl && pluginConfig.embeddingApiBaseUrl !== "") {
282
+ updates.push({ section: "embedding", key: "api_base_url", value: pluginConfig.embeddingApiBaseUrl });
283
+ updated = true;
284
+ }
285
+ if (pluginConfig.embeddingModel && pluginConfig.embeddingModel !== "") {
286
+ updates.push({ section: "embedding", key: "model_name", value: pluginConfig.embeddingModel });
287
+ updated = true;
288
+ }
289
+ if (!updated) {
290
+ return { updated: false, path: configPath };
291
+ }
292
+ // Read current content
293
+ let content = fs.readFileSync(configPath, "utf-8");
294
+ // Apply each update
295
+ for (const { section, key, value } of updates) {
296
+ // Escape value for TOML string
297
+ const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
298
+ // Pattern to match the key in the correct section
299
+ // This handles both existing keys and missing keys
300
+ const sectionPattern = new RegExp(`(\\[${section}\\][^\\[]*?)(${key}\\s*=\\s*)"[^"]*"`, "s");
301
+ const keyExistsInSection = sectionPattern.test(content);
302
+ if (keyExistsInSection) {
303
+ // Update existing key
304
+ content = content.replace(sectionPattern, `$1$2"${escapedValue}"`);
305
+ }
306
+ else {
307
+ // Add key to section
308
+ const sectionStartPattern = new RegExp(`(\\[${section}\\]\\n)`, "");
309
+ if (sectionStartPattern.test(content)) {
310
+ content = content.replace(sectionStartPattern, `$1${key} = "${escapedValue}"\n`);
311
+ }
312
+ }
313
+ }
314
+ // Write updated content
315
+ fs.writeFileSync(configPath, content, "utf-8");
316
+ return { updated: true, path: configPath };
317
+ }
318
+ /**
319
+ * Merge plugin config with file config, preferring plugin config values
320
+ */
321
+ function mergeConfigWithPlugin(fileConfig, pluginConfig) {
322
+ return {
323
+ ...fileConfig,
324
+ llm: {
325
+ ...fileConfig.llm,
326
+ api_base_url: pluginConfig.llmApiBaseUrl || fileConfig.llm.api_base_url,
327
+ api_key: pluginConfig.llmApiKey || fileConfig.llm.api_key,
328
+ model_efficient: pluginConfig.llmModel || fileConfig.llm.model_efficient,
329
+ },
330
+ embedding: {
331
+ ...fileConfig.embedding,
332
+ api_base_url: pluginConfig.embeddingApiBaseUrl || fileConfig.embedding.api_base_url,
333
+ api_key: pluginConfig.embeddingApiKey || fileConfig.embedding.api_key,
334
+ model_name: pluginConfig.embeddingModel || fileConfig.embedding.model_name,
335
+ },
336
+ };
337
+ }
338
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Migration script for OpenClaw native memory to MemClaw
3
+ *
4
+ * Migrates:
5
+ * - memory/YYYY-MM-DD.md → session timeline files
6
+ * - MEMORY.md → users/{tenant}/preferences.md
7
+ */
8
+ interface MigrationResult {
9
+ dailyLogsMigrated: number;
10
+ memoryMdMigrated: boolean;
11
+ sessionsCreated: string[];
12
+ errors: string[];
13
+ }
14
+ /**
15
+ * Main migration function
16
+ */
17
+ export declare function migrateFromOpenClaw(log?: (msg: string) => void): Promise<MigrationResult>;
18
+ /**
19
+ * Check if migration is possible
20
+ */
21
+ export declare function canMigrate(): {
22
+ possible: boolean;
23
+ reason: string;
24
+ };
25
+ export {};
26
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,UAAU,eAAe;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAgPD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,eAAe,CAAC,CA8C1B;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAelE"}
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /**
3
+ * Migration script for OpenClaw native memory to MemClaw
4
+ *
5
+ * Migrates:
6
+ * - memory/YYYY-MM-DD.md → session timeline files
7
+ * - MEMORY.md → users/{tenant}/preferences.md
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.migrateFromOpenClaw = migrateFromOpenClaw;
44
+ exports.canMigrate = canMigrate;
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const child_process_1 = require("child_process");
49
+ const util_1 = require("util");
50
+ const glob_1 = require("glob");
51
+ const config_js_1 = require("./config.js");
52
+ const binaries_js_1 = require("./binaries.js");
53
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
54
+ // Migration configuration
55
+ const MIGRATION_TENANT = 'tenant_claw';
56
+ const DEFAULT_ROLE = 'user';
57
+ /**
58
+ * Detect OpenClaw workspace directory
59
+ */
60
+ function findOpenClawWorkspace() {
61
+ const homeDir = os.homedir();
62
+ const workspacePath = path.join(homeDir, '.openclaw', 'workspace');
63
+ if (fs.existsSync(workspacePath)) {
64
+ return workspacePath;
65
+ }
66
+ return null;
67
+ }
68
+ /**
69
+ * Split content into paragraphs (not just lines)
70
+ */
71
+ function splitIntoParagraphs(content) {
72
+ return content
73
+ .split(/\n\s*\n/)
74
+ .map(p => p.trim())
75
+ .filter(p => p.length > 0 && !p.startsWith('#')); // Skip headers
76
+ }
77
+ /**
78
+ * Generate L2 content for a single paragraph
79
+ */
80
+ function generateL2Content(paragraph, sessionId, date, index) {
81
+ // Generate a deterministic timestamp based on index
82
+ const hour = String(index % 24).padStart(2, '0');
83
+ const minute = String((index * 7) % 60).padStart(2, '0');
84
+ const second = String((index * 13) % 60).padStart(2, '0');
85
+ const timestamp = `${date}T${hour}:${minute}:${second}Z`;
86
+ const msgId = `${date.replace(/-/g, '')}_${String(index).padStart(4, '0')}`;
87
+ return `---
88
+ id: "${msgId}"
89
+ role: "${DEFAULT_ROLE}"
90
+ timestamp: "${timestamp}"
91
+ thread_id: "${sessionId}"
92
+ ---
93
+ ${paragraph}`;
94
+ }
95
+ /**
96
+ * Migrate daily logs from OpenClaw native memory to MemClaw
97
+ */
98
+ async function migrateDailyLogs(ocWorkspace, dataDir, log) {
99
+ const memoryDir = path.join(ocWorkspace, 'memory');
100
+ const count = 0;
101
+ const sessions = [];
102
+ const errors = [];
103
+ if (!fs.existsSync(memoryDir)) {
104
+ log?.('No memory directory found in OpenClaw workspace');
105
+ return { count: 0, sessions: [], errors: [] };
106
+ }
107
+ // Find all daily log files
108
+ const dailyLogPattern = path.join(memoryDir, '*.md').replace(/\\/g, '/');
109
+ const files = await (0, glob_1.glob)(dailyLogPattern);
110
+ const dailyLogs = files.filter(f => {
111
+ const basename = path.basename(f);
112
+ return /^\d{4}-\d{2}-\d{2}\.md$/.test(basename);
113
+ });
114
+ log?.(`Found ${dailyLogs.length} daily log files to migrate`);
115
+ for (const logPath of dailyLogs) {
116
+ try {
117
+ const date = path.basename(logPath, '.md'); // 2026-03-13
118
+ const [year, month, day] = date.split('-');
119
+ const sessionId = `migrated-oc-${date}`;
120
+ const timelineDir = path.join(dataDir, 'sessions', MIGRATION_TENANT, sessionId, 'timeline', year, month, day);
121
+ // Create directory
122
+ fs.mkdirSync(timelineDir, { recursive: true });
123
+ // Read and split content
124
+ const content = fs.readFileSync(logPath, 'utf-8');
125
+ const paragraphs = splitIntoParagraphs(content);
126
+ // Write each paragraph as L2 file
127
+ for (let i = 0; i < paragraphs.length; i++) {
128
+ const para = paragraphs[i];
129
+ const hour = String(i % 24).padStart(2, '0');
130
+ const minute = String((i * 7) % 60).padStart(2, '0');
131
+ const second = String((i * 13) % 60).padStart(2, '0');
132
+ const msgId = `${date.replace(/-/g, '')}_${String(i).padStart(4, '0')}`;
133
+ const l2Content = generateL2Content(para, sessionId, date, i);
134
+ const filename = `${hour}_${minute}_${second}_${msgId}.md`;
135
+ fs.writeFileSync(path.join(timelineDir, filename), l2Content, 'utf-8');
136
+ }
137
+ sessions.push(sessionId);
138
+ log?.(`Migrated ${date}: ${paragraphs.length} messages`);
139
+ }
140
+ catch (err) {
141
+ const errorMsg = `Failed to migrate ${logPath}: ${err}`;
142
+ errors.push(errorMsg);
143
+ log?.(`Error: ${errorMsg}`);
144
+ }
145
+ }
146
+ return {
147
+ count: dailyLogs.length,
148
+ sessions,
149
+ errors,
150
+ };
151
+ }
152
+ /**
153
+ * Migrate MEMORY.md to user preferences
154
+ */
155
+ async function migrateMemoryMd(ocWorkspace, dataDir, log) {
156
+ const memoryMdPath = path.join(ocWorkspace, 'MEMORY.md');
157
+ if (!fs.existsSync(memoryMdPath)) {
158
+ log?.('No MEMORY.md found');
159
+ return { migrated: false };
160
+ }
161
+ try {
162
+ const userDir = path.join(dataDir, 'users', MIGRATION_TENANT);
163
+ fs.mkdirSync(userDir, { recursive: true });
164
+ const content = fs.readFileSync(memoryMdPath, 'utf-8');
165
+ const targetPath = path.join(userDir, 'preferences.md');
166
+ // Add header to indicate migration source
167
+ const migratedContent = `<!--
168
+ Migrated from OpenClaw native MEMORY.md
169
+ Original path: ${memoryMdPath}
170
+ Migration date: ${new Date().toISOString()}
171
+ -->
172
+ ${content}`;
173
+ fs.writeFileSync(targetPath, migratedContent, 'utf-8');
174
+ log?.('Migrated MEMORY.md to user preferences');
175
+ return { migrated: true };
176
+ }
177
+ catch (err) {
178
+ const error = `Failed to migrate MEMORY.md: ${err}`;
179
+ log?.(`Error: ${error}`);
180
+ return { migrated: false, error };
181
+ }
182
+ }
183
+ /**
184
+ * Generate L0/L1 layers using cortex-mem-cli
185
+ */
186
+ async function generateLayers(configPath, tenant, log) {
187
+ log?.('Generating L0/L1 layers...');
188
+ const cliPath = (0, binaries_js_1.getCliPath)();
189
+ if (!cliPath) {
190
+ log?.('cortex-mem-cli not found, skipping layer generation');
191
+ return;
192
+ }
193
+ try {
194
+ const { stdout, stderr } = await execAsync(`"${cliPath}" --config "${configPath}" --tenant ${tenant} layers ensure-all`, { timeout: 300000 } // 5 minutes
195
+ );
196
+ if (stdout)
197
+ log?.(stdout);
198
+ if (stderr)
199
+ log?.(stderr);
200
+ log?.('Layer generation completed');
201
+ }
202
+ catch (err) {
203
+ log?.(`Layer generation warning: ${err}`);
204
+ // Don't throw - this is not critical for migration
205
+ }
206
+ }
207
+ /**
208
+ * Generate vector index using cortex-mem-cli
209
+ */
210
+ async function generateVectorIndex(configPath, tenant, log) {
211
+ log?.('Generating vector index...');
212
+ const cliPath = (0, binaries_js_1.getCliPath)();
213
+ if (!cliPath) {
214
+ log?.('cortex-mem-cli not found, skipping vector index generation');
215
+ return;
216
+ }
217
+ try {
218
+ const { stdout, stderr } = await execAsync(`"${cliPath}" --config "${configPath}" --tenant ${tenant} vector reindex`, { timeout: 600000 } // 10 minutes
219
+ );
220
+ if (stdout)
221
+ log?.(stdout);
222
+ if (stderr)
223
+ log?.(stderr);
224
+ log?.('Vector index generation completed');
225
+ }
226
+ catch (err) {
227
+ log?.(`Vector index warning: ${err}`);
228
+ // Don't throw - this is not critical for migration
229
+ }
230
+ }
231
+ /**
232
+ * Main migration function
233
+ */
234
+ async function migrateFromOpenClaw(log) {
235
+ const result = {
236
+ dailyLogsMigrated: 0,
237
+ memoryMdMigrated: false,
238
+ sessionsCreated: [],
239
+ errors: [],
240
+ };
241
+ log?.('Starting OpenClaw memory migration...');
242
+ // Find OpenClaw workspace
243
+ const ocWorkspace = findOpenClawWorkspace();
244
+ if (!ocWorkspace) {
245
+ const error = 'OpenClaw workspace not found at ~/.openclaw/workspace';
246
+ result.errors.push(error);
247
+ log?.(error);
248
+ return result;
249
+ }
250
+ log?.(`Found OpenClaw workspace: ${ocWorkspace}`);
251
+ const dataDir = (0, config_js_1.getDataDir)();
252
+ const configPath = (0, config_js_1.getConfigPath)();
253
+ // Migrate daily logs
254
+ const dailyResult = await migrateDailyLogs(ocWorkspace, dataDir, log);
255
+ result.dailyLogsMigrated = dailyResult.count;
256
+ result.sessionsCreated = dailyResult.sessions;
257
+ result.errors.push(...dailyResult.errors);
258
+ // Migrate MEMORY.md
259
+ const memoryMdResult = await migrateMemoryMd(ocWorkspace, dataDir, log);
260
+ result.memoryMdMigrated = memoryMdResult.migrated;
261
+ if (memoryMdResult.error) {
262
+ result.errors.push(memoryMdResult.error);
263
+ }
264
+ // Generate layers and index
265
+ if (result.dailyLogsMigrated > 0 || result.memoryMdMigrated) {
266
+ await generateLayers(configPath, MIGRATION_TENANT, log);
267
+ await generateVectorIndex(configPath, MIGRATION_TENANT, log);
268
+ }
269
+ log?.(`Migration completed: ${result.dailyLogsMigrated} daily logs, MEMORY.md: ${result.memoryMdMigrated}`);
270
+ return result;
271
+ }
272
+ /**
273
+ * Check if migration is possible
274
+ */
275
+ function canMigrate() {
276
+ const ocWorkspace = findOpenClawWorkspace();
277
+ if (!ocWorkspace) {
278
+ return { possible: false, reason: 'OpenClaw workspace not found' };
279
+ }
280
+ const memoryDir = path.join(ocWorkspace, 'memory');
281
+ const memoryMd = path.join(ocWorkspace, 'MEMORY.md');
282
+ if (!fs.existsSync(memoryDir) && !fs.existsSync(memoryMd)) {
283
+ return { possible: false, reason: 'No memory files found in OpenClaw workspace' };
284
+ }
285
+ return { possible: true, reason: 'OpenClaw memory found and ready for migration' };
286
+ }
287
+ //# sourceMappingURL=migrate.js.map