Skip to main content

atomr_agents_coding_cli_core/
result.rs

1//! Terminal value produced by a headless run.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::event::FinishReason;
7use crate::request::CliRunId;
8use crate::vendor::CliVendorKind;
9
10/// One tool the CLI invoked during the run.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ToolCallRecord {
13    pub tool_call_id: String,
14    pub name: String,
15    pub input: serde_json::Value,
16    pub output: Option<serde_json::Value>,
17    pub error: Option<String>,
18    pub started_at: DateTime<Utc>,
19    pub finished_at: Option<DateTime<Utc>>,
20}
21
22/// Token + cost totals.
23#[derive(Debug, Clone, Default, Serialize, Deserialize)]
24pub struct UsageSummary {
25    pub input_tokens: u64,
26    pub output_tokens: u64,
27    pub cost_usd: Option<f64>,
28}
29
30impl UsageSummary {
31    pub fn add(&mut self, input_tokens: u64, output_tokens: u64, cost_usd: Option<f64>) {
32        self.input_tokens += input_tokens;
33        self.output_tokens += output_tokens;
34        if let Some(c) = cost_usd {
35            *self.cost_usd.get_or_insert(0.0) += c;
36        }
37    }
38}
39
40/// Final shape of a headless run.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct CliResult {
43    pub run_id: CliRunId,
44    pub vendor: CliVendorKind,
45
46    /// Concatenation of all `AssistantTextDelta` events.
47    pub final_text: String,
48
49    /// Optional structured payload if the vendor produced one
50    /// (`claude --json-schema`, etc.).
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub structured_output: Option<serde_json::Value>,
53
54    pub tool_calls: Vec<ToolCallRecord>,
55    pub usage: UsageSummary,
56
57    pub finish_reason: FinishReason,
58    pub exit_code: Option<i32>,
59
60    pub started_at: DateTime<Utc>,
61    pub ended_at: Option<DateTime<Utc>>,
62}
63
64impl CliResult {
65    pub fn new(run_id: CliRunId, vendor: CliVendorKind) -> Self {
66        Self {
67            run_id,
68            vendor,
69            final_text: String::new(),
70            structured_output: None,
71            tool_calls: Vec::new(),
72            usage: UsageSummary::default(),
73            finish_reason: FinishReason::Completed,
74            exit_code: None,
75            started_at: Utc::now(),
76            ended_at: None,
77        }
78    }
79}