Implements Phase 9: Remoting / Cloud Hybrid Deployment with complete WebSocket transport support and comprehensive failover mechanisms. **WebSocket Transport (remote_client.rs):** - Added WebSocket support to RemoteMcpClient using tokio-tungstenite - Full bidirectional JSON-RPC communication over WebSocket - Connection establishment with error handling - Text/binary message support with proper encoding - Connection closure detection and error reporting **Failover & Redundancy (failover.rs - 323 lines):** - ServerHealth tracking: Healthy, Degraded, Down states - ServerEntry with priority-based selection (lower = higher priority) - FailoverMcpClient implementing McpClient trait - Automatic retry with exponential backoff - Circuit breaker pattern (5 consecutive failures triggers Down state) - Background health checking with configurable intervals - Graceful failover through server priority list **Configuration:** - FailoverConfig with tunable parameters: - max_retries: 3 (default) - base_retry_delay: 100ms with exponential backoff - health_check_interval: 30s - circuit_breaker_threshold: 5 failures **Testing (phase9_remoting.rs - 9 tests, all passing):** - Priority-based server selection - Automatic failover to backup servers - Retry mechanism with exponential backoff - Health status tracking and transitions - Background health checking - Circuit breaker behavior - Error handling for edge cases **Dependencies:** - tokio-tungstenite 0.21 - tungstenite 0.21 All tests pass successfully. Phase 9 specification fully implemented. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
98 lines
3.1 KiB
Rust
98 lines
3.1 KiB
Rust
//! Tool module aggregating built‑in tool implementations.
|
||
//!
|
||
//! The crate originally declared `pub mod tools;` in `lib.rs` but the source
|
||
//! directory only contained individual tool files without a `mod.rs`, causing the
|
||
//! compiler to look for `tools.rs` and fail. Adding this module file makes the
|
||
//! directory a proper Rust module and re‑exports the concrete tool types.
|
||
|
||
pub mod code_exec;
|
||
pub mod fs_tools;
|
||
pub mod registry;
|
||
pub mod web_scrape;
|
||
pub mod web_search;
|
||
pub mod web_search_detailed;
|
||
|
||
use async_trait::async_trait;
|
||
use serde_json::{json, Value};
|
||
use std::collections::HashMap;
|
||
use std::time::Duration;
|
||
|
||
use crate::Result;
|
||
|
||
/// Trait representing a tool that can be called via the MCP interface.
|
||
#[async_trait]
|
||
pub trait Tool: Send + Sync {
|
||
/// Unique name of the tool (used in the MCP protocol).
|
||
fn name(&self) -> &'static str;
|
||
/// Human‑readable description for documentation.
|
||
fn description(&self) -> &'static str;
|
||
/// JSON‑Schema describing the expected arguments.
|
||
fn schema(&self) -> Value;
|
||
/// Execute the tool with the provided arguments.
|
||
fn requires_network(&self) -> bool {
|
||
false
|
||
}
|
||
fn requires_filesystem(&self) -> Vec<String> {
|
||
Vec::new()
|
||
}
|
||
async fn execute(&self, args: Value) -> Result<ToolResult>;
|
||
}
|
||
|
||
/// Result returned by a tool execution.
|
||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||
pub struct ToolResult {
|
||
/// Indicates whether the tool completed successfully.
|
||
pub success: bool,
|
||
/// Human‑readable status string – retained for compatibility.
|
||
pub status: String,
|
||
/// Arbitrary JSON payload describing the tool output.
|
||
pub output: Value,
|
||
/// Execution duration.
|
||
#[serde(skip_serializing_if = "Duration::is_zero", default)]
|
||
pub duration: Duration,
|
||
/// Optional key/value metadata for the tool invocation.
|
||
#[serde(default)]
|
||
pub metadata: HashMap<String, String>,
|
||
}
|
||
|
||
impl ToolResult {
|
||
pub fn success(output: Value) -> Self {
|
||
Self {
|
||
success: true,
|
||
status: "success".into(),
|
||
output,
|
||
duration: Duration::default(),
|
||
metadata: HashMap::new(),
|
||
}
|
||
}
|
||
|
||
pub fn error(msg: &str) -> Self {
|
||
Self {
|
||
success: false,
|
||
status: "error".into(),
|
||
output: json!({ "error": msg }),
|
||
duration: Duration::default(),
|
||
metadata: HashMap::new(),
|
||
}
|
||
}
|
||
|
||
pub fn cancelled(msg: &str) -> Self {
|
||
Self {
|
||
success: false,
|
||
status: "cancelled".into(),
|
||
output: json!({ "error": msg }),
|
||
duration: Duration::default(),
|
||
metadata: HashMap::new(),
|
||
}
|
||
}
|
||
}
|
||
|
||
// Re‑export the most commonly used types so they can be accessed as
|
||
// `owlen_core::tools::CodeExecTool`, etc.
|
||
pub use code_exec::CodeExecTool;
|
||
pub use fs_tools::{ResourcesDeleteTool, ResourcesGetTool, ResourcesListTool, ResourcesWriteTool};
|
||
pub use registry::ToolRegistry;
|
||
pub use web_scrape::WebScrapeTool;
|
||
pub use web_search::WebSearchTool;
|
||
pub use web_search_detailed::WebSearchDetailedTool;
|