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 acp;
175pub mod api_keys;
176pub mod constants;
177pub mod context;
178pub mod core;
179pub mod defaults;
180pub mod loader;
181pub mod mcp;
182pub mod models;
183pub mod router;
184pub mod telemetry;
185pub mod types;
186
187// Re-export main types for backward compatibility
188pub use acp::{
189 AgentClientProtocolConfig, AgentClientProtocolTransport, AgentClientProtocolZedConfig,
190 AgentClientProtocolZedToolsConfig,
191};
192pub use context::{ContextFeaturesConfig, LedgerConfig};
193pub use core::{
194 AgentConfig, AutomationConfig, CommandsConfig, FullAutoConfig, SecurityConfig, ToolPolicy,
195 ToolsConfig,
196};
197pub use defaults::{ContextStoreDefaults, PerformanceDefaults, ScenarioDefaults};
198pub use loader::{ConfigManager, VTCodeConfig};
199pub use mcp::{
200 McpAllowListConfig, McpAllowListRules, McpClientConfig, McpHttpServerConfig, McpProviderConfig,
201 McpStdioServerConfig, McpTransportConfig, McpUiConfig, McpUiMode,
202};
203pub use router::{ComplexityModelMap, ResourceBudget, RouterConfig};
204pub use telemetry::TelemetryConfig;
205pub use types::ReasoningEffortLevel;
206
207use serde::{Deserialize, Serialize};
208
209#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
210#[serde(rename_all = "snake_case")]
211pub enum ToolOutputMode {
212 Compact,
213 Full,
214}
215
216impl Default for ToolOutputMode {
217 fn default() -> Self {
218 Self::Compact
219 }
220}
221
222#[derive(Debug, Clone, Deserialize, Serialize)]
223pub struct UiConfig {
224 #[serde(default = "default_tool_output_mode")]
225 pub tool_output_mode: ToolOutputMode,
226 #[serde(default = "default_inline_viewport_rows")]
227 pub inline_viewport_rows: u16,
228 #[serde(default = "default_show_timeline_pane")]
229 pub show_timeline_pane: bool,
230}
231
232impl Default for UiConfig {
233 fn default() -> Self {
234 Self {
235 tool_output_mode: default_tool_output_mode(),
236 inline_viewport_rows: default_inline_viewport_rows(),
237 show_timeline_pane: default_show_timeline_pane(),
238 }
239 }
240}
241
242/// PTY configuration
243#[derive(Debug, Clone, Deserialize, Serialize)]
244pub struct PtyConfig {
245 /// Enable PTY functionality
246 #[serde(default = "default_pty_enabled")]
247 pub enabled: bool,
248
249 /// Default terminal rows
250 #[serde(default = "default_pty_rows")]
251 pub default_rows: u16,
252
253 /// Default terminal columns
254 #[serde(default = "default_pty_cols")]
255 pub default_cols: u16,
256
257 /// Maximum number of concurrent PTY sessions
258 #[serde(default = "default_max_pty_sessions")]
259 pub max_sessions: usize,
260
261 /// Command timeout in seconds
262 #[serde(default = "default_pty_timeout")]
263 pub command_timeout_seconds: u64,
264
265 /// Number of PTY stdout lines to display in chat output
266 #[serde(default = "default_stdout_tail_lines")]
267 pub stdout_tail_lines: usize,
268}
269
270impl Default for PtyConfig {
271 fn default() -> Self {
272 Self {
273 enabled: default_pty_enabled(),
274 default_rows: default_pty_rows(),
275 default_cols: default_pty_cols(),
276 max_sessions: default_max_pty_sessions(),
277 command_timeout_seconds: default_pty_timeout(),
278 stdout_tail_lines: default_stdout_tail_lines(),
279 }
280 }
281}
282
283fn default_pty_enabled() -> bool {
284 true
285}
286fn default_pty_rows() -> u16 {
287 24
288}
289fn default_pty_cols() -> u16 {
290 80
291}
292fn default_max_pty_sessions() -> usize {
293 10
294}
295fn default_pty_timeout() -> u64 {
296 300
297}
298fn default_stdout_tail_lines() -> usize {
299 crate::config::constants::defaults::DEFAULT_PTY_STDOUT_TAIL_LINES
300}
301fn default_tool_output_mode() -> ToolOutputMode {
302 ToolOutputMode::Compact
303}
304fn default_inline_viewport_rows() -> u16 {
305 crate::config::constants::ui::DEFAULT_INLINE_VIEWPORT_ROWS
306}
307
308fn default_show_timeline_pane() -> bool {
309 crate::config::constants::ui::INLINE_SHOW_TIMELINE_PANE
310}