1use std::collections::BTreeMap;
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use ts_rs::TS;
7
8pub type UserInput = Value;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
11#[serde(rename_all = "camelCase")]
12pub struct TurnStartParams {
13 pub thread_id: String,
14 #[serde(default, deserialize_with = "deserialize_input_items")]
15 pub input: Vec<UserInput>,
16 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
17 pub metadata: BTreeMap<String, Value>,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
21#[serde(rename_all = "camelCase", deny_unknown_fields)]
22pub struct TurnResumeParams {
23 pub thread_id: String,
24 pub turn_id: String,
25 pub checkpoint_key: String,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
29#[serde(rename_all = "camelCase")]
30pub struct TurnInterruptParams {
31 pub thread_id: String,
32 #[serde(default)]
33 pub expected_turn_id: String,
34 #[serde(default, skip_serializing_if = "String::is_empty")]
35 pub reason: String,
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
39#[serde(rename_all = "camelCase")]
40pub struct TurnSteerParams {
41 pub thread_id: String,
42 #[serde(default)]
43 pub expected_turn_id: String,
44 #[serde(default, deserialize_with = "deserialize_input_items")]
45 pub input: Vec<UserInput>,
46}
47
48pub type TurnFollowUpParams = TurnSteerParams;
49
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
51#[serde(rename_all = "camelCase")]
52pub struct TurnStartResponse {
53 pub thread_id: String,
54 pub turn_id: String,
55 pub status: TurnStatus,
56}
57
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
59#[serde(rename_all = "camelCase", deny_unknown_fields)]
60pub struct TurnResumeResponse {
61 pub thread_id: String,
62 pub turn_id: String,
63 pub run_id: String,
64 pub status: TurnStatus,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub final_output: Option<String>,
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub completion_reason: Option<String>,
69 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub completion_tool_name: Option<String>,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub partial_output: Option<String>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 pub checkpoint: Option<CheckpointSummary>,
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub interruption: Option<InterruptionSummary>,
77 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub error: Option<String>,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
82#[serde(rename_all = "camelCase")]
83pub struct TurnInterruptResponse {
84 pub thread_id: String,
85 pub turn_id: String,
86 pub cancelled: bool,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
90#[serde(rename_all = "camelCase")]
91pub struct TurnControlResponse {
92 pub thread_id: String,
93 pub turn_id: String,
94 pub queued: bool,
95}
96
97pub type TurnSteerResponse = TurnControlResponse;
98pub type TurnFollowUpResponse = TurnControlResponse;
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
101#[serde(rename_all = "camelCase")]
102pub struct TurnStartedParams {
103 pub thread_id: String,
104 pub turn_id: String,
105 #[serde(default, skip_serializing_if = "Option::is_none")]
106 pub run_id: Option<String>,
107 #[serde(default, skip_serializing_if = "Option::is_none")]
108 pub status: Option<TurnStatus>,
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
112#[serde(rename_all = "camelCase")]
113pub struct TurnCompletedParams {
114 pub thread_id: String,
115 pub turn_id: String,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
117 pub run_id: Option<String>,
118 pub status: TurnStatus,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub final_output: Option<String>,
121 #[serde(default, skip_serializing_if = "Option::is_none")]
122 pub completion_reason: Option<String>,
123 #[serde(default, skip_serializing_if = "Option::is_none")]
124 pub completion_tool_name: Option<String>,
125 #[serde(default, skip_serializing_if = "Option::is_none")]
126 pub partial_output: Option<String>,
127 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub error: Option<String>,
129 #[serde(default, skip_serializing_if = "Option::is_none")]
130 pub token_usage: Option<AppTokenUsage>,
131 #[serde(default, skip_serializing_if = "Option::is_none")]
132 pub budget_usage: Option<BTreeMap<String, Value>>,
133 #[serde(default, skip_serializing_if = "Option::is_none")]
134 pub budget_exhaustion: Option<BTreeMap<String, Value>>,
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub checkpoint: Option<CheckpointSummary>,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub interruption: Option<InterruptionSummary>,
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
142#[serde(rename_all = "camelCase", deny_unknown_fields)]
143pub struct CheckpointSummary {
144 pub key: String,
145 pub resume_attempt: u64,
146 pub cycle_index: u64,
147 pub status: CheckpointSummaryStatus,
148 pub terminal_acknowledged: bool,
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
152#[serde(rename_all = "snake_case")]
153pub enum CheckpointSummaryStatus {
154 Pending,
155 Running,
156 WaitUser,
157 Completed,
158 Failed,
159 MaxCycles,
160 ReconciliationRequired,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
164#[serde(rename_all = "camelCase", deny_unknown_fields)]
165pub struct InterruptionSummary {
166 pub reason: String,
167 pub operation_id: String,
168 pub operation_kind: InterruptionOperationKind,
169 pub cycle_index: u64,
170 pub risk: String,
171 pub idempotency_support: InterruptionIdempotencySupport,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
175#[serde(rename_all = "snake_case")]
176pub enum InterruptionOperationKind {
177 Model,
178 Tool,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
182#[serde(rename_all = "snake_case")]
183pub enum InterruptionIdempotencySupport {
184 Supported,
185 Unsupported,
186 Unknown,
187}
188
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
190#[serde(rename_all = "camelCase")]
191pub struct AppTurn {
192 pub turn_id: String,
193 pub thread_id: String,
194 #[serde(default)]
195 pub run_id: Option<String>,
196 pub status: TurnStatus,
197 pub started_at: f64,
198 #[serde(default)]
199 pub completed_at: Option<f64>,
200 #[serde(default, deserialize_with = "deserialize_input_items")]
201 pub input: Vec<UserInput>,
202 #[serde(default)]
203 pub result: BTreeMap<String, Value>,
204}
205
206fn deserialize_input_items<'de, D>(deserializer: D) -> Result<Vec<UserInput>, D::Error>
207where
208 D: serde::Deserializer<'de>,
209{
210 let items = Vec::<Value>::deserialize(deserializer)?;
211 if items.iter().all(Value::is_object) {
212 Ok(items)
213 } else {
214 Err(serde::de::Error::custom("input must be a list of objects"))
215 }
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
219#[serde(rename_all = "camelCase")]
220pub enum TurnStatus {
221 Queued,
222 Running,
223 Completed,
224 Failed,
225 Interrupted,
226}
227
228#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
229pub struct AppTokenUsage {
230 pub prompt_tokens: u64,
231 pub completion_tokens: u64,
232 pub total_tokens: u64,
233 pub cached_tokens: u64,
234 pub reasoning_tokens: u64,
235 pub input_tokens: u64,
236 pub output_tokens: u64,
237 pub cache_creation_tokens: u64,
238 pub cache_usage: AppCacheUsage,
239}
240
241#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
242pub struct AppCacheUsage {
243 pub status: String,
244 pub read_tokens: Option<u64>,
245 pub write_tokens: Option<u64>,
246 pub uncached_input_tokens: Option<u64>,
247 pub source: Option<String>,
248}