"""CLI commands for report generation.""" from pathlib import Path from typing import Optional import typer from agenteval.evaluation.report import generate_report as build_report from agenteval.evaluation.report import save_report from agenteval.evaluation.report_render import render_html, render_json from agenteval.storage.repository import RunRepository from rich.console import Console app = typer.Typer(help="评测报告") console = Console() @app.command("show", help="查看报告") def show_report( run_id: str, fmt: str = typer.Option("json", "--format", help="输出格式: json | html"), ) -> None: run = RunRepository().get(run_id) if not run: console.print(f"评测记录不存在: {run_id}", style="red") raise typer.Exit(1) if fmt == "json": console.print(render_json(build_report(run_id))) elif fmt == "html": console.print(render_html(build_report(run_id))) else: console.print(f"不支持的格式: {fmt}", style="red") raise typer.Exit(1) @app.command("generate", help="生成报告并保存到文件") def generate_report( run_id: str, fmt: str = typer.Option("html", "--format", help="输出格式: json | html"), output_dir: Optional[Path] = typer.Option(None, help="输出目录"), ) -> None: run = RunRepository().get(run_id) if not run: console.print(f"评测记录不存在: {run_id}", style="red") raise typer.Exit(1) path = save_report(run_id, fmt=fmt, output_dir=output_dir) console.print(f"报告已保存: {path}") @app.command("compare", help="对比两次评测报告") def compare_reports( run_id_1: str, run_id_2: str, ) -> None: r1 = RunRepository().get(run_id_1) r2 = RunRepository().get(run_id_2) if not r1 or not r2: console.print("评测记录不存在", style="red") raise typer.Exit(1) report1 = build_report(run_id_1) report2 = build_report(run_id_2) console.print(f"对比: {run_id_1} vs {run_id_2}") console.print(f" 用例数: {report1['summary']['total_cases']} -> {report2['summary']['total_cases']}") console.print(f" 通过用例: {report1['summary']['passed_cases']} -> {report2['summary']['passed_cases']}") console.print(f" 通过率: {report1['summary']['pass_rate']:.2%} -> {report2['summary']['pass_rate']:.2%}")