1use crate::config::types::{ReasoningEffortLevel, VerbosityLevel};
2use serde::{Deserialize, Serialize};
3use serde_json::{Value, json};
4use std::sync::Arc;
5
6use super::{Message, ToolDefinition};
7
8#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11pub struct FallbackModel {
12 pub model: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub max_tokens: Option<u32>,
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub thinking: Option<AnthropicThinkingConfig>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
24#[serde(tag = "type", rename_all = "lowercase")]
25pub enum AnthropicThinkingConfig {
26 #[default]
27 Disabled,
28 Enabled {
29 budget_tokens: u32,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 display: Option<String>,
32 },
33 Adaptive {
34 #[serde(skip_serializing_if = "Option::is_none")]
35 display: Option<String>,
36 },
37}
38
39#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
40#[serde(rename_all = "snake_case")]
41pub enum PromptCacheProfile {
42 BudgetContinuation,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
46#[serde(rename_all = "snake_case")]
47pub enum AnthropicThinkingModeOverride {
48 #[default]
49 Inherit,
50 Disabled,
51 Adaptive,
52 ManualBudget(u32),
53}
54
55#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
56#[serde(rename_all = "snake_case")]
57pub enum AnthropicThinkingDisplayOverride {
58 #[default]
59 Inherit,
60 Summarized,
61 Omitted,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
65#[serde(rename_all = "snake_case")]
66pub enum AnthropicOptionalStringOverride {
67 #[default]
68 Inherit,
69 Omit,
70 Explicit(String),
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
74#[serde(rename_all = "snake_case")]
75pub enum AnthropicOptionalU32Override {
76 #[default]
77 Inherit,
78 Omit,
79 Explicit(u32),
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
83pub struct AnthropicRequestOverrides {
84 #[serde(default)]
85 pub thinking_mode: AnthropicThinkingModeOverride,
86 #[serde(default)]
87 pub thinking_display: AnthropicThinkingDisplayOverride,
88 #[serde(default)]
89 pub effort: AnthropicOptionalStringOverride,
90 #[serde(default)]
91 pub task_budget_tokens: AnthropicOptionalU32Override,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, Default)]
96
97pub struct LLMRequest {
98 pub messages: Vec<Message>,
99 pub system_prompt: Option<Arc<String>>,
100 pub tools: Option<Arc<Vec<ToolDefinition>>>,
101 pub model: String,
102 pub max_tokens: Option<u32>,
103 pub temperature: Option<f32>,
104 pub stream: bool,
105
106 pub output_format: Option<Value>,
109
110 pub tool_choice: Option<ToolChoice>,
113
114 pub parallel_tool_calls: Option<bool>,
116
117 pub parallel_tool_config: Option<Box<ParallelToolConfig>>,
119
120 pub reasoning_effort: Option<ReasoningEffortLevel>,
123
124 pub effort: Option<String>,
129
130 pub verbosity: Option<VerbosityLevel>,
133
134 pub do_sample: Option<bool>,
136 pub top_p: Option<f32>,
137 pub top_k: Option<i32>,
138 pub presence_penalty: Option<f32>,
139 pub frequency_penalty: Option<f32>,
140 pub stop_sequences: Option<Vec<String>>,
141 pub thinking_budget: Option<u32>,
144
145 pub betas: Option<Vec<String>>,
147
148 pub context_management: Option<Value>,
150
151 pub prefill: Option<String>,
154
155 pub character_reinforcement: bool,
157
158 pub character_name: Option<String>,
160
161 pub coding_agent_settings: Option<Box<CodingAgentSettings>>,
163
164 pub metadata: Option<Value>,
167
168 pub previous_response_id: Option<String>,
171
172 pub response_store: Option<bool>,
175
176 pub responses_include: Option<Vec<String>>,
179
180 pub service_tier: Option<String>,
183
184 pub prompt_cache_key: Option<String>,
187
188 pub prompt_cache_profile: Option<PromptCacheProfile>,
190
191 pub fallbacks: Option<Vec<FallbackModel>>,
194
195 pub fallback_credit_token: Option<String>,
200
201 pub anthropic_request_overrides: Option<AnthropicRequestOverrides>,
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
208pub struct ResponsesCompactionOptions {
209 pub instructions: Option<String>,
211 pub max_output_tokens: Option<u32>,
213 pub reasoning_effort: Option<ReasoningEffortLevel>,
215 pub verbosity: Option<VerbosityLevel>,
217 pub responses_include: Option<Vec<String>>,
219 pub response_store: Option<bool>,
221 pub service_tier: Option<String>,
223 pub prompt_cache_key: Option<String>,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize, Default)]
229pub struct CodingAgentSettings {
230 pub force_xml_tags: bool,
232 pub prefill_thought: bool,
234 pub allow_uncertainty: bool,
236 pub strict_grounding: bool,
238 pub long_context_optimization: bool,
240 pub use_xml_document_format: bool,
242 pub force_quote_grounding: bool,
244 pub role_specialization: Option<String>,
246 pub enforce_structured_thought: bool,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
254#[serde(untagged)]
255#[derive(Default)]
256pub enum ToolChoice {
257 #[default]
260 Auto,
261
262 None,
265
266 Any,
269
270 Specific(SpecificToolChoice),
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct SpecificToolChoice {
278 #[serde(rename = "type")]
279 pub tool_type: String, pub function: SpecificFunctionChoice,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct SpecificFunctionChoice {
287 pub name: String,
288}
289
290impl ToolChoice {
291 pub fn auto() -> Self {
293 Self::Auto
294 }
295
296 pub fn none() -> Self {
298 Self::None
299 }
300
301 pub fn any() -> Self {
303 Self::Any
304 }
305
306 pub fn function(name: String) -> Self {
308 Self::Specific(SpecificToolChoice {
309 tool_type: "function".to_owned(),
310 function: SpecificFunctionChoice { name },
311 })
312 }
313
314 pub fn allows_parallel_tools(&self) -> bool {
317 match self {
318 Self::Auto => true,
320 Self::Any => true,
322 Self::Specific(_) => false,
324 Self::None => false,
326 }
327 }
328
329 pub fn description(&self) -> &'static str {
331 match self {
332 Self::Auto => "Model decides when to use tools (allows parallel)",
333 Self::None => "No tools will be used",
334 Self::Any => "At least one tool must be used (allows parallel)",
335 Self::Specific(_) => "Specific tool must be used (no parallel)",
336 }
337 }
338
339 const OPENAI_STYLE_PROVIDERS: &'static [&'static str] = &[
341 "openai",
342 "deepseek",
343 "huggingface",
344 "mistral",
345 "openrouter",
346 "zai",
347 "moonshot",
348 "stepfun",
349 "evolink",
350 "lmstudio",
351 "llamacpp",
352 ];
353
354 #[inline]
356 pub fn to_provider_format(&self, provider: &str) -> Value {
357 if Self::OPENAI_STYLE_PROVIDERS.contains(&provider) {
358 return self.to_openai_format();
359 }
360
361 match provider {
362 "anthropic" => self.to_anthropic_format(),
363 "gemini" => self.to_gemini_format(),
364 _ => self.to_openai_format(), }
366 }
367
368 #[inline]
369 fn to_openai_format(&self) -> Value {
370 match self {
371 Self::Auto => json!("auto"),
372 Self::None => json!("none"),
373 Self::Any => json!("required"),
374 Self::Specific(choice) => json!(choice),
375 }
376 }
377
378 #[inline]
379 fn to_anthropic_format(&self) -> Value {
380 match self {
381 Self::Auto => json!({"type": "auto"}),
382 Self::None => json!({"type": "none"}),
383 Self::Any => json!({"type": "any"}),
384 Self::Specific(choice) => json!({"type": "tool", "name": &choice.function.name}),
385 }
386 }
387
388 #[inline]
389 fn to_gemini_format(&self) -> Value {
390 match self {
391 Self::Auto => json!({"mode": "auto"}),
392 Self::None => json!({"mode": "none"}),
393 Self::Any => json!({"mode": "any"}),
394 Self::Specific(choice) => {
395 json!({"mode": "any", "allowed_function_names": [&choice.function.name]})
396 }
397 }
398 }
399}
400
401#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct ParallelToolConfig {
405 pub disable_parallel_tool_use: bool,
408
409 pub max_parallel_tools: Option<usize>,
412
413 pub encourage_parallel: bool,
415}
416
417impl Default for ParallelToolConfig {
418 fn default() -> Self {
419 Self {
420 disable_parallel_tool_use: false,
421 max_parallel_tools: Some(5), encourage_parallel: true,
423 }
424 }
425}
426
427impl ParallelToolConfig {
428 pub fn anthropic_optimized() -> Self {
430 Self {
431 disable_parallel_tool_use: false,
432 max_parallel_tools: None, encourage_parallel: true,
434 }
435 }
436
437 pub fn sequential_only() -> Self {
439 Self {
440 disable_parallel_tool_use: true,
441 max_parallel_tools: Some(1),
442 encourage_parallel: false,
443 }
444 }
445}