xynthe 0.1.0

A unified orchestration framework for autonomous intelligence with temporal continuity
Documentation
//! Capability Bindings example - demonstrates typed-safe tool integration
//!
//! Run with: cargo run --example capability_bindings

use xynthe::prelude::*;
use async_trait::async_trait;
use std::sync::Arc;

/// Mock Weather API capability
struct WeatherCapability {
    name: String,
    api_key: Option<String>,
}

impl WeatherCapability {
    fn new() -> Self {
        Self {
            name: "weather_api".to_string(),
            api_key: None,
        }
    }
}

#[async_trait]
impl Capability for WeatherCapability {
    fn name(&self) -> &str {
        &self.name
    }

    fn describe(&self) -> CapabilityContract {
        CapabilityContract::new()
            .with_precondition("location_specified")
            .with_precondition("valid_city_or_coords")
            .with_effect("returns_weather_data")
            .with_effect("network_request_made")
            .with_failure_mode("api_unreachable")
            .with_failure_mode("invalid_location")
            .with_failure_mode("rate_limit_exceeded")
            .build()
    }

    fn check_precondition(&self, precondition: &str, state: &StructuredContent) -> bool {
        match precondition {
            "location_specified" => {
                if let Some(obj) = state.as_json() {
                    return obj.get("location").is_some();
                }
                false
            }
            "valid_city_or_coords" => {
                if let Some(obj) = state.as_json() {
                    return obj.get("location").is_some();
                }
                false
            }
            _ => false,
        }
    }

    async fn invoke(&self, input: StructuredContent) -> Result<CapabilityResult> {
        // Simulate API call
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

        if let Some(obj) = input.as_json() {
            let location = obj.get("location").and_then(|v| v.as_str()).unwrap_or("unknown");

            // Simulate weather data
            let weather_data = serde_json::json!({
                "location": location,
                "temperature": 72,
                "unit": "fahrenheit",
                "condition": "sunny",
                "humidity": 65
            });

            Ok(CapabilityResult::success(StructuredContent::json(weather_data)))
        } else {
            Err(Error::CapabilityExecutionFailed("Invalid input format".into()))
        }
    }

    fn simulate(&self, input: &StructuredContent) -> Result<CapabilityResult> {
        // Fast simulation without side effects
        Ok(CapabilityResult::success(StructuredContent::json(
            serde_json::json!({
                "simulated": true,
                "location": input.as_json().and_then(|j| j.get("location")),
            })
        )))
    }

    async fn reflect(&self, traces: &[CapabilityTrace]) -> Result<StructuredContent> {
        let avg_duration = traces.iter()
            .filter(|t| t.metadata.success)
            .map(|t| t.metadata.duration_ms as f64)
            .sum::<f64>()
            / traces.len().max(1) as f64;

        let success_rate = traces.iter()
            .filter(|t| t.metadata.success)
            .count() as f64
            / traces.len().max(1) as f64;

        let reflection = serde_json::json!({
            "reflection": "Weather API performance analysis",
            "traces_analyzed": traces.len(),
            "success_rate": success_rate,
            "avg_duration_ms": avg_duration,
            "recommendation": if success_rate > 0.9 {
                "Maintain current API configuration"
            } else {
                "Investigate error patterns and improve reliability"
            }
        });

        Ok(StructuredContent::json(reflection))
    }
}

/// Calculator capability
struct CalculatorCapability {
    name: String,
}

impl CalculatorCapability {
    fn new() -> Self {
        Self {
            name: "calculator".to_string(),
        }
    }
}

#[async_trait]
impl Capability for CalculatorCapability {
    fn name(&self) -> &str {
        &self.name
    }

    fn describe(&self) -> CapabilityContract {
        CapabilityContract::new()
            .with_precondition("valid_expression")
            .with_effect("computes_result")
            .with_effect("pure_computation")
            .with_failure_mode("invalid_syntax")
            .with_failure_mode("division_by_zero")
            .build()
    }

    fn check_precondition(&self, precondition: &str, state: &StructuredContent) -> bool {
        match precondition {
            "valid_expression" => {
                state.as_json()
                    .and_then(|j| j.get("expression"))
                    .is_some()
            }
            _ => false,
        }
    }

