assay_core/agent_assertions/
mod.rs1pub mod matchers;
2pub mod model;
3
4use crate::errors::diagnostic::Diagnostic;
5use crate::storage::Store;
6
7pub struct EpisodeGraph {
8 pub episode_id: String,
9 pub steps: Vec<crate::storage::rows::StepRow>,
10 pub tool_calls: Vec<crate::storage::rows::ToolCallRow>,
11}
12
13pub fn verify_assertions(
14 store: &Store,
15 run_id: i64,
16 test_id: &str,
17 assertions: &[model::TraceAssertion],
18) -> anyhow::Result<Vec<Diagnostic>> {
19 let graph_res = store.get_episode_graph(run_id, test_id);
20 match graph_res {
21 Ok(graph) => matchers::evaluate(&graph, assertions),
22 Err(e) => {
23 let is_unit_test = assertions.iter().all(|a| match a {
27 model::TraceAssertion::ArgsValid { test_args, .. } => test_args.is_some(),
28 model::TraceAssertion::SequenceValid {
29 test_trace,
30 test_trace_raw,
31 ..
32 } => test_trace.is_some() || test_trace_raw.is_some(),
33 model::TraceAssertion::ToolBlocklist {
34 test_tool_calls, ..
35 } => test_tool_calls.is_some(),
36 _ => false,
37 });
38
39 if is_unit_test {
40 let dummy = EpisodeGraph {
42 episode_id: "unit_test_mock".into(),
43 steps: vec![],
44 tool_calls: vec![],
45 };
46 return matchers::evaluate(&dummy, assertions);
47 }
48
49 if e.to_string().contains("E_TRACE_EPISODE_MISSING") {
53 match store.get_latest_episode_graph_by_test_id(test_id) {
54 Ok(latest_graph) => return matchers::evaluate(&latest_graph, assertions),
55 Err(fallback_err) => {
56 return Err(anyhow::anyhow!("E_TRACE_EPISODE_MISSING: Primary query failed ({}), Fallback failed: {}", e, fallback_err));
57 }
58 }
59 }
60
61 Err(e)
64 }
65 }
66}