(
send: (event: string, data: unknown) => void,
sources?: string[],
concurrency: number = 1,
)
| 4252 | } |
| 4253 | |
| 4254 | private async runMigration( |
| 4255 | send: (event: string, data: unknown) => void, |
| 4256 | sources?: string[], |
| 4257 | concurrency: number = 1, |
| 4258 | ): Promise<void> { |
| 4259 | const ocHome = this.getOpenClawHome(); |
| 4260 | const importSqlite = !sources || sources.includes("sqlite"); |
| 4261 | const importSessions = !sources || sources.includes("sessions"); |
| 4262 | |
| 4263 | let totalProcessed = 0; |
| 4264 | let totalStored = 0; |
| 4265 | let totalSkipped = 0; |
| 4266 | let totalErrors = 0; |
| 4267 | |
| 4268 | const cfgPath = this.getOpenClawConfigPath(); |
| 4269 | let summarizerCfg: any; |
| 4270 | try { |
| 4271 | const raw = JSON.parse(fs.readFileSync(cfgPath, "utf-8")); |
| 4272 | const pluginCfg = raw?.plugins?.entries?.["memos-local-openclaw-plugin"]?.config ?? |
| 4273 | raw?.plugins?.entries?.["memos-local"]?.config ?? |
| 4274 | raw?.plugins?.entries?.["memos-lite-openclaw-plugin"]?.config ?? |
| 4275 | raw?.plugins?.entries?.["memos-lite"]?.config ?? {}; |
| 4276 | summarizerCfg = pluginCfg.summarizer; |
| 4277 | } catch { /* no config */ } |
| 4278 | |
| 4279 | const summarizer = new Summarizer(summarizerCfg, this.log); |
| 4280 | |
| 4281 | // Phase 1: Import SQLite memory chunks |
| 4282 | if (importSqlite) { |
| 4283 | const memoryDir = path.join(ocHome, "memory"); |
| 4284 | if (fs.existsSync(memoryDir)) { |
| 4285 | const files = fs.readdirSync(memoryDir).filter(f => f.endsWith(".sqlite")); |
| 4286 | for (const file of files) { |
| 4287 | if (this.migrationAbort) break; |
| 4288 | send("phase", { phase: "sqlite", file }); |
| 4289 | try { |
| 4290 | const Database = require("better-sqlite3"); |
| 4291 | const db = new Database(path.join(memoryDir, file), { readonly: true }); |
| 4292 | const rows = db.prepare("SELECT id, path, text, updated_at FROM chunks ORDER BY updated_at ASC").all() as Array<{ |
| 4293 | id: string; path: string; text: string; updated_at: number; |
| 4294 | }>; |
| 4295 | db.close(); |
| 4296 | |
| 4297 | const agentId = file.replace(".sqlite", ""); |
| 4298 | send("progress", { total: rows.length, processed: 0, phase: "sqlite", file }); |
| 4299 | |
| 4300 | for (let i = 0; i < rows.length; i++) { |
| 4301 | if (this.migrationAbort) break; |
| 4302 | const row = rows[i]; |
| 4303 | totalProcessed++; |
| 4304 | |
| 4305 | const contentHash = crypto.createHash("sha256").update(row.text).digest("hex"); |
| 4306 | if (this.store.chunkExistsByContent(`agent:${agentId}:import`, "assistant", row.text) || this.store.chunkExistsByContent(`openclaw-import-${agentId}`, "assistant", row.text)) { |
| 4307 | totalSkipped++; |
| 4308 | send("item", { |
| 4309 | index: i + 1, |
| 4310 | total: rows.length, |
| 4311 | status: "skipped", |
no test coverage detected