    async fn invoke(&self, input: StructuredContent) -> Result<CapabilityResult> {
        if let Some(obj) = input.as_json() {
            if let Some(expr) = obj.get("expression").and_then(|v| v.as_str()) {
                // Simple expression parser (just for demo)
                if expr.contains("+") {
                    let parts: Vec<f64> = expr.split("+").filter_map(|s| s.trim().parse().ok()).collect();
                    let sum: f64 = parts.iter().sum();
                    return Ok(CapabilityResult::success(StructuredContent::json(
                        serde_json::json!({ "result": sum, "operation": "addition" })
                    ));
                }
            }
        }

        Err(Error::CapabilityExecutionFailed("Unsupported expression".into()))
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    println!("=== Xynthe Capability Bindings Example ===\n");

    // 1. Initialize capability registry
    println!("1. Initializing capability registry...");
    let registry = Arc::new(CapabilityRegistry::new());
    println!("   ✓ Registry created\n");

    // 2. Register capabilities
    println!("2. Registering capabilities...");

    let weather_cap = Arc::new(WeatherCapability::new()) as Arc<dyn Capability>;
    registry.register(weather_cap.clone()).await?;
    println!("   ✓ Weather API capability registered");

    let calc_cap = Arc::new(CalculatorCapability::new()) as Arc<dyn Capability>;
    registry.register(calc_cap.clone()).await?;
    println!("   ✓ Calculator capability registered\n");

    // 3. List registered capabilities
    println!("3. Listing registered capabilities:");
    let capabilities = registry.list().await;
    for (idx, cap_name) in capabilities.iter().enumerate() {
        let cap = registry.get(cap_name).await?;
        println!("   {}. {}", idx + 1, cap.name());
    }
    println!();

    // 4. Describe capability contracts
    println!("4. Inspecting capability contracts...");
    for cap_name in &capabilities {
        let cap = registry.get(cap_name).await?;
        let contract = cap.describe();

        println!("   Capability: {}", cap.name());
        println!("   Preconditions: {:?}", contract.preconditions);
        println!("   Effects: {:?}", contract.effects);
        println!("   Failure modes: {:?}", contract.failure_modes);
        println!();
    }

    // 5. Invoke Weather API capability
    println!("5. Invoking Weather API capability...");
    let weather_input = StructuredContent::json(serde_json::json!({
        "location": "San Francisco, CA"
    }));

    // Check preconditions
    let weather_cap = registry.get("weather_api").await?;
    if weather_cap.can_invoke(&weather_input) {
        let result = registry.invoke("weather_api", weather_input).await?;

        if result.is_success() {
            println!("   ✓ Weather API invocation successful");
            println!("   Result: {:?}\n", result.data().as_json());
        }
    } else {
        println!("   ✗ Preconditions not met\n");
    }

    // 6. Invoke Calculator capability
    println!("6. Invoking Calculator capability...");
    let calc_input = StructuredContent::json(serde_json::json!({
        "expression": "15 + 27"
    }));

    let calc_cap = registry.get("calculator").await?;
    if calc_cap.can_invoke(&calc_input) {
        let result = registry.invoke("calculator", calc_input).await?;

        if result.is_success() {
            println!("   ✓ Calculator invocation successful");
            println!("   Result: {:?}\n", result.data().as_json());
        }
    }

    // 7. Simulate capability execution
    println!("7. Simulating capability execution (no side effects)...");
    let weather_cap = registry.get("weather_api").await?;
    let sim_result = weather_cap.simulate(&StructuredContent::json(
        serde_json::json!({ "location": "New York, NY" })
    ))?;
    println!("   Simulation result: {:?}\n", sim_result.data().as_json());

    // 8. Reflect on execution traces
    println!("8. Reflecting on execution traces...");
    let traces = registry.traces().await;

    if !traces.is_empty() {
        let reflection = weather_cap.reflect(&traces).await?;
        println!("   Reflection analysis:");
        println!("   {:?}\n", reflection.as_json());
    }

    // 9. Verify trace recording
    println!("9. Verifying trace recording...");
    println!("   Total traces recorded: {}\n", traces.len());

    for (idx, trace) in traces.iter().enumerate() {
        println!("   Trace {}: {}", idx + 1, trace.capability_name);
        println!("     Success: {}", trace.success);
        println!("     Duration: {} ms", trace.metadata.duration_ms);
    }

    println!("\n=== Capability Bindings Example Completed ===\n");
    println!("Safety features demonstrated:");
    println!("  ✓ Precondition checking");
    println!("  ✓ Capability contracts");
    println!("  ✓ Failure mode definitions");
    println!("  ✓ Simulation support");
    println!("  ✓ Reflection and learning");
    println!("  ✓ Immutable trace recording");

    Ok(())
}