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 FinalResponse(MockResponse),
82 Error(MockError),
84}
85
86use super::completion::MockError;
87
88impl MockStreamEvent {
89 pub fn text(text: impl Into<String>) -> Self {
91 Self::Text(text.into())
92 }
93
94 pub fn text_start(additional_params: Option<serde_json::Value>) -> Self {
96 Self::TextStart { additional_params }
97 }
98
99 pub fn text_additional_params(additional_params: serde_json::Value) -> Self {
101 Self::TextAdditionalParams(additional_params)
102 }
103
104 pub fn tool_call(
106 id: impl Into<String>,
107 name: impl Into<String>,
108 arguments: serde_json::Value,
109 ) -> Self {
110 Self::ToolCall {
111 id: id.into(),
112 name: name.into(),
113 arguments,
114 call_id: None,
115 }
116 }
117
118 pub fn with_call_id(mut self, call_id: impl Into<String>) -> Self {
120 if let Self::ToolCall { call_id: id, .. } = &mut self {
121 *id = Some(call_id.into());
122 }
123 self
124 }
125
126 pub fn tool_call_name_delta(
128 id: impl Into<String>,
129 internal_call_id: impl Into<String>,
130 name: impl Into<String>,
131 ) -> Self {
132 Self::ToolCallDelta {
133 id: id.into(),
134 internal_call_id: internal_call_id.into(),
135 content: ToolCallDeltaContent::Name(name.into()),
136 }
137 }
138
139 pub fn tool_call_arguments_delta(
141 id: impl Into<String>,
142 internal_call_id: impl Into<String>,
143 arguments: impl Into<String>,
144 ) -> Self {
145 Self::ToolCallDelta {
146 id: id.into(),
147 internal_call_id: internal_call_id.into(),
148 content: ToolCallDeltaContent::Delta(arguments.into()),
149 }
150 }
151
152 pub fn reasoning(reasoning: impl Into<String>) -> Self {
154 Self::Reasoning {
155 id: None,
156 content: ReasoningContent::Text {
157 text: reasoning.into(),
158 signature: None,
159 },
160 }
161 }
162
163 pub fn with_reasoning_id(mut self, reasoning_id: impl Into<String>) -> Self {
165 if let Self::Reasoning { id, .. } = &mut self {
166 *id = Some(reasoning_id.into());
167 }
168 self
169 }
170
171 pub fn reasoning_delta(id: Option<impl Into<String>>, reasoning: impl Into<String>) -> Self {
173 Self::ReasoningDelta {
174 id: id.map(Into::into),
175 reasoning: reasoning.into(),
176 }
177 }
178
179 pub fn message_id(id: impl Into<String>) -> Self {
181 Self::MessageId(id.into())
182 }
183
184 pub fn final_response(usage: Usage) -> Self {
186 Self::FinalResponse(MockResponse::with_usage(usage))
187 }
188
189 pub fn final_response_with_default_usage() -> Self {
191 Self::FinalResponse(MockResponse::with_usage(Usage::new()))
192 }
193
194 pub fn final_response_with_total_tokens(total_tokens: u64) -> Self {
196 Self::FinalResponse(MockResponse::with_total_tokens(total_tokens))
197 }
198
199 pub fn error(message: impl Into<String>) -> Self {
201 Self::Error(MockError::provider(message))
202 }
203
204 pub(crate) fn into_raw_choice(
205 self,
206 ) -> Result<RawStreamingChoice<MockResponse>, CompletionError> {
207 match self {
208 Self::Text(text) => Ok(RawStreamingChoice::Message(text)),
209 Self::TextStart { additional_params } => {
210 Ok(RawStreamingChoice::TextStart { additional_params })
211 }
212 Self::TextAdditionalParams(additional_params) => {
213 Ok(RawStreamingChoice::TextAdditionalParams(additional_params))
214 }
215 Self::ToolCall {
216 id,
217 name,
218 arguments,
219 call_id,
220 } => {
221 let mut tool_call = RawStreamingToolCall::new(id, name, arguments);
222 if let Some(call_id) = call_id {
223 tool_call = tool_call.with_call_id(call_id);
224 }
225 Ok(RawStreamingChoice::ToolCall(tool_call))
226 }
227 Self::ToolCallDelta {
228 id,
229 internal_call_id,
230 content,
231 } => Ok(RawStreamingChoice::ToolCallDelta {
232 id,
233 internal_call_id,
234 content,
235 }),
236 Self::Reasoning { id, content } => Ok(RawStreamingChoice::Reasoning { id, content }),
237 Self::ReasoningDelta { id, reasoning } => {
238 Ok(RawStreamingChoice::ReasoningDelta { id, reasoning })
239 }
240 Self::MessageId(id) => Ok(RawStreamingChoice::MessageId(id)),
241 Self::FinalResponse(response) => Ok(RawStreamingChoice::FinalResponse(response)),
242 Self::Error(error) => Err(error.into_completion_error()),
243 }
244 }
245}