1use super::tools::{CallToolResult, ToolCall};
7use serde::{Deserialize, Serialize};
8use uuid::Uuid;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct AiResponse {
12 pub request_id: Uuid,
13 pub content: String,
14 pub provider: String,
15 pub model: String,
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub tokens_used: Option<u32>,
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub input_tokens: Option<u32>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub output_tokens: Option<u32>,
22 pub latency_ms: u64,
23 #[serde(default, skip_serializing_if = "Vec::is_empty")]
24 pub tool_calls: Vec<ToolCall>,
25 #[serde(default, skip_serializing_if = "Vec::is_empty")]
26 pub tool_results: Vec<CallToolResult>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub finish_reason: Option<String>,
29 pub cache_hit: bool,
30 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub cache_read_tokens: Option<u32>,
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub cache_creation_tokens: Option<u32>,
34 #[serde(default, skip_serializing_if = "Option::is_none")]
35 pub reasoning_tokens: Option<u32>,
36 pub is_streaming: bool,
37}
38
39impl Default for AiResponse {
40 fn default() -> Self {
41 Self {
42 request_id: Uuid::nil(),
43 content: String::new(),
44 provider: String::new(),
45 model: String::new(),
46 tokens_used: None,
47 input_tokens: None,
48 output_tokens: None,
49 latency_ms: 0,
50 tool_calls: Vec::new(),
51 tool_results: Vec::new(),
52 finish_reason: None,
53 cache_hit: false,
54 cache_read_tokens: None,
55 cache_creation_tokens: None,
56 reasoning_tokens: None,
57 is_streaming: false,
58 }
59 }
60}
61
62impl AiResponse {
63 pub fn new(request_id: Uuid, content: String, provider: String, model: String) -> Self {
64 Self {
65 request_id,
66 content,
67 provider,
68 model,
69 ..Default::default()
70 }
71 }
72
73 pub const fn with_tokens(mut self, tokens_used: u32) -> Self {
74 self.tokens_used = Some(tokens_used);
75 self
76 }
77
78 pub const fn with_latency(mut self, latency_ms: u64) -> Self {
79 self.latency_ms = latency_ms;
80 self
81 }
82
83 pub const fn with_streaming(mut self, is_streaming: bool) -> Self {
84 self.is_streaming = is_streaming;
85 self
86 }
87
88 pub fn with_tool_calls(mut self, tool_calls: Vec<ToolCall>) -> Self {
89 self.tool_calls = tool_calls;
90 self
91 }
92
93 pub fn with_tool_results(mut self, tool_results: Vec<CallToolResult>) -> Self {
94 self.tool_results = tool_results;
95 self
96 }
97
98 pub const fn has_tool_calls(&self) -> bool {
99 !self.tool_calls.is_empty()
100 }
101
102 pub const fn has_tool_results(&self) -> bool {
103 !self.tool_results.is_empty()
104 }
105}
106
107#[derive(Debug, Clone)]
108pub enum StreamChunk {
109 Text(String),
110 Usage {
111 input_tokens: Option<u32>,
112 output_tokens: Option<u32>,
113 tokens_used: Option<u32>,
114 cache_read_tokens: Option<u32>,
115 cache_creation_tokens: Option<u32>,
116 reasoning_tokens: Option<u32>,
117 finish_reason: Option<String>,
118 },
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct WebSource {
123 pub title: String,
124 pub uri: String,
125 pub relevance: f32,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct UrlMetadata {
130 pub retrieved_url: String,
131 pub url_retrieval_status: String,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct SearchGroundedResponse {
136 pub content: String,
137 pub sources: Vec<WebSource>,
138 pub confidence_scores: Vec<f32>,
139 pub web_search_queries: Vec<String>,
140 #[serde(default, skip_serializing_if = "Option::is_none")]
141 pub url_context_metadata: Option<Vec<UrlMetadata>>,
142 #[serde(default, skip_serializing_if = "Option::is_none")]
143 pub tokens_used: Option<u32>,
144 pub latency_ms: u64,
145 #[serde(default, skip_serializing_if = "Option::is_none")]
146 pub finish_reason: Option<String>,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
148 pub safety_ratings: Option<Vec<serde_json::Value>>,
149}