fix: resolve all compilation errors and clippy warnings
This commit fixes 12 categories of errors across the codebase: - Fix owlen-mcp-llm-server build target conflict by renaming lib.rs to main.rs - Resolve ambiguous glob re-exports in owlen-core by using explicit exports - Add Default derive to MockMcpClient and MockProvider test utilities - Remove unused imports from owlen-core test files - Fix needless borrows in test file arguments - Improve Config initialization style in mode_tool_filter tests - Make AgentExecutor::parse_response public for testing - Remove non-existent max_tool_calls field from AgentConfig usage - Fix AgentExecutor::new calls to use correct 3-argument signature - Fix AgentResult field access in agent tests - Use Debug formatting instead of Display for AgentResult - Remove unnecessary default() calls on unit structs All changes ensure the project compiles cleanly with: - cargo check --all-targets ✓ - cargo clippy --all-targets -- -D warnings ✓ - cargo test --no-run ✓ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -82,10 +82,9 @@ async fn test_agent_single_tool_scenario() {
|
|||||||
model: "llama3.2".to_string(),
|
model: "llama3.2".to_string(),
|
||||||
temperature: Some(0.7),
|
temperature: Some(0.7),
|
||||||
max_tokens: None,
|
max_tokens: None,
|
||||||
max_tool_calls: 10,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let executor = AgentExecutor::new(provider, mcp_client, config, None);
|
let executor = AgentExecutor::new(provider, mcp_client, config);
|
||||||
|
|
||||||
// Simple query that should complete in one tool call
|
// Simple query that should complete in one tool call
|
||||||
let result = executor
|
let result = executor
|
||||||
@@ -93,9 +92,12 @@ async fn test_agent_single_tool_scenario() {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(answer) => {
|
Ok(agent_result) => {
|
||||||
assert!(!answer.is_empty(), "Answer should not be empty");
|
assert!(
|
||||||
println!("Agent answer: {}", answer);
|
!agent_result.answer.is_empty(),
|
||||||
|
"Answer should not be empty"
|
||||||
|
);
|
||||||
|
println!("Agent answer: {}", agent_result.answer);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// It's okay if this fails due to LLM not following format
|
// It's okay if this fails due to LLM not following format
|
||||||
@@ -116,10 +118,9 @@ async fn test_agent_multi_step_workflow() {
|
|||||||
model: "llama3.2".to_string(),
|
model: "llama3.2".to_string(),
|
||||||
temperature: Some(0.5), // Lower temperature for more consistent behavior
|
temperature: Some(0.5), // Lower temperature for more consistent behavior
|
||||||
max_tokens: None,
|
max_tokens: None,
|
||||||
max_tool_calls: 20,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let executor = AgentExecutor::new(provider, mcp_client, config, None);
|
let executor = AgentExecutor::new(provider, mcp_client, config);
|
||||||
|
|
||||||
// Query requiring multiple steps: list -> read -> analyze
|
// Query requiring multiple steps: list -> read -> analyze
|
||||||
let result = executor
|
let result = executor
|
||||||
@@ -127,9 +128,9 @@ async fn test_agent_multi_step_workflow() {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(answer) => {
|
Ok(agent_result) => {
|
||||||
assert!(!answer.is_empty());
|
assert!(!agent_result.answer.is_empty());
|
||||||
println!("Multi-step answer: {}", answer);
|
println!("Multi-step answer: {:?}", agent_result);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Multi-step test skipped: {}", e);
|
println!("Multi-step test skipped: {}", e);
|
||||||
@@ -148,10 +149,9 @@ async fn test_agent_iteration_limit() {
|
|||||||
model: "llama3.2".to_string(),
|
model: "llama3.2".to_string(),
|
||||||
temperature: Some(0.7),
|
temperature: Some(0.7),
|
||||||
max_tokens: None,
|
max_tokens: None,
|
||||||
max_tool_calls: 5,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let executor = AgentExecutor::new(provider, mcp_client, config, None);
|
let executor = AgentExecutor::new(provider, mcp_client, config);
|
||||||
|
|
||||||
// Complex query that would require many iterations
|
// Complex query that would require many iterations
|
||||||
let result = executor
|
let result = executor
|
||||||
@@ -186,14 +186,13 @@ async fn test_agent_tool_budget_enforcement() {
|
|||||||
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
|
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
|
||||||
|
|
||||||
let config = AgentConfig {
|
let config = AgentConfig {
|
||||||
max_iterations: 20,
|
max_iterations: 3, // Very low iteration limit to enforce budget
|
||||||
model: "llama3.2".to_string(),
|
model: "llama3.2".to_string(),
|
||||||
temperature: Some(0.7),
|
temperature: Some(0.7),
|
||||||
max_tokens: None,
|
max_tokens: None,
|
||||||
max_tool_calls: 3, // Very low tool call budget
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let executor = AgentExecutor::new(provider, mcp_client, config, None);
|
let executor = AgentExecutor::new(provider, mcp_client, config);
|
||||||
|
|
||||||
// Query that would require many tool calls
|
// Query that would require many tool calls
|
||||||
let result = executor
|
let result = executor
|
||||||
@@ -238,7 +237,7 @@ fn create_test_executor() -> AgentExecutor {
|
|||||||
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
|
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
|
||||||
|
|
||||||
let config = AgentConfig::default();
|
let config = AgentConfig::default();
|
||||||
AgentExecutor::new(provider, mcp_client, config, None)
|
AgentExecutor::new(provider, mcp_client, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -248,7 +247,7 @@ fn test_agent_config_defaults() {
|
|||||||
assert_eq!(config.max_iterations, 10);
|
assert_eq!(config.max_iterations, 10);
|
||||||
assert_eq!(config.model, "ollama");
|
assert_eq!(config.model, "ollama");
|
||||||
assert_eq!(config.temperature, Some(0.7));
|
assert_eq!(config.temperature, Some(0.7));
|
||||||
assert_eq!(config.max_tool_calls, 20);
|
// max_tool_calls field removed - agent now tracks iterations instead
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -258,12 +257,10 @@ fn test_agent_config_custom() {
|
|||||||
model: "custom-model".to_string(),
|
model: "custom-model".to_string(),
|
||||||
temperature: Some(0.5),
|
temperature: Some(0.5),
|
||||||
max_tokens: Some(2000),
|
max_tokens: Some(2000),
|
||||||
max_tool_calls: 30,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(config.max_iterations, 15);
|
assert_eq!(config.max_iterations, 15);
|
||||||
assert_eq!(config.model, "custom-model");
|
assert_eq!(config.model, "custom-model");
|
||||||
assert_eq!(config.temperature, Some(0.5));
|
assert_eq!(config.temperature, Some(0.5));
|
||||||
assert_eq!(config.max_tokens, Some(2000));
|
assert_eq!(config.max_tokens, Some(2000));
|
||||||
assert_eq!(config.max_tool_calls, 30);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ impl AgentExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse LLM response into structured format
|
/// Parse LLM response into structured format
|
||||||
fn parse_response(&self, text: &str) -> Result<LlmResponse> {
|
pub fn parse_response(&self, text: &str) -> Result<LlmResponse> {
|
||||||
let lines: Vec<&str> = text.lines().collect();
|
let lines: Vec<&str> = text.lines().collect();
|
||||||
let mut thought = String::new();
|
let mut thought = String::new();
|
||||||
let mut action = String::new();
|
let mut action = String::new();
|
||||||
@@ -370,8 +370,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_tool_call() {
|
fn test_parse_tool_call() {
|
||||||
let executor = AgentExecutor {
|
let executor = AgentExecutor {
|
||||||
llm_client: Arc::new(MockProvider::new()),
|
llm_client: Arc::new(MockProvider),
|
||||||
tool_client: Arc::new(MockMcpClient::new()),
|
tool_client: Arc::new(MockMcpClient),
|
||||||
config: AgentConfig::default(),
|
config: AgentConfig::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -399,8 +399,8 @@ ACTION_INPUT: {"query": "Rust programming language"}
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_final_answer() {
|
fn test_parse_final_answer() {
|
||||||
let executor = AgentExecutor {
|
let executor = AgentExecutor {
|
||||||
llm_client: Arc::new(MockProvider::new()),
|
llm_client: Arc::new(MockProvider),
|
||||||
tool_client: Arc::new(MockMcpClient::new()),
|
tool_client: Arc::new(MockMcpClient),
|
||||||
config: AgentConfig::default(),
|
config: AgentConfig::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,15 @@ pub use credentials::*;
|
|||||||
pub use encryption::*;
|
pub use encryption::*;
|
||||||
pub use formatting::*;
|
pub use formatting::*;
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
pub use mcp::*;
|
// Export MCP types but exclude test_utils to avoid ambiguity
|
||||||
|
pub use mcp::{
|
||||||
|
client, factory, failover, permission, protocol, remote_client, LocalMcpClient, McpServer,
|
||||||
|
McpToolCall, McpToolDescriptor, McpToolResponse,
|
||||||
|
};
|
||||||
pub use mode::*;
|
pub use mode::*;
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
pub use provider::*;
|
// Export provider types but exclude test_utils to avoid ambiguity
|
||||||
|
pub use provider::{ChatStream, Provider, ProviderConfig, ProviderRegistry};
|
||||||
pub use router::*;
|
pub use router::*;
|
||||||
pub use sandbox::*;
|
pub use sandbox::*;
|
||||||
pub use session::*;
|
pub use session::*;
|
||||||
|
|||||||
@@ -149,14 +149,9 @@ pub mod test_utils {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Mock MCP client for testing
|
/// Mock MCP client for testing
|
||||||
|
#[derive(Default)]
|
||||||
pub struct MockMcpClient;
|
pub struct MockMcpClient;
|
||||||
|
|
||||||
impl MockMcpClient {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl McpClient for MockMcpClient {
|
impl McpClient for MockMcpClient {
|
||||||
async fn list_tools(&self) -> Result<Vec<McpToolDescriptor>> {
|
async fn list_tools(&self) -> Result<Vec<McpToolDescriptor>> {
|
||||||
|
|||||||
@@ -181,14 +181,9 @@ pub mod test_utils {
|
|||||||
use crate::types::{ChatRequest, ChatResponse, Message, ModelInfo, Role};
|
use crate::types::{ChatRequest, ChatResponse, Message, ModelInfo, Role};
|
||||||
|
|
||||||
/// Mock provider for testing
|
/// Mock provider for testing
|
||||||
|
#[derive(Default)]
|
||||||
pub struct MockProvider;
|
pub struct MockProvider;
|
||||||
|
|
||||||
impl MockProvider {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Provider for MockProvider {
|
impl Provider for MockProvider {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use owlen_core::mcp::client::McpClient;
|
|
||||||
use owlen_core::mcp::remote_client::RemoteMcpClient;
|
use owlen_core::mcp::remote_client::RemoteMcpClient;
|
||||||
use owlen_core::mcp::McpToolCall;
|
use owlen_core::McpToolCall;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
@@ -22,7 +21,7 @@ async fn remote_file_server_read_and_list() {
|
|||||||
.join("../..")
|
.join("../..")
|
||||||
.join("Cargo.toml");
|
.join("Cargo.toml");
|
||||||
let build_status = std::process::Command::new("cargo")
|
let build_status = std::process::Command::new("cargo")
|
||||||
.args(&["build", "-p", "owlen-mcp-server", "--manifest-path"])
|
.args(["build", "-p", "owlen-mcp-server", "--manifest-path"])
|
||||||
.arg(manifest_path)
|
.arg(manifest_path)
|
||||||
.status()
|
.status()
|
||||||
.expect("failed to run cargo build for MCP server");
|
.expect("failed to run cargo build for MCP server");
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use owlen_core::mcp::client::McpClient;
|
|
||||||
use owlen_core::mcp::remote_client::RemoteMcpClient;
|
use owlen_core::mcp::remote_client::RemoteMcpClient;
|
||||||
use owlen_core::mcp::McpToolCall;
|
use owlen_core::McpToolCall;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn remote_write_and_delete() {
|
async fn remote_write_and_delete() {
|
||||||
// Build the server binary first
|
// Build the server binary first
|
||||||
let status = std::process::Command::new("cargo")
|
let status = std::process::Command::new("cargo")
|
||||||
.args(&["build", "-p", "owlen-mcp-server"])
|
.args(["build", "-p", "owlen-mcp-server"])
|
||||||
.status()
|
.status()
|
||||||
.expect("failed to build MCP server");
|
.expect("failed to build MCP server");
|
||||||
assert!(status.success());
|
assert!(status.success());
|
||||||
@@ -42,7 +41,7 @@ async fn remote_write_and_delete() {
|
|||||||
async fn write_outside_root_is_rejected() {
|
async fn write_outside_root_is_rejected() {
|
||||||
// Build server (already built in previous test, but ensure it exists)
|
// Build server (already built in previous test, but ensure it exists)
|
||||||
let status = std::process::Command::new("cargo")
|
let status = std::process::Command::new("cargo")
|
||||||
.args(&["build", "-p", "owlen-mcp-server"])
|
.args(["build", "-p", "owlen-mcp-server"])
|
||||||
.status()
|
.status()
|
||||||
.expect("failed to build MCP server");
|
.expect("failed to build MCP server");
|
||||||
assert!(status.success());
|
assert!(status.success());
|
||||||
|
|||||||
@@ -42,14 +42,16 @@ impl Tool for EchoTool {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_tool_allowed_in_chat_mode() {
|
async fn test_tool_allowed_in_chat_mode() {
|
||||||
// Build a config where the `echo` tool is explicitly allowed in chat.
|
// Build a config where the `echo` tool is explicitly allowed in chat.
|
||||||
let mut cfg = Config::default();
|
let cfg = Config {
|
||||||
cfg.modes = ModeConfig {
|
modes: ModeConfig {
|
||||||
chat: ModeToolConfig {
|
chat: ModeToolConfig {
|
||||||
allowed_tools: vec!["echo".to_string()],
|
allowed_tools: vec!["echo".to_string()],
|
||||||
},
|
},
|
||||||
code: ModeToolConfig {
|
code: ModeToolConfig {
|
||||||
allowed_tools: vec!["*".to_string()],
|
allowed_tools: vec!["*".to_string()],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let cfg = Arc::new(Mutex::new(cfg));
|
let cfg = Arc::new(Mutex::new(cfg));
|
||||||
|
|
||||||
@@ -70,17 +72,18 @@ async fn test_tool_allowed_in_chat_mode() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_tool_not_allowed_in_any_mode() {
|
async fn test_tool_not_allowed_in_any_mode() {
|
||||||
// Config that does NOT list `echo` in either mode.
|
// Config that does NOT list `echo` in either mode.
|
||||||
let mut cfg = Config::default();
|
let cfg = Config {
|
||||||
cfg.modes = ModeConfig {
|
modes: ModeConfig {
|
||||||
chat: ModeToolConfig {
|
chat: ModeToolConfig {
|
||||||
allowed_tools: vec!["web_search".to_string()],
|
allowed_tools: vec!["web_search".to_string()],
|
||||||
},
|
},
|
||||||
code: ModeToolConfig {
|
code: ModeToolConfig {
|
||||||
allowed_tools: vec!["*".to_string()], // allow all in code
|
// Strict denial - only web_search allowed
|
||||||
|
allowed_tools: vec!["web_search".to_string()],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
// Remove the wildcard for code to simulate strict denial.
|
|
||||||
cfg.modes.code.allowed_tools = vec!["web_search".to_string()];
|
|
||||||
let cfg = Arc::new(Mutex::new(cfg));
|
let cfg = Arc::new(Mutex::new(cfg));
|
||||||
|
|
||||||
let ui: Arc<dyn UiController> = Arc::new(NoOpUiController);
|
let ui: Arc<dyn UiController> = Arc::new(NoOpUiController);
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ serde_json = "1.0"
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/lib.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "owlen-mcp-llm-server"
|
name = "owlen-mcp-llm-server"
|
||||||
path = "src/lib.rs"
|
path = "src/main.rs"
|
||||||
|
|||||||
Reference in New Issue
Block a user