import { defineCommand, useLogger } from '@kb-labs/sdk';
import { loadTrace, formatTraceLoadError } from '@kb-labs/agent-tracing';

// src/cli/commands/trace-stats.ts

// src/cli/commands/trace-event-normalizer.ts
function normalizeTraceEvents(events) {
  const out = [];
  let currentIteration = 0;
  for (const raw of events) {
    const type = String(raw.type ?? "");
    const data = getEventData(raw);
    const explicitIteration = asNumber(raw.iteration) ?? asNumber(data.iteration);
    if (type === "iteration:start") {
      currentIteration = explicitIteration ?? Math.max(1, currentIteration + 1);
    }
    const iteration = explicitIteration ?? currentIteration;
    out.push({ raw, type, data, iteration });
  }
  return out;
}
function getEventData(event) {
  const data = event.data;
  if (data && typeof data === "object") {
    return data;
  }
  return {};
}
function asNumber(value) {
  if (typeof value === "number" && Number.isFinite(value)) {
    return value;
  }
  if (typeof value === "string") {
    const n = Number(value);
    if (Number.isFinite(n)) {
      return n;
    }
  }
  return void 0;
}

// src/cli/commands/trace-stats.ts
var trace_stats_default = defineCommand({
  id: "trace:stats",
  description: "Show trace statistics with cost and performance metrics",
  handler: {
    async execute(ctx, input) {
      const logger = useLogger();
      const flags = typeof input === "object" && input !== null && "flags" in input ? input.flags : input;
      const taskId = flags["task-id"] ?? flags.taskId;
      try {
        const loaded = await loadTrace(taskId);
        if (!loaded.ok) {
          const code = loaded.error.kind === "invalid_task_id" ? "INVALID_TASK_ID" : loaded.error.kind === "not_found" ? "TRACE_NOT_FOUND" : loaded.error.kind === "too_large" ? "FILE_TOO_LARGE" : "CORRUPTED_TRACE";
          const err = error(code, formatTraceLoadError(loaded.error));
          ctx.ui.write(JSON.stringify(err, null, 2) + "\n");
          return { exitCode: 1, response: err };
        }
        const { events } = loaded;
        const stats = calculateStats(events, taskId);
        const response = {
          success: true,
          command: "trace:stats",
          taskId: taskId ?? "",
          data: stats,
          summary: {
            message: `${stats.iterations.total} iterations, ${stats.llm.calls} LLM calls, $${stats.cost.total.toFixed(4)} cost`,
            severity: stats.errors > 0 ? "warning" : "info",
            actionable: stats.errors > 5
          }
        };
        if (flags.json) {
          ctx.ui.write(JSON.stringify(response, null, 2) + "\n");
        } else {
          printHumanReadable(ctx, stats);
        }
        return { exitCode: 0, response };
      } catch (err) {
        logger.error("trace:stats error:", err instanceof Error ? err : void 0);
        const errResponse = error("IO_ERROR", err instanceof Error ? err.message : String(err));
        ctx.ui.write(JSON.stringify(errResponse, null, 2) + "\n");
        return { exitCode: 1, response: errResponse };
      }
    }
  }
});
function calculateStats(events, taskId) {
  const normalized = normalizeTraceEvents(events);
  const iterationSet = /* @__PURE__ */ new Set();
  for (const e of normalized) {
    if (e.iteration > 0) {
      iterationSet.add(e.iteration);
    }
  }
  const llmStartEvents = normalized.filter((e) => e.type === "llm:start" || e.type === "llm:call" || e.type === "llm_call");
  const llmEndEvents = normalized.filter((e) => e.type === "llm:end" || e.type === "llm:call");
  const toolEndEvents = normalized.filter((e) => e.type === "tool:end" || e.type === "tool:execution" || e.type === "tool_result");
  const errorEvents = normalized.filter((e) => e.type === "error:captured" || e.type === "agent:error" || e.type === "tool:error");
  const inputTokens = llmEndEvents.reduce((sum, e) => {
    const tokens = e.raw.response?.usage?.inputTokens || 0;
    return sum + tokens;
  }, 0);
  const outputTokens = llmEndEvents.reduce((sum, e) => {
    const tokens = e.raw.response?.usage?.outputTokens || 0;
    return sum + tokens;
  }, 0);
  const legacyTotalTokens = llmEndEvents.reduce((sum, e) => {
    const tokens = e.data.tokensUsed || 0;
    return sum + tokens;
  }, 0);
  const totalCost = llmEndEvents.reduce((sum, e) => {
    const cost = e.raw.cost?.totalCost || 0;
    return sum + cost;
  }, 0);
  const toolCounts = {};
  let successfulTools = 0;
  let failedTools = 0;
  for (const tool of toolEndEvents) {
    const toolName = tool.raw.tool?.name || tool.data.toolName || "unknown";
    toolCounts[toolName] = (toolCounts[toolName] || 0) + 1;
    const success = tool.raw.output?.success ?? tool.data.success ?? true;
    if (success) {
      successfulTools++;
    } else {
      failedTools++;
    }
  }
  const firstEvent = events[0];
  const lastEvent = events[events.length - 1];
  const startedAt = firstEvent?.timestamp || (/* @__PURE__ */ new Date()).toISOString();
  const completedAt = lastEvent?.timestamp || (/* @__PURE__ */ new Date()).toISOString();
  const totalDurationMs = new Date(completedAt).getTime() - new Date(startedAt).getTime();
  return {
    taskId: taskId || "unknown",
    status: errorEvents.length > 0 ? "failed" : "success",
    iterations: {
      total: iterationSet.size,
      completed: iterationSet.size
    },
    llm: {
      calls: llmStartEvents.length,
      inputTokens,
      outputTokens,
      // Use explicit tokens if available, otherwise fall back to legacy total
      totalTokens: inputTokens + outputTokens || legacyTotalTokens
    },
    tools: {
      totalCalls: toolEndEvents.length,
      byTool: toolCounts,
      successful: successfulTools,
      failed: failedTools
    },
    timing: {
      startedAt,
      completedAt,
      totalDurationMs,
      durationFormatted: formatDuration(totalDurationMs)
    },
    cost: {
      total: totalCost,
      currency: "USD"
    },
    errors: errorEvents.length
  };
}
function formatDuration(ms) {
  const seconds = Math.floor(ms / 1e3);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  if (hours > 0) {
    return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
  }
  if (minutes > 0) {
    return `${minutes}m ${seconds % 60}s`;
  }
  return `${seconds}s`;
}
function printHumanReadable(ctx, stats) {
  ctx.ui.write("\n");
  ctx.ui.write("\u{1F4CA} Trace Statistics\n");
  ctx.ui.write("\n");
  ctx.ui.write(`Status: ${stats.status === "success" ? "\u2705 Success" : "\u274C Failed"}
`);
  ctx.ui.write(`Iterations: ${stats.iterations.total}
`);
  ctx.ui.write("\n");
  ctx.ui.write("\u{1F916} LLM Usage:\n");
  ctx.ui.write(`  Calls: ${stats.llm.calls}
`);
  ctx.ui.write(`  Input tokens: ${stats.llm.inputTokens.toLocaleString()}
`);
  ctx.ui.write(`  Output tokens: ${stats.llm.outputTokens.toLocaleString()}
`);
  ctx.ui.write(`  Total tokens: ${stats.llm.totalTokens.toLocaleString()}
`);
  ctx.ui.write("\n");
  ctx.ui.write("\u{1F527} Tool Usage:\n");
  ctx.ui.write(`  Total calls: ${stats.tools.totalCalls}
`);
  ctx.ui.write(`  Successful: ${stats.tools.successful}
`);
  ctx.ui.write(`  Failed: ${stats.tools.failed}
`);
  ctx.ui.write("  By tool:\n");
  for (const [tool, count] of Object.entries(stats.tools.byTool)) {
    ctx.ui.write(`    ${tool}: ${count}
`);
  }
  ctx.ui.write("\n");
  ctx.ui.write("\u23F1\uFE0F  Timing:\n");
  ctx.ui.write(`  Started: ${stats.timing.startedAt}
`);
  ctx.ui.write(`  Completed: ${stats.timing.completedAt}
`);
  ctx.ui.write(`  Duration: ${stats.timing.durationFormatted}
`);
  ctx.ui.write("\n");
  ctx.ui.write("\u{1F4B0} Cost:\n");
  ctx.ui.write(`  Total: $${stats.cost.total.toFixed(4)} ${stats.cost.currency}
`);
  ctx.ui.write("\n");
  if (stats.errors > 0) {
    ctx.ui.write(`\u26A0\uFE0F  Errors: ${stats.errors}
`);
    ctx.ui.write("\n");
  }
}
function error(code, message) {
  return {
    success: false,
    command: "trace:stats",
    taskId: "",
    error: {
      code,
      message
    },
    summary: {
      message,
      severity: "error",
      actionable: true
    }
  };
}

export { trace_stats_default as default };
//# sourceMappingURL=trace-stats.js.map
//# sourceMappingURL=trace-stats.js.map