// @bun
import {
  parseFilterTokens
} from "./chunk-wk6ynbab.js";
import {
  SqliteLogStore,
  filterLogEntries,
  findLatestLogFile
} from "./chunk-ezj5n8ct.js";
import {
  findMatchingAdkDevConsole
} from "./chunk-wv16r7dd.js";
import"./chunk-91ams3v9.js";
import {
  ensureJsonOnlyFormat
} from "./chunk-5zqmmchg.js";
import"./chunk-2jcqy5j6.js";
import"./chunk-damz8wsc.js";
import {
  findAgentRootOrFail
} from "./chunk-6fad0ts7.js";
import {
  createCliLogger,
  source_default
} from "./chunk-t993tmz7.js";
import"./chunk-px7fts59.js";
import {
  AdkError
} from "./chunk-7krp2mgz.js";
import"./chunk-np5wcwfv.js";
import"./chunk-je8v6rhj.js";
import"./chunk-6w0knnta.js";
import"./chunk-w15xmtkn.js";
import"./chunk-3sd5p4qp.js";
import"./chunk-nh2akp42.js";
import"./chunk-kat1bv74.js";
import"./chunk-2a5b6azq.js";
import"./chunk-s8cp3qe6.js";
import"./chunk-fv5teh9w.js";
import"./chunk-8ab2w9a1.js";
import"./chunk-3xrpxgq4.js";
import"./chunk-w346ejn9.js";
import"./chunk-n8gath4k.js";
import"./chunk-v3ens42y.js";
import"./chunk-8839jtgk.js";
import"./chunk-s2akeqpw.js";
import"./chunk-6771vrjp.js";
import"./chunk-g8mm42v1.js";
import"./chunk-0q5d80bn.js";
import"./chunk-300xaact.js";
import"./chunk-b8c41yvb.js";
import"./chunk-jsqe5am4.js";
import"./chunk-m4c14gcg.js";
import"./chunk-gspjbr79.js";
import"./chunk-wesykvkp.js";
import"./chunk-gzj56z73.js";
import"./chunk-dhs2bg35.js";

// src/commands/adk-logs.ts
import { existsSync as existsSync2, statSync } from "fs";
import { join as join2 } from "path";

