import {
  scanSignals
} from "./chunk-XYIK4LF6.js";
import {
  log
} from "./chunk-2ODBA7MQ.js";

// src/bootstrap.ts
import path from "path";
import { readdir, readFile } from "fs/promises";
var BootstrapEngine = class {
  constructor(config, orchestrator) {
    this.config = config;
    this.orchestrator = orchestrator;
  }
  config;
  orchestrator;
  async run(options) {
    const dryRun = options.dryRun === true;
    const since = options.since ?? /* @__PURE__ */ new Date(0);
    const end = /* @__PURE__ */ new Date();
    const limit = Math.max(0, options.limit ?? Number.POSITIVE_INFINITY);
    const sessions = await this.resolveSessions(options.sessionsDir, since, end);
    const selected = sessions.slice(0, Number.isFinite(limit) ? limit : sessions.length);
    const beforeCount = dryRun ? 0 : (await this.orchestrator.storage.readAllMemories()).length;
    let turnsProcessed = 0;
    let highSignalTurns = 0;
    let skipped = 0;
    for (const session of selected) {
      for (const entry of session.entries) {
        if (entry.role !== "user") continue;
        turnsProcessed += 1;
        const content = typeof entry.content === "string" ? entry.content.trim() : "";
        if (!content) {
          skipped += 1;
          continue;
        }
        const signal = scanSignals(content, this.config.highSignalPatterns);
        if (signal.level !== "high") {
          skipped += 1;
          continue;
        }
        highSignalTurns += 1;
        if (!dryRun) {
          await this.orchestrator.processTurn("user", content, session.sessionKey);
        }
      }
    }
    let memoriesCreated = 0;
    if (!dryRun && highSignalTurns > 0) {
      await this.orchestrator.waitForExtractionIdle();
      const afterCount = (await this.orchestrator.storage.readAllMemories()).length;
      memoriesCreated = Math.max(0, afterCount - beforeCount);
    }
    const result = {
      sessionsScanned: selected.length,
      turnsProcessed,
      highSignalTurns,
      memoriesCreated,
      skipped
    };
    log.info(
      `bootstrap complete: sessions=${result.sessionsScanned}, turns=${result.turnsProcessed}, high=${result.highSignalTurns}, created=${result.memoriesCreated}, skipped=${result.skipped}, dryRun=${dryRun}`
    );
    return result;
  }
  async resolveSessions(sessionsDir, since, until) {
    if (sessionsDir && sessionsDir.trim().length > 0) {
      return this.readSessionsFromDir(sessionsDir, since, until);
    }
    const keys = await this.orchestrator.transcript.listSessionKeys();
    const sessions = [];
    for (const key of keys) {
      const entries = await this.orchestrator.transcript.readRange(
        since.toISOString(),
        until.toISOString(),
        key
      );
      if (entries.length > 0) {
        sessions.push({ sessionKey: key, entries });
      }
    }
    return sessions;
  }
  async readSessionsFromDir(baseDir, since, until) {
    const files = await this.listJsonlFiles(baseDir);
    const bySession = /* @__PURE__ */ new Map();
    for (const filePath of files) {
      let raw = "";
      try {
        raw = await readFile(filePath, "utf-8");
      } catch {
        continue;
      }
      const lines = raw.split("\n").filter((line) => line.trim().length > 0);
      for (const line of lines) {
        let parsed;
        try {
          parsed = JSON.parse(line);
        } catch {
          continue;
        }
        const ts = new Date(String(parsed?.timestamp ?? ""));
        if (Number.isNaN(ts.getTime())) continue;
        if (ts < since || ts > until) continue;
        const role = String(parsed?.role ?? "");
        const content = typeof parsed?.content === "string" ? parsed.content : "";
        if (!role || !content) continue;
        const sessionKey = typeof parsed?.sessionKey === "string" && parsed.sessionKey.length > 0 ? parsed.sessionKey : path.relative(baseDir, filePath);
        const list = bySession.get(sessionKey) ?? [];
        list.push({
          role,
          content,
          timestamp: ts.toISOString(),
          sessionKey
        });
        bySession.set(sessionKey, list);
      }
    }
    return Array.from(bySession.entries()).map(([sessionKey, entries]) => ({
      sessionKey,
      entries: entries.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
    }));
  }
  async listJsonlFiles(dir) {
    const out = [];
    const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
    for (const entry of entries) {
      const full = path.join(dir, entry.name);
      if (entry.isDirectory()) {
        out.push(...await this.listJsonlFiles(full));
      } else if (entry.isFile() && full.endsWith(".jsonl")) {
        out.push(full);
      }
    }
    return out;
  }
};

export {
  BootstrapEngine
};
//# sourceMappingURL=chunk-N53K2EXC.js.map