Skip to main content

oxi_ai/providers/
options.rs

1//! Stream options for providers
2
3use crate::{CacheRetention, ThinkingLevel};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::fmt;
7
8/// Options for streaming requests
9#[derive(Clone, Default, Serialize, Deserialize)]
10pub struct StreamOptions {
11    /// Sampling temperature (0.0 to 2.0)
12    #[serde(default)]
13    pub temperature: Option<f64>,
14
15    /// Maximum tokens to generate
16    #[serde(default)]
17    pub max_tokens: Option<usize>,
18
19    /// API key (overrides environment variable)
20    /// This field is excluded from serialization and Debug output to prevent leakage.
21    #[serde(skip)]
22    pub api_key: Option<String>,
23
24    /// Cache retention preference
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub cache_retention: Option<CacheRetention>,
27
28    /// Session ID for providers that support session-based caching
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub session_id: Option<String>,
31
32    /// Custom HTTP headers to include
33    #[serde(default)]
34    pub headers: HashMap<String, String>,
35
36    /// Thinking/reasoning level
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub thinking_level: Option<ThinkingLevel>,
39
40    /// Custom token budgets for thinking levels
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub thinking_budgets: Option<ThinkingBudgets>,
43}
44
45impl fmt::Debug for StreamOptions {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        f.debug_struct("StreamOptions")
48            .field("temperature", &self.temperature)
49            .field("max_tokens", &self.max_tokens)
50            .field("api_key", &self.api_key.as_ref().map(|_| "[REDACTED]"))
51            .field("cache_retention", &self.cache_retention)
52            .field("session_id", &self.session_id)
53            .field("headers", &self.headers)
54            .field("thinking_level", &self.thinking_level)
55            .field("thinking_budgets", &self.thinking_budgets)
56            .finish()
57    }
58}
59
60impl StreamOptions {
61    /// Create new stream options
62    pub fn new() -> Self {
63        Self::default()
64    }
65
66    /// Set temperature
67    pub fn temperature(mut self, temp: f64) -> Self {
68        self.temperature = Some(temp);
69        self
70    }
71
72    /// Set max tokens
73    pub fn max_tokens(mut self, tokens: usize) -> Self {
74        self.max_tokens = Some(tokens);
75        self
76    }
77
78    /// Set API key
79    pub fn api_key(mut self, key: impl Into<String>) -> Self {
80        self.api_key = Some(key.into());
81        self
82    }
83
84    /// Set cache retention
85    pub fn cache_retention(mut self, retention: CacheRetention) -> Self {
86        self.cache_retention = Some(retention);
87        self
88    }
89
90    /// Set session ID
91    pub fn session_id(mut self, id: impl Into<String>) -> Self {
92        self.session_id = Some(id.into());
93        self
94    }
95
96    /// Set thinking level
97    pub fn thinking_level(mut self, level: ThinkingLevel) -> Self {
98        self.thinking_level = Some(level);
99        self
100    }
101}
102
103/// Token budgets for thinking levels
104#[derive(Debug, Clone, Default, Serialize, Deserialize)]
105pub struct ThinkingBudgets {
106    #[serde(default)]
107    pub minimal: Option<usize>,
108    #[serde(default)]
109    pub low: Option<usize>,
110    #[serde(default)]
111    pub medium: Option<usize>,
112    #[serde(default)]
113    pub high: Option<usize>,
114}
115
116impl ThinkingBudgets {
117    pub fn new() -> Self {
118        Self::default()
119    }
120
121    pub fn minimal(mut self, tokens: usize) -> Self {
122        self.minimal = Some(tokens);
123        self
124    }
125
126    pub fn low(mut self, tokens: usize) -> Self {
127        self.low = Some(tokens);
128        self
129    }
130
131    pub fn medium(mut self, tokens: usize) -> Self {
132        self.medium = Some(tokens);
133        self
134    }
135
136    pub fn high(mut self, tokens: usize) -> Self {
137        self.high = Some(tokens);
138        self
139    }
140}