Skip to main content

vtcode_config/core/
provider.rs

1use serde::{Deserialize, Serialize};
2
3/// OpenAI-specific provider configuration
4#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
5#[derive(Debug, Clone, Deserialize, Serialize, Default)]
6pub struct OpenAIConfig {
7    /// Enable Responses API WebSocket transport for non-streaming requests.
8    /// This is an opt-in path designed for long-running, tool-heavy workflows.
9    #[serde(default)]
10    pub websocket_mode: bool,
11}
12
13/// Anthropic-specific provider configuration
14#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
15#[derive(Debug, Clone, Deserialize, Serialize)]
16pub struct AnthropicConfig {
17    /// DEPRECATED: Model name validation has been removed. The Anthropic API validates
18    /// model names directly, avoiding maintenance burden and allowing flexibility.
19    /// This field is kept for backward compatibility but has no effect.
20    #[deprecated(
21        since = "0.75.0",
22        note = "Model validation removed. API validates model names directly."
23    )]
24    #[serde(default)]
25    pub skip_model_validation: bool,
26
27    /// Enable extended thinking feature for Anthropic models
28    /// When enabled, Claude uses internal reasoning before responding, providing
29    /// enhanced reasoning capabilities for complex tasks.
30    /// Only supported by Claude 4, Claude 4.5, and Claude 3.7 Sonnet models.
31    /// Claude 4.6 uses adaptive thinking instead of extended thinking.
32    /// Note: Extended thinking is now auto-enabled by default (31,999 tokens).
33    /// Set MAX_THINKING_TOKENS=63999 environment variable for 2x budget on 64K models.
34    /// See: https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
35    #[serde(default = "default_extended_thinking_enabled")]
36    pub extended_thinking_enabled: bool,
37
38    /// Beta header for interleaved thinking feature
39    #[serde(default = "default_interleaved_thinking_beta")]
40    pub interleaved_thinking_beta: String,
41
42    /// Budget tokens for extended thinking (minimum: 1024, default: 31999)
43    /// On 64K output models (Opus 4.5, Sonnet 4.5, Haiku 4.5): default 31,999, max 63,999
44    /// On 32K output models (Opus 4): max 31,999
45    /// Use MAX_THINKING_TOKENS environment variable to override.
46    #[serde(default = "default_interleaved_thinking_budget_tokens")]
47    pub interleaved_thinking_budget_tokens: u32,
48
49    /// Type value for enabling interleaved thinking
50    #[serde(default = "default_interleaved_thinking_type")]
51    pub interleaved_thinking_type_enabled: String,
52
53    /// Tool search configuration for dynamic tool discovery (advanced-tool-use beta)
54    #[serde(default)]
55    pub tool_search: ToolSearchConfig,
56
57    /// Effort level for token usage (high, medium, low)
58    /// Controls how many tokens Claude uses when responding, trading off between
59    /// response thoroughness and token efficiency.
60    /// Supported by Claude Opus 4.5/4.6 (4.5 requires effort beta header)
61    #[serde(default = "default_effort")]
62    pub effort: String,
63
64    /// Enable token counting via the count_tokens endpoint
65    /// When enabled, the agent can estimate input token counts before making API calls
66    /// Useful for proactive management of rate limits and costs
67    #[serde(default = "default_count_tokens_enabled")]
68    pub count_tokens_enabled: bool,
69}
70
71#[allow(deprecated)]
72impl Default for AnthropicConfig {
73    fn default() -> Self {
74        Self {
75            skip_model_validation: false,
76            extended_thinking_enabled: default_extended_thinking_enabled(),
77            interleaved_thinking_beta: default_interleaved_thinking_beta(),
78            interleaved_thinking_budget_tokens: default_interleaved_thinking_budget_tokens(),
79            interleaved_thinking_type_enabled: default_interleaved_thinking_type(),
80            tool_search: ToolSearchConfig::default(),
81            effort: default_effort(),
82            count_tokens_enabled: default_count_tokens_enabled(),
83        }
84    }
85}
86
87#[inline]
88fn default_count_tokens_enabled() -> bool {
89    false
90}
91
92/// Configuration for Anthropic's tool search feature (advanced-tool-use beta)
93/// Enables dynamic tool discovery for large tool catalogs (up to 10k tools)
94#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
95#[derive(Debug, Clone, Deserialize, Serialize)]
96pub struct ToolSearchConfig {
97    /// Enable tool search feature (requires advanced-tool-use-2025-11-20 beta)
98    #[serde(default)]
99    pub enabled: bool,
100
101    /// Search algorithm: "regex" (Python regex patterns) or "bm25" (natural language)
102    #[serde(default = "default_tool_search_algorithm")]
103    pub algorithm: String,
104
105    /// Automatically defer loading of all tools except core tools
106    #[serde(default = "default_defer_by_default")]
107    pub defer_by_default: bool,
108
109    /// Maximum number of tool search results to return
110    #[serde(default = "default_max_results")]
111    pub max_results: u32,
112
113    /// Tool names that should never be deferred (always available)
114    #[serde(default)]
115    pub always_available_tools: Vec<String>,
116}
117
118impl Default for ToolSearchConfig {
119    fn default() -> Self {
120        Self {
121            enabled: false,
122            algorithm: default_tool_search_algorithm(),
123            defer_by_default: default_defer_by_default(),
124            max_results: default_max_results(),
125            always_available_tools: vec![],
126        }
127    }
128}
129
130#[inline]
131fn default_tool_search_algorithm() -> String {
132    "regex".to_string()
133}
134
135#[inline]
136fn default_defer_by_default() -> bool {
137    true
138}
139
140#[inline]
141fn default_max_results() -> u32 {
142    5
143}
144
145#[inline]
146fn default_extended_thinking_enabled() -> bool {
147    true
148}
149
150#[inline]
151fn default_interleaved_thinking_beta() -> String {
152    "interleaved-thinking-2025-05-14".to_string()
153}
154
155#[inline]
156fn default_interleaved_thinking_budget_tokens() -> u32 {
157    31999
158}
159
160#[inline]
161fn default_interleaved_thinking_type() -> String {
162    "enabled".to_string()
163}
164
165#[inline]
166fn default_effort() -> String {
167    "low".to_string()
168}
169
170#[cfg(test)]
171mod tests {
172    use super::OpenAIConfig;
173
174    #[test]
175    fn openai_config_defaults_to_websocket_mode_disabled() {
176        let config = OpenAIConfig::default();
177        assert!(!config.websocket_mode);
178    }
179
180    #[test]
181    fn openai_config_parses_websocket_mode_opt_in() {
182        let parsed: OpenAIConfig =
183            toml::from_str("websocket_mode = true").expect("config should parse");
184        assert!(parsed.websocket_mode);
185    }
186}