// src/logs/log-follower.ts
var POLL_INTERVAL_MS = 1000;
function createLogFollower(store, query = {}) {
  let lastId = store.getMaxId();
  let stopped = false;
  let resolveNext = null;
  const buffer = [];
  let intervalId = null;
  function poll() {
    if (stopped)
      return;
    const rows = store.getLogsAfter(lastId, query);
    for (const row of rows) {
      if (row.id > lastId)
        lastId = row.id;
      if (resolveNext) {
        const resolve = resolveNext;
        resolveNext = null;
        resolve({ value: row, done: false });
      } else {
        buffer.push(row);
      }
    }
  }
  function stop() {
    stopped = true;
    if (intervalId) {
      clearInterval(intervalId);
      intervalId = null;
    }
    if (resolveNext) {
      const resolve = resolveNext;
      resolveNext = null;
      resolve({ value: undefined, done: true });
    }
  }
  const entries = {
    [Symbol.asyncIterator]() {
      if (!intervalId && !stopped) {
        intervalId = setInterval(poll, POLL_INTERVAL_MS);
        intervalId.unref?.();
      }
      return {
        next() {
          if (buffer.length > 0) {
            return Promise.resolve({ value: buffer.shift(), done: false });
          }
          if (stopped) {
            return Promise.resolve({ value: undefined, done: true });
          }
          return new Promise((resolve) => {
            resolveNext = resolve;
          });
        }
      };
    }
  };
  return { entries, stop };
}
// src/logs/log-formatter.ts
var LEVEL_LABELS = {
  error: "ERROR",
  warning: "WARN ",
  info: "INFO ",
  raw: "RAW  "
};
function levelColor(level) {
  switch (level) {
    case "error":
      return source_default.red;
    case "warning":
      return source_default.yellow;
    case "info":
      return source_default.cyan;
    default:
      return source_default.gray;
  }
}
function formatLogEntry(entry, _opts) {
  const ts = new Date(entry.timestamp);
  const timeStr = ts.toLocaleTimeString("en-US", { hour12: false });
  const label = LEVEL_LABELS[entry.level] || entry.level.toUpperCase().padEnd(5);
  const colorize = levelColor(entry.level);
  return `${source_default.dim(`[${timeStr}]`)} ${colorize(label)}  ${entry.message}`;
}
// src/logs/log-summary.ts
import { existsSync } from "fs";
import { join } from "path";
var ALL_LOG_LIMIT = 5000;
function normalizeHealthStatus(status) {
  if (status === "running")
    return "ready";
  if (status === "ready" || status === "building" || status === "error")
    return status;
  return "unknown";
}
function isError(entry) {
  return entry.level === "error";
}
function isWarning(entry) {
  return entry.level === "warning";
}
function getEntryFindingLevel(entry) {
  if (isError(entry))
    return "error";
  if (isWarning(entry))
    return "warning";
  return null;
}
function parseBuildDuration(message) {
  const match = message.match(/(\d+(?:\.\d+)?)ms/);
  if (!match)
    return;
  const duration = Number.parseFloat(match[1]);
  return Number.isFinite(duration) ? duration : undefined;
}
function detectBuildStatus(entries) {
  for (let index = entries.length - 1;index >= 0; index--) {
    const entry = entries[index];
    const message = entry.message.toLowerCase();
    if (message.includes("bot bundled") || message.includes("typings generated") || message.includes("dev bot ready") || message.includes("listening on")) {
      return {
        status: "ready",
        lastBuild: {
          timestamp: entry.timestamp,
          duration: parseBuildDuration(entry.message),
          message: entry.message
        }
      };
    }
    if (message.includes("bundling") || message.includes("generating") || message.includes("compiling")) {
      return {
        status: "building",
        lastBuild: {
          timestamp: entry.timestamp,
          message: entry.message
        }
      };
    }
    if (isError(entry)) {
      return {
        status: "error",
        lastBuild: {
          timestamp: entry.timestamp,
          message: entry.message
        }
      };
    }
  }
  return { status: "unknown" };
}
function mergeBuildStatus(healthStatus, logStatus) {
  if (healthStatus === "error")
    return "error";
  if (healthStatus === "building")
    return logStatus === "error" ? "error" : "building";
  if (healthStatus === "ready")
    return logStatus === "error" ? "error" : "ready";
  return logStatus;
}
function serializeEntry(entry) {
  return {
    timestamp: entry.timestamp,
    type: entry.type,
    level: entry.level,
    message: entry.message,
    ...entry.spanId ? { spanId: entry.spanId } : {},
    ...entry.traceId ? { traceId: entry.traceId } : {}
  };
}
function dedupeFindings(entries) {
  const findings = new Map;
  for (const entry of entries) {
    const level = getEntryFindingLevel(entry);
    if (!level) {
      continue;
    }
    const message = entry.message.trim();
    const key = `${level}:${message}`;
    const existing = findings.get(key);
    if (existing) {
      existing.count += 1;
      existing.lastSeenAt = entry.timestamp;
      continue;
    }
    findings.set(key, {
      level,
      message,
      count: 1,
      firstSeenAt: entry.timestamp,
      lastSeenAt: entry.timestamp
    });
  }
  return [...findings.values()];
}
async function buildLogSummary(options, dependencies = {}) {
  const findAdkDevConsole = dependencies.findAdkDevConsole ?? findMatchingAdkDevConsole;
  const logFile = options.logFile ?? findLatestLogFile(options.agentRoot);
  const storeDbPath = join(options.agentRoot, ".adk", "bot", "logs", "logs.db");
  let allEntries = [];
  if (existsSync(storeDbPath)) {
    const store = new SqliteLogStore(options.agentRoot);
    allEntries = store.getRecentLogs(ALL_LOG_LIMIT);
    store.close();
  }
  const logs = filterLogEntries(allEntries, {
    ...options.level ? { level: options.level } : {},
    ...options.since ? { since: options.since } : {},
    limit: options.limit ?? 50
  }).map(serializeEntry);
  const findings = dedupeFindings(allEntries);
  const errors = findings.filter((finding) => finding.level === "error");
  const warnings = findings.filter((finding) => finding.level === "warning");
  const logBuild = detectBuildStatus(allEntries);
  const adkDevConsole = await findAdkDevConsole(options.agentRoot);
  const healthStatus = normalizeHealthStatus(adkDevConsole?.health.status);
  return {
    logFile,
    health: {
      running: adkDevConsole !== null,
      status: healthStatus,
      port: adkDevConsole?.port ?? null,
      url: adkDevConsole?.url ?? null,
      agentPath: adkDevConsole?.health.agentPath ?? null,
      adkVersion: adkDevConsole?.health.adkVersion ?? null,
      startTime: adkDevConsole?.health.startTime ?? null,
      uptime: adkDevConsole?.health.uptime ?? null
    },
    buildStatus: mergeBuildStatus(healthStatus, logBuild.status),
    ...logBuild.lastBuild ? { lastBuild: logBuild.lastBuild } : {},
    counts: {
      totalEntries: allEntries.length,
      errorCount: errors.length,
      warningCount: warnings.length,
      findingCount: findings.length
    },
    findings,
    errors,
    warnings,
    logs
  };
}
// src/commands/adk-logs.ts
function logStoreDbPath(agentRoot) {
  return join2(agentRoot, ".adk", "bot", "logs", "logs.db");
}
function isDevServerLikelyRunning(agentRoot) {
  const dbPath = logStoreDbPath(agentRoot);
  let newest = 0;
  for (const candidate of [dbPath, `${dbPath}-wal`]) {
    try {
      newest = Math.max(newest, statSync(candidate).mtime.getTime());
    } catch {}
  }
  return newest > 0 && Date.now() - newest < 30000;
}
function toResultJson(entry) {
  const { raw: _raw, id: _id, ...rest } = entry;
  return rest;
}
async function adkLogs(tokens, options) {
  const logger = createCliLogger({ format: options?.format });
  if (options.summary) {
    if (options.follow) {
      throw new AdkError({
        code: "INVALID_FLAGS",
        message: "The --summary flag cannot be used with --follow.",
        expected: true
      });
    }
    if (options.format !== "json") {
      throw new AdkError({
        code: "INVALID_FLAGS",
        message: "The --summary flag requires --format json.",
        expected: true
      });
    }
  } else {
    ensureJsonOnlyFormat(options.format);
  }
  const agentRoot = await findAgentRootOrFail(process.cwd());
  const { options: parsed, errors } = parseFilterTokens(tokens);
  if (errors.length > 0) {
    throw new AdkError({
      code: "INVALID_FLAGS",
      message: errors.map((e) => e.suggestion ? `${e.message} (${e.suggestion})` : e.message).join("; "),
      expected: true
    });
  }
  if (options.summary) {
    const summary = await buildLogSummary({
      agentRoot,
      level: parsed.level,
      since: parsed.since,
      limit: parsed.limit
    });
    logger.info("Log summary").result(summary);
    return;
  }
  if (!existsSync2(logStoreDbPath(agentRoot))) {
    logger.warn("No logs found. Run `adk dev` to start generating logs.");
    process.exit(0);
  }
  const isFollow = options.follow ?? false;
  const serverRunning = isDevServerLikelyRunning(agentRoot);
  if (!serverRunning) {
    if (isFollow) {
      logger.warn("Dev server is not running. Nothing to follow.");
      process.exit(0);
    }
    logger.warn(`Dev server is not running. Showing logs from last session.
`);
  }
  const store = new SqliteLogStore(agentRoot);
  const query = { level: parsed.level, since: parsed.since };
  if (isFollow) {
    const cap = parsed.limit;
    let printed = 0;
    const printEntry = (entry) => {
      if (cap && printed >= cap)
        return;
      logger.info(formatLogEntry(entry)).result(toResultJson(entry));
      printed++;
    };
    const existing = store.queryLogs({ ...query, limit: cap ?? 999999 });
    for (const entry of existing) {
      printEntry(entry);
    }
    if (cap && printed >= cap) {
      store.close();
      return;
    }
    const handle = createLogFollower(store, query);
    const cleanup = () => {
      handle.stop();
      store.close();
      process.exit(0);
    };
    process.on("SIGINT", cleanup);
    process.on("SIGTERM", cleanup);
    for await (const entry of handle.entries) {
      printEntry(entry);
      if (cap && printed >= cap) {
        cleanup();
        break;
      }
    }
  } else {
    const entries = store.queryLogs({ ...query, limit: parsed.limit ?? 50 });
    store.close();
    if (entries.length === 0) {
      logger.info("No log entries match the given filters.");
      return;
    }
    for (const entry of entries) {
      logger.info(formatLogEntry(entry)).result(toResultJson(entry));
    }
  }
}
export {
  adkLogs
};
