Files
owlen/crates/owlen-core/src/tools.rs
vikingowl cdf95002fc feat(phase9): implement WebSocket transport and failover system
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>
2025-10-10 20:43:21 +02:00

98 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Tool module aggregating builtin 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 reexports 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;
/// Humanreadable description for documentation.
fn description(&self) -> &'static str;
/// JSONSchema 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,
/// Humanreadable 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(),
}
}
}
// Reexport 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;