Skip to main content

cats/
lib.rs

1//! # CATS - Coding Agent ToolS
2//!
3//! A comprehensive toolkit for building AI-powered coding agents.
4//! This crate provides structured, LLM-friendly tools for software engineering tasks.
5//!
6//! ## Features
7//!
8//! - **File Navigation**: Windowed file viewing, line navigation, scrolling
9//! - **Search Tools**: File discovery, content search across files and directories
10//! - **File Editing**: Search/replace editing with integrated linting
11//! - **State Management**: Persistent tool state and session history
12//! - **Utility Tools**: Project structure visualization, task submission
13//! - **LLM Integration**: JSON conversion, tool execution, result handling for LLM providers
14//!
15//! ## Tool Sets
16//!
17//! CATS supports multiple tool sets via feature flags:
18//!
19//! - `old` (default): Original CATS tools
20//! - `opencode`: OpenCode-compatible tools
21//! - `gemini-cli`: Google Gemini CLI tools (coming soon)
22//! - `claude-code`: Claude Code-compatible tools (coming soon)
23//!
24//! ## Usage
25//!
26//! ```rust,no_run
27//! use cats::{create_tool_registry, ToolArgs};
28//!
29//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
30//! let mut registry = create_tool_registry();
31//! let result = registry.execute_tool("_state", &ToolArgs::from_args(&[]))?;
32//! println!("{}", result.message);
33//! # Ok(())
34//! # }
35//! ```
36
37pub mod core;
38pub mod llm;
39pub mod state;
40pub mod tools;
41
42// Re-export main types
43pub use core::{Tool, ToolArgs, ToolRegistry, ToolResult};
44
45// Re-export state types
46pub use state::{FileState, StateSnapshot, ToolState};
47
48// Re-export tools from the active tool set
49#[cfg(feature = "old")]
50pub use tools::old::{
51    // Editing tools
52    CopyPathTool, CreateDirectoryTool, CreateFileTool, DeleteFunctionTool, DeleteLineTool,
53    DeletePathTool, DeleteTextTool, InsertTextTool, MovePathTool, OverwriteFileTool,
54    ReplaceTextTool,
55    // Execution tools
56    RunCommandTool,
57    // File navigation tools
58    CreateTool, GotoTool, OpenTool, ScrollTool, WindowedFile,
59    // Search tools
60    ConfigurableFilter, FindFileTool, SearchDirTool, SearchFileTool,
61    // State tools
62    StateTool,
63    // Utility tools
64    ClassifyTaskTool, CountTokensTool, FilemapTool, SubmitTool,
65};
66
67// Re-export opencode tools
68#[cfg(feature = "opencode")]
69pub use tools::opencode::{
70    BashTool, EditTool, GlobTool, GrepTool, ListTool, MultiEditTool, ReadTool, TodoReadTool,
71    TodoWriteTool, WebFetchTool, WebSearchTool, WriteTool,
72};
73
74// Re-export LLM integration
75pub use llm::{
76    assistant::{generate_assistant_content, ToolCallInfo},
77    converter::json_to_tool_args,
78    executor::{
79        execute_tool_calls, execute_tool_calls_structured, ExecutionCallback, NoOpCallback,
80        ToolCallRequest, ToolExecutionResult,
81    },
82    result_handler::{handle_large_result, ResultHandlerConfig},
83};
84
85// Re-export create_tool_registry functions from the active tool set
86#[cfg(all(feature = "old", not(feature = "opencode")))]
87pub use tools::old::{create_tool_registry, create_tool_registry_with_open_window_size};
88
89#[cfg(feature = "opencode")]
90pub use tools::opencode::{create_tool_registry, create_tool_registry_with_open_window_size};
91
92#[cfg(all(test, feature = "old", not(feature = "opencode")))]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_registry_creation() {
98        let registry = create_tool_registry();
99
100        // Test that all expected tools are registered
101        let tool_names = registry.list_tools();
102
103        // File navigation tools
104        assert!(tool_names.contains(&"open".to_string()));
105        assert!(tool_names.contains(&"goto".to_string()));
106        assert!(tool_names.contains(&"scroll_up".to_string()));
107        assert!(tool_names.contains(&"scroll_down".to_string()));
108        assert!(tool_names.contains(&"create".to_string()));
109
110        // Command execution tool
111        assert!(tool_names.contains(&"run_command".to_string()));
112
113        // Search tools
114        assert!(tool_names.contains(&"find_file".to_string()));
115        assert!(tool_names.contains(&"search_file".to_string()));
116        assert!(tool_names.contains(&"search_dir".to_string()));
117
118        // Editing tools - New specialized tools
119        assert!(tool_names.contains(&"create_file".to_string()));
120        assert!(tool_names.contains(&"replace_text".to_string()));
121        assert!(tool_names.contains(&"insert_text".to_string()));
122        assert!(tool_names.contains(&"delete_text".to_string()));
123        assert!(tool_names.contains(&"delete_line".to_string()));
124        assert!(tool_names.contains(&"overwrite_file".to_string()));
125
126        // File management tools
127        assert!(tool_names.contains(&"delete_path".to_string()));
128        assert!(tool_names.contains(&"move_path".to_string()));
129        assert!(tool_names.contains(&"copy_path".to_string()));
130        assert!(tool_names.contains(&"create_directory".to_string()));
131
132        // State and utility tools
133        assert!(tool_names.contains(&"_state".to_string()));
134        assert!(tool_names.contains(&"count_tokens".to_string()));
135        assert!(tool_names.contains(&"filemap".to_string()));
136        assert!(tool_names.contains(&"submit".to_string()));
137        assert!(tool_names.contains(&"classify_task".to_string()));
138    }
139}
140
141#[cfg(all(test, feature = "opencode"))]
142mod opencode_tests {
143    use super::*;
144
145    #[test]
146    fn test_opencode_registry_creation() {
147        let registry = create_tool_registry();
148
149        // Test that all expected opencode tools are registered
150        let tool_names = registry.list_tools();
151
152        // Core tools
153        assert!(tool_names.contains(&"bash".to_string()));
154        assert!(tool_names.contains(&"read".to_string()));
155        assert!(tool_names.contains(&"write".to_string()));
156        assert!(tool_names.contains(&"edit".to_string()));
157        assert!(tool_names.contains(&"glob".to_string()));
158        assert!(tool_names.contains(&"grep".to_string()));
159        assert!(tool_names.contains(&"list".to_string()));
160        
161        // Extended tools
162        assert!(tool_names.contains(&"multiedit".to_string()));
163        assert!(tool_names.contains(&"webfetch".to_string()));
164        assert!(tool_names.contains(&"websearch".to_string()));
165        assert!(tool_names.contains(&"todowrite".to_string()));
166        assert!(tool_names.contains(&"todoread".to_string()));
167    }
168}