agent_sdk_eval/
run_report.rs1use serde::{Deserialize, Serialize};
4
5use agent_sdk_core::{AgentError, RunId, RunTrace};
6
7use crate::{CostPolicy, CostReport, UsageReport};
8
9#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
10pub struct RunReportLimitations {
12 pub items: Vec<String>,
14}
15
16impl RunReportLimitations {
17 pub fn from_parts(usage: &UsageReport, cost: Option<&CostReport>) -> Self {
19 let mut items = usage.limitations.clone();
20 if let Some(cost) = cost {
21 items.extend(cost.limitations.clone());
22 } else {
23 items.push("cost report was not requested".to_string());
24 }
25 items.sort();
26 items.dedup();
27 Self { items }
28 }
29}
30
31#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
32pub struct RunReport {
34 pub run_id: RunId,
36 pub usage: UsageReport,
38 pub cost: Option<CostReport>,
40 pub limitations: RunReportLimitations,
42}
43
44impl RunReport {
45 pub fn from_run_trace(
47 trace: &RunTrace,
48 cost_policy: Option<&dyn CostPolicy>,
49 ) -> Result<Self, AgentError> {
50 let run_id = trace.run_id.clone().ok_or_else(|| {
51 AgentError::contract_violation("run report requires a run trace with run_id")
52 })?;
53 let usage = UsageReport::from_run_trace(trace)?;
54 let cost = cost_policy.map(|policy| policy.estimate_cost(&usage));
55 let limitations = RunReportLimitations::from_parts(&usage, cost.as_ref());
56 Ok(Self {
57 run_id,
58 usage,
59 cost,
60 limitations,
61 })
62 }
63}