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:
2025-10-11 00:49:32 +02:00
parent 5c37df1b22
commit 40c44470e8
10 changed files with 55 additions and 65 deletions

View File

@@ -82,10 +82,9 @@ async fn test_agent_single_tool_scenario() {
model: "llama3.2".to_string(),
temperature: Some(0.7),
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
let result = executor
@@ -93,9 +92,12 @@ async fn test_agent_single_tool_scenario() {
.await;
match result {
Ok(answer) => {
assert!(!answer.is_empty(), "Answer should not be empty");
println!("Agent answer: {}", answer);
Ok(agent_result) => {
assert!(
!agent_result.answer.is_empty(),
"Answer should not be empty"
);
println!("Agent answer: {}", agent_result.answer);
}
Err(e) => {
// 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(),
temperature: Some(0.5), // Lower temperature for more consistent behavior
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
let result = executor
@@ -127,9 +128,9 @@ async fn test_agent_multi_step_workflow() {
.await;
match result {
Ok(answer) => {
assert!(!answer.is_empty());
println!("Multi-step answer: {}", answer);
Ok(agent_result) => {
assert!(!agent_result.answer.is_empty());
println!("Multi-step answer: {:?}", agent_result);
}
Err(e) => {
println!("Multi-step test skipped: {}", e);
@@ -148,10 +149,9 @@ async fn test_agent_iteration_limit() {
model: "llama3.2".to_string(),
temperature: Some(0.7),
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
let result = executor
@@ -186,14 +186,13 @@ async fn test_agent_tool_budget_enforcement() {
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
let config = AgentConfig {
max_iterations: 20,
max_iterations: 3, // Very low iteration limit to enforce budget
model: "llama3.2".to_string(),
temperature: Some(0.7),
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
let result = executor
@@ -238,7 +237,7 @@ fn create_test_executor() -> AgentExecutor {
let mcp_client = Arc::clone(&provider) as Arc<RemoteMcpClient>;
let config = AgentConfig::default();
AgentExecutor::new(provider, mcp_client, config, None)
AgentExecutor::new(provider, mcp_client, config)
}
#[test]
@@ -248,7 +247,7 @@ fn test_agent_config_defaults() {
assert_eq!(config.max_iterations, 10);
assert_eq!(config.model, "ollama");
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]
@@ -258,12 +257,10 @@ fn test_agent_config_custom() {
model: "custom-model".to_string(),
temperature: Some(0.5),
max_tokens: Some(2000),
max_tool_calls: 30,
};
assert_eq!(config.max_iterations, 15);
assert_eq!(config.model, "custom-model");
assert_eq!(config.temperature, Some(0.5));
assert_eq!(config.max_tokens, Some(2000));
assert_eq!(config.max_tool_calls, 30);
}

View File

@@ -235,7 +235,7 @@ impl AgentExecutor {
}
/// 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 mut thought = String::new();
let mut action = String::new();
@@ -370,8 +370,8 @@ mod tests {
#[test]
fn test_parse_tool_call() {
let executor = AgentExecutor {
llm_client: Arc::new(MockProvider::new()),
tool_client: Arc::new(MockMcpClient::new()),
llm_client: Arc::new(MockProvider),
tool_client: Arc::new(MockMcpClient),
config: AgentConfig::default(),
};
@@ -399,8 +399,8 @@ ACTION_INPUT: {"query": "Rust programming language"}
#[test]
fn test_parse_final_answer() {
let executor = AgentExecutor {
llm_client: Arc::new(MockProvider::new()),
tool_client: Arc::new(MockMcpClient::new()),
llm_client: Arc::new(MockProvider),
tool_client: Arc::new(MockMcpClient),
config: AgentConfig::default(),
};

View File

@@ -34,10 +34,15 @@ pub use credentials::*;
pub use encryption::*;
pub use formatting::*;
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 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 sandbox::*;
pub use session::*;

View File

@@ -149,14 +149,9 @@ pub mod test_utils {
use super::*;
/// Mock MCP client for testing
#[derive(Default)]
pub struct MockMcpClient;
impl MockMcpClient {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl McpClient for MockMcpClient {
async fn list_tools(&self) -> Result<Vec<McpToolDescriptor>> {

View File

@@ -181,14 +181,9 @@ pub mod test_utils {
use crate::types::{ChatRequest, ChatResponse, Message, ModelInfo, Role};
/// Mock provider for testing
#[derive(Default)]
pub struct MockProvider;
impl MockProvider {
pub fn new() -> Self {
Self
}
}
#[async_trait::async_trait]
impl Provider for MockProvider {
fn name(&self) -> &str {

View File

@@ -1,6 +1,5 @@
use owlen_core::mcp::client::McpClient;
use owlen_core::mcp::remote_client::RemoteMcpClient;
use owlen_core::mcp::McpToolCall;
use owlen_core::McpToolCall;
use std::fs::File;
use std::io::Write;
use tempfile::tempdir;
@@ -22,7 +21,7 @@ async fn remote_file_server_read_and_list() {
.join("../..")
.join("Cargo.toml");
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)
.status()
.expect("failed to run cargo build for MCP server");

View File

@@ -1,13 +1,12 @@
use owlen_core::mcp::client::McpClient;
use owlen_core::mcp::remote_client::RemoteMcpClient;
use owlen_core::mcp::McpToolCall;
use owlen_core::McpToolCall;
use tempfile::tempdir;
#[tokio::test]
async fn remote_write_and_delete() {
// Build the server binary first
let status = std::process::Command::new("cargo")
.args(&["build", "-p", "owlen-mcp-server"])
.args(["build", "-p", "owlen-mcp-server"])
.status()
.expect("failed to build MCP server");
assert!(status.success());
@@ -42,7 +41,7 @@ async fn remote_write_and_delete() {
async fn write_outside_root_is_rejected() {
// Build server (already built in previous test, but ensure it exists)
let status = std::process::Command::new("cargo")
.args(&["build", "-p", "owlen-mcp-server"])
.args(["build", "-p", "owlen-mcp-server"])
.status()
.expect("failed to build MCP server");
assert!(status.success());

View File

@@ -42,14 +42,16 @@ impl Tool for EchoTool {
#[tokio::test]
async fn test_tool_allowed_in_chat_mode() {
// Build a config where the `echo` tool is explicitly allowed in chat.
let mut cfg = Config::default();
cfg.modes = ModeConfig {
chat: ModeToolConfig {
allowed_tools: vec!["echo".to_string()],
},
code: ModeToolConfig {
allowed_tools: vec!["*".to_string()],
let cfg = Config {
modes: ModeConfig {
chat: ModeToolConfig {
allowed_tools: vec!["echo".to_string()],
},
code: ModeToolConfig {
allowed_tools: vec!["*".to_string()],
},
},
..Default::default()
};
let cfg = Arc::new(Mutex::new(cfg));
@@ -70,17 +72,18 @@ async fn test_tool_allowed_in_chat_mode() {
#[tokio::test]
async fn test_tool_not_allowed_in_any_mode() {
// Config that does NOT list `echo` in either mode.
let mut cfg = Config::default();
cfg.modes = ModeConfig {
chat: ModeToolConfig {
allowed_tools: vec!["web_search".to_string()],
},
code: ModeToolConfig {
allowed_tools: vec!["*".to_string()], // allow all in code
let cfg = Config {
modes: ModeConfig {
chat: ModeToolConfig {
allowed_tools: vec!["web_search".to_string()],
},
code: ModeToolConfig {
// 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 ui: Arc<dyn UiController> = Arc::new(NoOpUiController);

View File

@@ -12,9 +12,6 @@ serde_json = "1.0"
anyhow = "1.0"
tokio-stream = "0.1"
[lib]
path = "src/lib.rs"
[[bin]]
name = "owlen-mcp-llm-server"
path = "src/lib.rs"
path = "src/main.rs"