vtcode_core/
lib.rs

1#![doc = r#"
2# VTCode Core - Research-Preview Rust Coding Agent Library
3
4A sophisticated terminal-based coding agent library that implements state-of-the-art agent
5architecture patterns, inspired by Anthropic's SWE-bench breakthroughs.
6
7## Features
8
9### Core Capabilities
10
11- **Single-Agent Reliability**: Streamlined, linear agent with robust context engineering
12- **Decision Ledger**: Structured record of key decisions injected each turn for consistency
13- **Multi-Provider LLM Support**: Gemini, OpenAI, Anthropic, DeepSeek integration
14- **Advanced Code Analysis**: Tree-sitter parsers for Rust, Python, JavaScript, TypeScript, Go, Java
15- **Intelligent Tool Suite**: File operations, search, terminal commands, and PTY integration
16- **Configuration Management**: TOML-based configuration with comprehensive policies
17- **Safety & Security**: Path validation, command policies, and human-in-the-loop controls
18- **Workspace-First Automation**: Reads, writes, indexing, and shell execution anchored to `WORKSPACE_DIR`
19
20### Advanced Features
21
22- **Context Engineering**: Full conversation history with intelligent management
23- **Performance Monitoring**: Real-time metrics and benchmarking capabilities
24- **Prompt Caching**: Strategic caching for improved response times
25- **Conversation Summarization**: Automatic compression for long sessions
26- **Tool Policy Management**: Configurable tool execution policies
27- **PTY Integration**: Full terminal emulation for interactive commands
28- **Project Indexing**: Intelligent workspace analysis and file discovery
29
30## Quick Start
31
32```rust,no_run
33use vtcode_core::{Agent, VTCodeConfig};
34
35#[tokio::main]
36async fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // Load configuration
38    let config = VTCodeConfig::load()?;
39
40    // Create agent
41    let agent = Agent::new(config).await?;
42
43    // Start interactive session
44    agent.run().await?;
45
46    Ok(())
47}
48```
49
50## Architecture
51
52The agent follows proven patterns for reliable, long-running coding assistance:
53
54- **Model-Driven Control**: Maximum autonomy given to language models
55- **Decision Transparency**: Complete audit trail of all agent actions
56- **Error Recovery**: Intelligent error handling with context preservation
57- **Conversation Summarization**: Automatic compression for long sessions
58- **Tool Integration**: Modular tool system with policy-based execution
59
60## Core Components
61
62### Agent System
63- [`Agent`] - Main agent implementation with conversation management
64- [`ConversationSummarizer`] - Automatic conversation compression
65- [`ContextCompressor`] - Intelligent context management
66
67### Tool System
68- [`ToolRegistry`] - Central tool registration and execution
69- [`ToolPolicy`] - Configurable tool execution policies
70- [`ToolPolicyManager`] - Policy enforcement and validation
71
72### LLM Integration
73- [`AnyClient`] - Unified interface for multiple LLM providers
74- [`make_client`] - Factory function for creating LLM clients
75- Gemini, OpenAI, Anthropic, DeepSeek provider implementations
76
77### Configuration
78- [`VTCodeConfig`] - Main configuration structure
79- [`AgentConfig`] - Agent-specific configuration
80- TOML-based configuration with comprehensive policies
81
82## Examples
83
84### Basic Agent Usage
85
86```rust,no_run
87use vtcode_core::{Agent, VTCodeConfig};
88use std::path::PathBuf;
89
90#[tokio::main]
91async fn main() -> Result<(), Box<dyn std::error::Error>> {
92    // Load configuration
93    let config = VTCodeConfig::load()?;
94
95    // Create agent with custom workspace
96    let workspace = PathBuf::from("/path/to/project");
97    let agent = Agent::new_with_workspace(config, workspace).await?;
98
99    // Process a coding task
100    let task = "Add error handling to the user authentication function";
101    let result = agent.process_task(task).await?;
102
103    println!("Task completed: {}", result);
104
105    Ok(())
106}
107```
108
109### Tool Registry Usage
110
111```rust,no_run
112use vtcode_core::tools::{ToolRegistry, ToolRegistration};
113use serde_json::Value;
114
115#[tokio::main]
116async fn main() -> Result<(), Box<dyn std::error::Error>> {
117    let workspace = std::env::current_dir()?;
118    let mut registry = ToolRegistry::new(workspace);
119
120    // Register a custom tool
121    let custom_tool = ToolRegistration {
122        name: "analyze_code".to_string(),
123        description: "Analyze code for potential issues".to_string(),
124        parameters: serde_json::json!({
125            "type": "object",
126            "properties": {
127                "file_path": {"type": "string", "description": "Path to file to analyze"},
128                "analysis_type": {"type": "string", "enum": ["security", "performance", "style"]}
129            },
130            "required": ["file_path"]
131        }),
132        handler: |args: Value| async move {
133            let file_path = args["file_path"].as_str().unwrap_or("");
134            let analysis_type = args["analysis_type"].as_str().unwrap_or("general");
135
136            // Perform analysis
137            let result = format!("Analysis of {} for {} completed", file_path, analysis_type);
138
139            Ok(serde_json::json!({
140                "success": true,
141                "analysis": result,
142                "issues_found": 0
143            }))
144        },
145    };
146
147    registry.register_tool(custom_tool).await?;
148
149    // Execute the tool
150    let args = serde_json::json!({
151        "file_path": "src/main.rs",
152        "analysis_type": "security"
153    });
154
155    let result = registry.execute_tool("analyze_code", args).await?;
156    println!("Tool result: {}", result);
157
158    Ok(())
159}
160```
161
162### Configuration Management
163
164```rust,no_run
165use vtcode_core::{VTCodeConfig, AgentConfig};
166use vtcode_core::config::types::{ToolConfig, LoggingConfig};
167
168#[tokio::main]
169async fn main() -> Result<(), Box<dyn std::error::Error>> {
170    // Create custom configuration
171    let config = VTCodeConfig {
172        agent: AgentConfig {
173            max_iterations: 50,
174            timeout_seconds: 300,
175            ..Default::default()
176        },
177        tools: ToolConfig {
178            max_tool_loops: 25,
179            default_policy: "prompt".to_string(),
180            ..Default::default()
181        },
182        logging: LoggingConfig {
183            level: "info".to_string(),
184            file_path: Some("vtcode.log".to_string()),
185            ..Default::default()
186        },
187        ..Default::default()
188    };
189
190    // Save configuration
191    config.save()?;
192
193    // Load and verify
194    let loaded = VTCodeConfig::load()?;
195    assert_eq!(loaded.agent.max_iterations, 50);
196
197    Ok(())
198}
199```
200
201### LLM Provider Integration
202
203```rust,no_run
204use vtcode_core::llm::{AnyClient, make_client};
205use vtcode_core::config::types::ProviderConfigs;
206
207#[tokio::main]
208async fn main() -> Result<(), Box<dyn std::error::Error>> {
209    // Configure providers
210    let providers = ProviderConfigs {
211        gemini: Some(vtcode_core::utils::dot_config::ProviderConfig {
212            api_key: std::env::var("GEMINI_API_KEY")?,
213            model: "gemini-2.5-flash-exp".to_string(),
214            ..Default::default()
215        }),
216        ..Default::default()
217    };
218
219    // Create LLM client
220    let client = make_client(&providers, "gemini")?;
221
222    // Make a request
223    let messages = vec![
224        vtcode_core::llm::types::Message {
225            role: "user".to_string(),
226            content: "Hello, can you help me with Rust code?".to_string(),
227        }
228    ];
229
230    let response = client.chat(&messages, None).await?;
231    println!("LLM Response: {}", response.content);
232
233    Ok(())
234}
235```
236
237## Safety & Security
238
239VTCode implements multiple layers of security:
240
241- **Path Validation**: All file operations check workspace boundaries
242- **Command Policies**: Configurable allow/deny lists for terminal commands
243- **Tool Policies**: Granular control over tool execution
244- **Human-in-the-Loop**: Optional approval for sensitive operations
245- **Audit Logging**: Complete trail of all agent actions
246
247## Performance
248
249- **Prompt Caching**: Reduces API calls for repeated prompts
250- **Context Compression**: Efficient memory usage for long conversations
251- **Parallel Processing**: Concurrent tool execution where appropriate
252- **Resource Limits**: Configurable timeouts and size limits
253
254## Distribution
255
256- **Cargo**: `cargo install vtcode-core`
257- **GitHub**: Source code and releases
258- **Documentation**: Available on [docs.rs](https://docs.rs/vtcode-core)
259
260## Contributing
261
262Contributions are welcome! Please see the main VTCode repository for contribution guidelines.
263
264## License
265
266Licensed under the MIT License.
267"#]
268
269//!
270//! A sophisticated terminal-based coding agent that implements state-of-the-art agent
271//! architecture patterns, inspired by Anthropic's SWE-bench breakthroughs.
272//!
273//! ## Architecture
274//!
275//! The agent follows proven patterns for reliable, long-running coding assistance:
276//! - **Model-Driven Control**: Maximum autonomy given to language models
277//! - **Decision Transparency**: Complete audit trail of all agent actions
278//! - **Error Recovery**: Intelligent error handling with context preservation
279//! - **Conversation Summarization**: Automatic compression for long sessions
280
281//! VTCode Core Library
282//!
283//! This crate provides the core functionality for the VTCode agent,
284//! including tool implementations, LLM integration, and utility functions.
285
286// Public modules
287pub mod bash_runner;
288pub mod cli;
289pub mod code;
290pub mod commands;
291pub mod config;
292pub mod constants;
293pub mod core;
294pub mod gemini;
295pub mod llm;
296pub mod markdown_storage;
297pub mod models;
298pub mod project;
299pub mod prompts;
300pub mod safety;
301pub mod simple_indexer;
302pub mod tool_policy;
303pub mod tools;
304pub mod types;
305pub mod ui;
306pub mod utils;
307
308// Re-exports for convenience
309pub use bash_runner::BashRunner;
310pub use cli::args::{Cli, Commands};
311pub use code::code_completion::{CompletionEngine, CompletionSuggestion};
312pub use commands::stats::handle_stats_command;
313pub use config::types::{
314    AnalysisDepth, CapabilityLevel, CommandResult, CompressionLevel, ContextConfig, LoggingConfig,
315    OutputFormat, PerformanceMetrics, ReasoningEffortLevel, SessionInfo, ToolConfig,
316};
317pub use config::{AgentConfig, VTCodeConfig};
318pub use core::agent::core::Agent;
319pub use core::context_compression::{
320    CompressedContext, ContextCompressionConfig, ContextCompressor,
321};
322pub use core::conversation_summarizer::ConversationSummarizer;
323pub use core::performance_profiler::PerformanceProfiler;
324pub use core::prompt_caching::{CacheStats, PromptCache, PromptCacheConfig, PromptOptimizer};
325pub use core::timeout_detector::TimeoutDetector;
326pub use gemini::{Content, FunctionDeclaration, Part};
327pub use llm::{AnyClient, make_client};
328pub use markdown_storage::{MarkdownStorage, ProjectData, ProjectStorage, SimpleKVStorage};
329pub use project::{SimpleCache, SimpleProjectManager};
330pub use prompts::{
331    generate_lightweight_instruction, generate_specialized_instruction, generate_system_instruction,
332};
333pub use simple_indexer::SimpleIndexer;
334pub use tool_policy::{ToolPolicy, ToolPolicyManager};
335pub use tools::advanced_search::{AdvancedSearchTool, SearchOptions};
336pub use tools::grep_search::GrepSearchManager;
337pub use tools::tree_sitter::TreeSitterAnalyzer;
338pub use tools::{
339    ToolRegistration, ToolRegistry, build_function_declarations,
340    build_function_declarations_for_level,
341};
342pub use ui::diff_renderer::DiffRenderer;
343pub use utils::dot_config::{
344    CacheConfig, DotConfig, DotManager, ProviderConfigs, UiConfig, UserPreferences,
345    WorkspaceTrustLevel, WorkspaceTrustRecord, WorkspaceTrustStore, initialize_dot_folder,
346    load_user_config, save_user_config, update_theme_preference,
347};
348pub use utils::vtcodegitignore::initialize_vtcode_gitignore;
349
350#[cfg(test)]
351mod tests {
352    use super::*;
353
354    use tempfile::TempDir;
355
356    #[test]
357    fn test_library_exports() {
358        // Test that all public exports are accessible
359        let _cache = PromptCache::new();
360    }
361
362    #[test]
363    fn test_module_structure() {
364        // Test that all modules can be imported
365        // This is a compile-time test that ensures module structure is correct
366    }
367
368    #[test]
369    fn test_version_consistency() {
370        // Test that version information is consistent across modules
371        // This would be more meaningful with actual version checking
372    }
373
374    #[tokio::test]
375    async fn test_tool_registry_integration() {
376        use crate::config::constants::tools;
377
378        let temp_dir = TempDir::new().unwrap();
379        std::env::set_current_dir(&temp_dir).unwrap();
380
381        let mut registry = ToolRegistry::new(temp_dir.path().to_path_buf());
382
383        // Test that we can execute basic tools
384        let list_args = serde_json::json!({
385            "path": "."
386        });
387
388        let result = registry.execute_tool(tools::LIST_FILES, list_args).await;
389        assert!(result.is_ok());
390
391        let response: serde_json::Value = result.unwrap();
392        assert!(response["files"].is_array());
393    }
394
395    #[tokio::test]
396    async fn test_pty_basic_command() {
397        let temp_dir = TempDir::new().unwrap();
398        let workspace = temp_dir.path().to_path_buf();
399        let mut registry = ToolRegistry::new(workspace.clone());
400
401        // Test a simple PTY command
402        let args = serde_json::json!({
403            "command": "echo",
404            "args": ["Hello, PTY!"]
405        });
406
407        let result = registry.execute_tool("run_pty_cmd", args).await;
408        assert!(result.is_ok());
409        let response: serde_json::Value = result.unwrap();
410        assert_eq!(response["success"], true);
411        assert_eq!(response["code"], 0);
412        assert!(response["output"].as_str().unwrap().contains("Hello, PTY!"));
413    }
414
415    #[tokio::test]
416    async fn test_pty_session_management() {
417        let temp_dir = TempDir::new().unwrap();
418        let workspace = temp_dir.path().to_path_buf();
419        let mut registry = ToolRegistry::new(workspace.clone());
420
421        // Test creating a PTY session
422        let args = serde_json::json!({
423            "session_id": "test_session",
424            "command": "bash"
425        });
426
427        let result = registry.execute_tool("create_pty_session", args).await;
428        assert!(result.is_ok());
429        let response: serde_json::Value = result.unwrap();
430        assert_eq!(response["success"], true);
431        assert_eq!(response["session_id"], "test_session");
432
433        // Test listing PTY sessions
434        let args = serde_json::json!({});
435        let result = registry.execute_tool("list_pty_sessions", args).await;
436        assert!(result.is_ok());
437        let response: serde_json::Value = result.unwrap();
438        assert!(
439            response["sessions"]
440                .as_array()
441                .unwrap()
442                .contains(&"test_session".into())
443        );
444
445        // Test closing a PTY session
446        let args = serde_json::json!({
447            "session_id": "test_session"
448        });
449
450        let result = registry.execute_tool("close_pty_session", args).await;
451        assert!(result.is_ok());
452        let response: serde_json::Value = result.unwrap();
453        assert_eq!(response["success"], true);
454        assert_eq!(response["session_id"], "test_session");
455    }
456}