1use crate::{
4 completion::{CompletionError, GetTokenUsage, Usage},
5 message::ReasoningContent,
6 streaming::{RawStreamingChoice, RawStreamingToolCall, ToolCallDeltaContent},
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Clone, Debug, Default, Deserialize, Serialize)]
12pub struct MockResponse {
13 usage: Usage,
14}
15
16impl MockResponse {
17 pub fn new() -> Self {
20 Self {
21 usage: Usage::new(),
22 }
23 }
24
25 pub fn with_usage(usage: Usage) -> Self {
27 Self { usage }
28 }
29
30 pub fn with_total_tokens(total_tokens: u64) -> Self {
32 let mut usage = Usage::new();
33 usage.total_tokens = total_tokens;
34 Self::with_usage(usage)
35 }
36}
37
38impl GetTokenUsage for MockResponse {
39 fn token_usage(&self) -> Usage {
40 self.usage
41 }
42}
43
44#[derive(Clone, Debug)]
46pub enum MockStreamEvent {
47 Text(String),
49 TextStart {
51 additional_params: Option<serde_json::Value>,
52 },
53 TextAdditionalParams(serde_json::Value),
55 ToolCall {
57 id: String,
58 name: String,
59 arguments: serde_json::Value,
60 call_id: Option<String>,
61 },
62 ToolCallDelta {
64 id: String,
65 internal_call_id: String,
66 content: ToolCallDeltaContent,
67 },
68 Reasoning {
70 id: Option<String>,
71 content: ReasoningContent,
72 },
73 ReasoningDelta {
75 id: Option<String>,
76 reasoning: String,
77 },
78 MessageId(String),
80 Unknown(serde_json::Value),
82 FinalResponse(MockResponse),
84 Error(MockError),
86}
87
88use super::completion::MockError;
89
90impl MockStreamEvent {
91 pub fn text(text: impl Into<String>) -> Self {
93 Self::Text(text.into())
94 }
95
96 pub fn text_start(additional_params: Option<serde_json::Value>) -> Self {
98 Self::TextStart { additional_params }
99 }
100
101 pub fn text_additional_params(additional_params: serde_json::Value) -> Self {
103 Self::TextAdditionalParams(additional_params)
104 }
105
106 pub fn tool_call(
108 id: impl Into<String>,
109 name: impl Into<String>,
110 arguments: serde_json::Value,
111 ) -> Self {
112 Self::ToolCall {
113 id: id.into(),
114 name: name.into(),
115 arguments,
116 call_id: None,
117 }
118 }
119
120 pub fn with_call_id(mut self, call_id: impl Into<String>) -> Self {
122 if let Self::ToolCall { call_id: id, .. } = &mut self {
123 *id = Some(call_id.into());
124 }
125 self
126 }
127
128 pub fn tool_call_name_delta(
130 id: impl Into<String>,
131 internal_call_id: impl Into<String>,
132 name: impl Into<String>,
133 ) -> Self {
134 Self::ToolCallDelta {
135 id: id.into(),
136 internal_call_id: internal_call_id.into(),
137 content: ToolCallDeltaContent::Name(name.into()),
138 }
139 }
140
141 pub fn tool_call_arguments_delta(
143 id: impl Into<String>,
144 internal_call_id: impl Into<String>,
145 arguments: impl Into<String>,
146 ) -> Self {
147 Self::ToolCallDelta {
148 id: id.into(),
149 internal_call_id: internal_call_id.into(),
150 content: ToolCallDeltaContent::Delta(arguments.into()),
151 }
152 }
153
154 pub fn reasoning(reasoning: impl Into<String>) -> Self {
156 Self::Reasoning {
157 id: None,
158 content: ReasoningContent::Text {
159 text: reasoning.into(),
160 signature: None,
161 },
162 }
163 }
164
165 pub fn with_reasoning_id(mut self, reasoning_id: impl Into<String>) -> Self {
167 if let Self::Reasoning { id, .. } = &mut self {
168 *id = Some(reasoning_id.into());
169 }
170 self
171 }
172
173 pub fn reasoning_delta(id: Option<impl Into<String>>, reasoning: impl Into<String>) -> Self {
175 Self::ReasoningDelta {
176 id: id.map(Into::into),
177 reasoning: reasoning.into(),
178 }
179 }
180
181 pub fn message_id(id: impl Into<String>) -> Self {
183 Self::MessageId(id.into())
184 }
185
186 pub fn unknown(value: serde_json::Value) -> Self {
188 Self::Unknown(value)
189 }
190
191 pub fn final_response(usage: Usage) -> Self {
193 Self::FinalResponse(MockResponse::with_usage(usage))
194 }
195
196 pub fn final_response_with_default_usage() -> Self {
198 Self::FinalResponse(MockResponse::with_usage(Usage::new()))
199 }
200
201 pub fn final_response_with_total_tokens(total_tokens: u64) -> Self {
203 Self::FinalResponse(MockResponse::with_total_tokens(total_tokens))
204 }
205
206 pub fn error(message: impl Into<String>) -> Self {
208 Self::Error(MockError::provider(message))
209 }
210
211 pub(crate) fn into_raw_choice(
212 self,
213 ) -> Result<RawStreamingChoice<MockResponse>, CompletionError> {
214 match self {
215 Self::Text(text) => Ok(RawStreamingChoice::Message(text)),
216 Self::TextStart { additional_params } => {
217 Ok(RawStreamingChoice::TextStart { additional_params })
218 }
219 Self::TextAdditionalParams(additional_params) => {
220 Ok(RawStreamingChoice::TextAdditionalParams(additional_params))
221 }
222 Self::ToolCall {
223 id,
224 name,
225 arguments,
226 call_id,
227 } => {
228 let mut tool_call = RawStreamingToolCall::new(id, name, arguments);
229 if let Some(call_id) = call_id {
230 tool_call = tool_call.with_call_id(call_id);
231 }
232 Ok(RawStreamingChoice::ToolCall(tool_call))
233 }
234 Self::ToolCallDelta {
235 id,
236 internal_call_id,
237 content,
238 } => Ok(RawStreamingChoice::ToolCallDelta {
239 id,
240 internal_call_id,
241 content,
242 }),
243 Self::Reasoning { id, content } => Ok(RawStreamingChoice::Reasoning { id, content }),
244 Self::ReasoningDelta { id, reasoning } => {
245 Ok(RawStreamingChoice::ReasoningDelta { id, reasoning })
246 }
247 Self::MessageId(id) => Ok(RawStreamingChoice::MessageId(id)),
248 Self::Unknown(value) => Ok(RawStreamingChoice::Unknown(value)),
249 Self::FinalResponse(response) => Ok(RawStreamingChoice::FinalResponse(response)),
250 Self::Error(error) => Err(error.into_completion_error()),
251 }
252 }
253}