Source code for toolscore.reports.json_report

"""JSON report generation."""

import json
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from toolscore.core import EvaluationResult


def _serialize_tool_call(call: Any) -> dict[str, Any]:
    """Serialize a ToolCall to JSON-compatible dict.

    Args:
        call: ToolCall to serialize.

    Returns:
        Dictionary representation.
    """
    return {
        "tool": call.tool,
        "args": call.args,
        "result": call.result,
        "timestamp": call.timestamp,
        "duration": call.duration,
        "cost": call.cost,
        "metadata": call.metadata,
    }


[docs] def generate_json_report( result: "EvaluationResult", output_path: str | Path = "toolscore.json", ) -> Path: """Generate JSON report from evaluation result. Args: result: Evaluation result to report. output_path: Path to save the JSON report. Returns: Path to the generated report file. """ path = Path(output_path) report = { "timestamp": datetime.now().isoformat(), "summary": { "gold_calls_count": len(result.gold_calls), "trace_calls_count": len(result.trace_calls), "score": result.score, "grade": result.grade, "weights": dict(result._weights), "required_call_recall": result.required_call_recall, "failed_calls": result.metrics.get("efficiency_metrics", {}).get("error_count", 0), "policy_violations": len(result.policy_violations), "secrets": (result.metrics.get("security_metrics") or {}).get("secret_count", 0), }, "metrics": result.metrics, "gold_calls": [_serialize_tool_call(call) for call in result.gold_calls], "trace_calls": [_serialize_tool_call(call) for call in result.trace_calls], } with path.open("w", encoding="utf-8") as f: json.dump(report, f, indent=2) return path