vtcode_core/config/mod.rs
1//! # Configuration Management System
2//!
3//! This module provides a comprehensive configuration management system for VTCode,
4//! handling TOML-based configuration files with support for policies, security settings,
5//! and runtime customization.
6//!
7//! ## Architecture Overview
8//!
9//! The configuration system is built around several key components:
10//!
11//! - **TOML Configuration**: Human-readable configuration files
12//! - **Layered Defaults**: Sensible defaults with user overrides
13//! - **Runtime Validation**: Configuration validation and error handling
14//! - **Hot Reloading**: Configuration changes without restart (where applicable)
15//! - **Security Controls**: Policy-based access control and restrictions
16//!
17//! ## Configuration Structure
18//!
19//! ```toml
20//! [agent]
21//! max_iterations = 50
22//! timeout_seconds = 300
23//! enable_decision_ledger = true
24//!
25//! [tools]
26//! max_tool_loops = 25
27//! default_policy = "prompt"
28//!
29//! [llm.providers.gemini]
30//! api_key = "your-key"
31//! model = "gemini-2.5-flash"
32//!
33//! [security]
34//! workspace_root = "/path/to/project"
35//! allow_network_access = false
36//! ```
37//!
38//! ## Basic Usage
39//!
40//! ```rust,no_run
41//! use vtcode_core::{VTCodeConfig, AgentConfig};
42//!
43//! #[tokio::main]
44//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
45//! // Load configuration from vtcode.toml
46//! let config = VTCodeConfig::load()?;
47//!
48//! // Access specific sections
49//! println!("Max iterations: {}", config.agent.max_iterations);
50//! println!("Default tool policy: {}", config.tools.default_policy);
51//!
52//! // Create agent with configuration
53//! let agent = vtcode_core::core::agent::core::Agent::new(config).await?;
54//!
55//! Ok(())
56//! }
57//! ```
58//!
59//! ## Configuration Sections
60//!
61//! ### Agent Configuration
62//! ```rust,no_run
63//! use vtcode_core::config::core::AgentConfig;
64//!
65//! let agent_config = AgentConfig {
66//! max_iterations: 100,
67//! timeout_seconds: 600,
68//! enable_decision_ledger: true,
69//! enable_conversation_summarization: true,
70//! ..Default::default()
71//! };
72//! ```
73//!
74//! ### Tool Configuration
75//! ```rust,no_run
76//! use vtcode_core::config::core::{ToolsConfig, ToolPolicy};
77//!
78//! let tools_config = ToolsConfig {
79//! max_tool_loops: 50,
80//! default_policy: ToolPolicy::Prompt,
81//! enable_file_operations: true,
82//! enable_terminal_commands: true,
83//! ..Default::default()
84//! };
85//! ```
86//!
87//! ### Security Configuration
88//! ```rust,no_run
89//! use vtcode_core::config::core::SecurityConfig;
90//!
91//! let security_config = SecurityConfig {
92//! workspace_root: "/path/to/secure/workspace".into(),
93//! allow_network_access: false,
94//! command_allowlist: vec!["git".to_string(), "cargo".to_string()],
95//! path_restrictions: vec!["*.secret".to_string()],
96//! ..Default::default()
97//! };
98//! ```
99//!
100//! ## Runtime Configuration Management
101//!
102//! ```rust,no_run
103//! use vtcode_core::config::loader::ConfigManager;
104//!
105//! #[tokio::main]
106//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
107//! let mut config_manager = ConfigManager::new()?;
108//!
109//! // Load configuration
110//! let config = config_manager.load_config().await?;
111//!
112//! // Modify configuration at runtime
113//! config.agent.max_iterations = 75;
114//!
115//! // Save changes
116//! config_manager.save_config(&config).await?;
117//!
118//! Ok(())
119//! }
120//! ```
121//!
122//! ## Environment Variables
123//!
124//! VTCode supports configuration through environment variables:
125//!
126//! ```bash
127//! # API Keys
128//! export GEMINI_API_KEY="your-gemini-key"
129//! export OPENAI_API_KEY="your-openai-key"
130//! export ANTHROPIC_API_KEY="your-anthropic-key"
131//!
132//! # Configuration
133//! export VTCode_WORKSPACE_DIR="/path/to/project"
134//! export VTCode_CONFIG_PATH="/path/to/vtcode.toml"
135//! ```
136//!
137//! ## Validation and Error Handling
138//!
139//! The configuration system provides comprehensive validation:
140//!
141//! ```rust,no_run
142//! use vtcode_core::VTCodeConfig;
143//!
144//! match VTCodeConfig::load() {
145//! Ok(config) => {
146//! // Configuration loaded successfully
147//! println!("Configuration valid");
148//! }
149//! Err(e) => {
150//! // Handle configuration errors
151//! eprintln!("Configuration error: {}", e);
152//! // Provide helpful error messages
153//! if e.to_string().contains("missing field") {
154//! eprintln!("Hint: Check your vtcode.toml file for required fields");
155//! }
156//! }
157//! }
158//! ```
159//!
160//! ## Security Best Practices
161//!
162//! - **Never commit API keys** to version control
163//! - **Use environment variables** for sensitive configuration
164//! - **Validate workspace paths** to prevent directory traversal
165//! - **Restrict command execution** to approved commands only
166//! - **Enable audit logging** for security monitoring
167
168//! VTCode Configuration Module
169//!
170//! This module handles loading and managing configuration from vtcode.toml files.
171//! It provides a centralized way to manage agent policies, tool permissions, and
172//! command allow lists.
173
174pub mod api_keys;
175pub mod constants;
176pub mod context;
177pub mod core;
178pub mod defaults;
179pub mod loader;
180pub mod mcp;
181pub mod models;
182pub mod router;
183pub mod telemetry;
184pub mod types;
185
186// Re-export main types for backward compatibility
187pub use context::{ContextFeaturesConfig, LedgerConfig};
188pub use core::{
189 AgentConfig, AutomationConfig, CommandsConfig, FullAutoConfig, SecurityConfig, ToolPolicy,
190 ToolsConfig,
191};
192pub use defaults::{ContextStoreDefaults, PerformanceDefaults, ScenarioDefaults};
193pub use loader::{ConfigManager, VTCodeConfig};
194pub use mcp::{
195 McpAllowListConfig, McpAllowListRules, McpClientConfig, McpHttpServerConfig, McpProviderConfig,
196 McpStdioServerConfig, McpTransportConfig, McpUiConfig, McpUiMode,
197};
198pub use router::{ComplexityModelMap, ResourceBudget, RouterConfig};
199pub use telemetry::TelemetryConfig;
200pub use types::ReasoningEffortLevel;
201
202use serde::{Deserialize, Serialize};
203
204#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
205#[serde(rename_all = "snake_case")]
206pub enum ToolOutputMode {
207 Compact,
208 Full,
209}
210
211impl Default for ToolOutputMode {
212 fn default() -> Self {
213 Self::Compact
214 }
215}
216
217#[derive(Debug, Clone, Deserialize, Serialize)]
218pub struct UiConfig {
219 #[serde(default = "default_tool_output_mode")]
220 pub tool_output_mode: ToolOutputMode,
221 #[serde(default = "default_inline_viewport_rows")]
222 pub inline_viewport_rows: u16,
223 #[serde(default = "default_show_timeline_pane")]
224 pub show_timeline_pane: bool,
225}
226
227impl Default for UiConfig {
228 fn default() -> Self {
229 Self {
230 tool_output_mode: default_tool_output_mode(),
231 inline_viewport_rows: default_inline_viewport_rows(),
232 show_timeline_pane: default_show_timeline_pane(),
233 }
234 }
235}
236
237/// PTY configuration
238#[derive(Debug, Clone, Deserialize, Serialize)]
239pub struct PtyConfig {
240 /// Enable PTY functionality
241 #[serde(default = "default_pty_enabled")]
242 pub enabled: bool,
243
244 /// Default terminal rows
245 #[serde(default = "default_pty_rows")]
246 pub default_rows: u16,
247
248 /// Default terminal columns
249 #[serde(default = "default_pty_cols")]
250 pub default_cols: u16,
251
252 /// Maximum number of concurrent PTY sessions
253 #[serde(default = "default_max_pty_sessions")]
254 pub max_sessions: usize,
255
256 /// Command timeout in seconds
257 #[serde(default = "default_pty_timeout")]
258 pub command_timeout_seconds: u64,
259
260 /// Number of PTY stdout lines to display in chat output
261 #[serde(default = "default_stdout_tail_lines")]
262 pub stdout_tail_lines: usize,
263}
264
265impl Default for PtyConfig {
266 fn default() -> Self {
267 Self {
268 enabled: default_pty_enabled(),
269 default_rows: default_pty_rows(),
270 default_cols: default_pty_cols(),
271 max_sessions: default_max_pty_sessions(),
272 command_timeout_seconds: default_pty_timeout(),
273 stdout_tail_lines: default_stdout_tail_lines(),
274 }
275 }
276}
277
278fn default_pty_enabled() -> bool {
279 true
280}
281fn default_pty_rows() -> u16 {
282 24
283}
284fn default_pty_cols() -> u16 {
285 80
286}
287fn default_max_pty_sessions() -> usize {
288 10
289}
290fn default_pty_timeout() -> u64 {
291 300
292}
293fn default_stdout_tail_lines() -> usize {
294 crate::config::constants::defaults::DEFAULT_PTY_STDOUT_TAIL_LINES
295}
296fn default_tool_output_mode() -> ToolOutputMode {
297 ToolOutputMode::Compact
298}
299fn default_inline_viewport_rows() -> u16 {
300 crate::config::constants::ui::DEFAULT_INLINE_VIEWPORT_ROWS
301}
302
303fn default_show_timeline_pane() -> bool {
304 crate::config::constants::ui::INLINE_SHOW_TIMELINE_PANE
305}