import fs from "node:fs"; import path from "node:path"; import { execSync, spawn } from "node:child_process"; if (!process.env.__OPENCLAW_PREFLIGHT_DONE) { process.env.__OPENCLAW_PREFLIGHT_DONE = "1"; const isGateway = process.argv.some(arg => arg.endsWith("openclaw.mjs") || arg.endsWith("openclaw")) && process.argv.includes("gateway"); if (isGateway) { const t0 = Date.now(); console.log("[gateway-preflight] Initializing container self-healing preflight..."); // 1. Clean up stale gateway lock files from ungraceful kills for (const dir of ["/tmp/openclaw-1000", "/tmp"]) { if (fs.existsSync(dir)) { try { const files = fs.readdirSync(dir); for (const file of files) { if (file.startsWith("gateway") && file.endsWith(".lock")) { const fullPath = path.join(dir, file); fs.unlinkSync(fullPath); console.log(`[gateway-preflight] Removed stale lock: ${fullPath}`); } } } catch (e) { console.warn(`[gateway-preflight] Lock cleanup warning in ${dir}:`, e.message); } } } // 2. Clear false database quarantines const qPath = "/home/node/.openclaw/state/openclaw-quarantine.sqlite"; if (fs.existsSync(qPath)) { try { execSync(`/home/node/.openclaw/.local/bin/python3 -c "import sqlite3; c=sqlite3.connect(\x27${qPath}\x27); c.execute(\x27DELETE FROM quarantined_databases\x27); c.commit(); c.close()"`, { stdio: "ignore" }); console.log("[gateway-preflight] Cleared database quarantine."); } catch (_) {} } // 3. Deduplicate subagent vector databases (keeps non-main agent DBs < 15MB) try { execSync("/home/node/.openclaw/.local/bin/python3 /home/node/.openclaw/scripts/dedup_subagent_vectors.py", { stdio: "inherit" }); } catch (e) { console.warn("[gateway-preflight] Vector deduplication warning:", e.message); } // 4. Pre-warm page cache sequentially (transforms random 70 IOPS disk reads into sequential streaming) try { const pw0 = Date.now(); execSync("cat /home/node/.openclaw/state/openclaw.sqlite /home/node/.openclaw/agents/*/agent/openclaw-agent.sqlite > /dev/null 2>&1 || true; find /home/node/.openclaw/wiki/main /home/node/.openclaw/workspace* -maxdepth 3 -name '*.md' -exec cat {} + > /dev/null 2>&1 || true"); console.log(`[gateway-preflight] Pre-warmed SQLite databases and Wiki markdown in ${Date.now() - pw0}ms`); } catch (_) {} // 5. Recover any wedged running sessions left over from ungraceful container restart try { execSync("/home/node/.openclaw/.local/bin/python3 /home/node/.openclaw/scripts/recover_sessions.py", { stdio: "inherit" }); } catch (e) { console.warn("[gateway-preflight] Session recovery warning:", e.message); } // 6. Spawn background turn replay daemon if interrupted turns were detected try { if (fs.existsSync("/tmp/openclaw-interrupted-turns.json")) { console.log("[gateway-preflight] Spawning background turn replay daemon..."); const child = spawn("/home/node/.openclaw/.local/bin/python3", ["/home/node/.openclaw/scripts/replay_interrupted_turns.py"], { detached: true, stdio: "ignore" }); child.unref(); } } catch (e) { console.warn("[gateway-preflight] Could not spawn turn replay daemon:", e.message); } console.log(`[gateway-preflight] Self-healing completed in ${Date.now() - t0}ms.`); } }