1use serde::{Deserialize, Serialize};
4
5pub const ATIF_VERSION: &str = "ATIF-v1.7";
7
8pub const SUPPORTED_VERSIONS: &[&str] = &[
10 "ATIF-v1.0",
11 "ATIF-v1.1",
12 "ATIF-v1.2",
13 "ATIF-v1.3",
14 "ATIF-v1.4",
15 "ATIF-v1.5",
16 "ATIF-v1.6",
17 "ATIF-v1.7",
18];
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
22#[serde(rename_all = "lowercase")]
23#[non_exhaustive]
24pub enum Source {
25 System,
27 User,
29 Agent,
31}
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35pub struct Trajectory {
36 pub schema_version: String,
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub session_id: Option<String>,
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub trajectory_id: Option<String>,
44 pub agent: Agent,
46 pub steps: Vec<Step>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub notes: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub final_metrics: Option<FinalMetrics>,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub continued_trajectory_ref: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub subagent_trajectories: Option<Vec<Trajectory>>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub extra: Option<serde_json::Value>,
63}
64
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct Agent {
68 pub name: String,
70 pub version: String,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub model_name: Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub tool_definitions: Option<Vec<serde_json::Map<String, serde_json::Value>>>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub extra: Option<serde_json::Value>,
81}
82
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85pub struct Step {
86 pub step_id: u64,
88 #[serde(skip_serializing_if = "Option::is_none")]
90 pub timestamp: Option<String>,
91 pub source: Source,
93 pub message: serde_json::Value,
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub reasoning_effort: Option<ReasoningEffort>,
98 #[serde(skip_serializing_if = "Option::is_none")]
100 pub reasoning_content: Option<String>,
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub model_name: Option<String>,
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub tool_calls: Option<Vec<ToolCall>>,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub observation: Option<Observation>,
110 #[serde(skip_serializing_if = "Option::is_none")]
112 pub metrics: Option<Metrics>,
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub is_copied_context: Option<bool>,
116 #[serde(skip_serializing_if = "Option::is_none")]
118 pub llm_call_count: Option<u64>,
119 #[serde(skip_serializing_if = "Option::is_none")]
121 pub extra: Option<serde_json::Value>,
122}
123
124#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126#[serde(untagged)]
127#[non_exhaustive]
128pub enum ReasoningEffort {
129 Text(String),
131 Numeric(f64),
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137pub struct ToolCall {
138 pub tool_call_id: String,
140 pub function_name: String,
142 pub arguments: serde_json::Value,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub extra: Option<serde_json::Value>,
147}
148
149#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub struct Observation {
152 pub results: Vec<ObservationResult>,
154}
155
156#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
158pub struct ObservationResult {
159 #[serde(skip_serializing_if = "Option::is_none")]
162 pub source_call_id: Option<String>,
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub content: Option<serde_json::Value>,
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub subagent_trajectory_ref: Option<Vec<SubagentTrajectoryRef>>,
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub extra: Option<serde_json::Value>,
172}
173
174#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
176pub struct SubagentTrajectoryRef {
177 #[serde(skip_serializing_if = "Option::is_none")]
179 pub trajectory_id: Option<String>,
180 #[serde(skip_serializing_if = "Option::is_none")]
182 pub session_id: Option<String>,
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub trajectory_path: Option<String>,
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub extra: Option<serde_json::Value>,
189}
190
191#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
194pub struct Metrics {
195 #[serde(skip_serializing_if = "Option::is_none")]
197 pub prompt_tokens: Option<u64>,
198 #[serde(skip_serializing_if = "Option::is_none")]
200 pub completion_tokens: Option<u64>,
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub cached_tokens: Option<u64>,
204 #[serde(skip_serializing_if = "Option::is_none")]
206 pub cost_usd: Option<f64>,
207 #[serde(skip_serializing_if = "Option::is_none")]
209 pub logprobs: Option<Vec<f64>>,
210 #[serde(skip_serializing_if = "Option::is_none")]
212 pub completion_token_ids: Option<Vec<u64>>,
213 #[serde(skip_serializing_if = "Option::is_none")]
215 pub prompt_token_ids: Option<Vec<u64>>,
216 #[serde(skip_serializing_if = "Option::is_none")]
218 pub extra: Option<serde_json::Value>,
219}
220
221#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
223pub struct FinalMetrics {
224 #[serde(skip_serializing_if = "Option::is_none")]
226 pub total_prompt_tokens: Option<u64>,
227 #[serde(skip_serializing_if = "Option::is_none")]
229 pub total_completion_tokens: Option<u64>,
230 #[serde(skip_serializing_if = "Option::is_none")]
232 pub total_cached_tokens: Option<u64>,
233 #[serde(skip_serializing_if = "Option::is_none")]
235 pub total_cost_usd: Option<f64>,
236 #[serde(skip_serializing_if = "Option::is_none")]
238 pub total_steps: Option<u64>,
239 #[serde(skip_serializing_if = "Option::is_none")]
241 pub extra: Option<serde_json::Value>,
242}