ubiquity-core 0.1.1

Core types and traits for Ubiquity consciousness-aware mesh
Documentation
//! Example demonstrating the unified command execution system

use futures::StreamExt;
use std::time::Duration;
use tracing::{info, Level};
use tracing_subscriber;
use ubiquity_core::{
    CommandEvent, ExecutionMode, UnifiedCommandExecutor, UnifiedExecutorConfig,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize tracing
    tracing_subscriber::fmt()
        .with_max_level(Level::INFO)
        .init();

    info!("Starting command execution example");

    // Example 1: Auto-detect execution mode
    example_auto_mode().await?;

    // Example 2: Stream command output
    example_streaming().await?;

    // Example 3: Collect complete output
    example_output_collection().await?;

    // Example 4: Command with timeout
    example_timeout().await?;

    // Example 5: Command cancellation
    example_cancellation().await?;

    // Example 6: Cloud execution (if configured)
    example_cloud_execution().await?;

    Ok(())
}

async fn example_auto_mode() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 1: Auto-detect execution mode ===");

    let executor = UnifiedCommandExecutor::auto()?;
    info!("Detected execution mode: {:?}", executor.mode());

    let output = executor
        .command("echo")
        .args(["Hello", "from", "Ubiquity!"])
        .output()
        .await?;

    info!("Command output: {}", output.stdout);
    info!("Success: {}", output.success);

    Ok(())
}

async fn example_streaming() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 2: Stream command output ===");

    let executor = UnifiedCommandExecutor::auto()?;
    let mut stream = executor
        .command("ls")
        .arg("-la")
        .execute()
        .await?;

    while let Some(event) = stream.next().await {
        match event {
            CommandEvent::Started { command, args, .. } => {
                info!("Started: {} {:?}", command, args);
            }
            CommandEvent::Stdout { data, .. } => {
                info!("STDOUT: {}", data);
            }
            CommandEvent::Stderr { data, .. } => {
                info!("STDERR: {}", data);
            }
            CommandEvent::Progress { percentage, message, .. } => {
                info!("Progress: {}% - {}", percentage, message);
            }
            CommandEvent::Completed { exit_code, duration_ms, .. } => {
                info!("Completed with exit code {} in {}ms", exit_code, duration_ms);
            }
            CommandEvent::Failed { error, .. } => {
                info!("Failed: {}", error);
            }
            CommandEvent::Cancelled { .. } => {
                info!("Cancelled");
            }
        }
    }

    Ok(())
}

async fn example_output_collection() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 3: Collect complete output ===");

    let executor = UnifiedCommandExecutor::auto()?;
    
    // Execute with environment variables and working directory
    let output = executor
        .command("echo")
        .arg("$USER")
        .env("USER", "ubiquity-user")
        .current_dir("/tmp")
        .output()
        .await?;

    info!("STDOUT: {}", output.stdout);
    info!("STDERR: {}", output.stderr);
    info!("Exit code: {:?}", output.exit_code);
    info!("Duration: {:?}ms", output.duration_ms);

    Ok(())
}

async fn example_timeout() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 4: Command with timeout ===");

    let executor = UnifiedCommandExecutor::auto()?;
    
    // This will timeout
    let result = executor
        .command("sleep")
        .arg("10")
        .timeout(Duration::from_millis(500))
        .output()
        .await;

    match result {
        Ok(output) => {
            info!("Command completed: success={}", output.success);
        }
        Err(e) => {
            info!("Command failed (expected timeout): {}", e);
        }
    }

    Ok(())
}

async fn example_cancellation() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 5: Command cancellation ===");

    let executor = UnifiedCommandExecutor::auto()?;
    
    let request = executor
        .command("sleep")
        .arg("5")
        .execute()
        .await?;
    
    let mut stream = request;
    let command_id = uuid::Uuid::new_v4(); // In real usage, get from the first event

    // Spawn a task to cancel after 1 second
    let executor_clone = UnifiedCommandExecutor::auto()?;
    tokio::spawn(async move {
        tokio::time::sleep(Duration::from_secs(1)).await;
        info!("Sending cancel signal...");
        // Note: In real usage, you'd track the command_id from the Started event
        // This is simplified for the example
    });

    // Collect events
    let mut cancelled = false;
    while let Some(event) = stream.next().await {
        match event {
            CommandEvent::Started { command_id: id, .. } => {
                info!("Started command {}", id);
            }
            CommandEvent::Cancelled { .. } => {
                info!("Command was cancelled");
                cancelled = true;
                break;
            }
            _ => {}
        }
    }

    info!("Cancellation example completed");

    Ok(())
}

async fn example_cloud_execution() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Example 6: Cloud execution (if configured) ===");

    // Check if cloud configuration is available
    if std::env::var("UBIQUITY_CLOUD_WORKER_URL").is_err() {
        info!("Skipping cloud execution example (not configured)");
        info!("Set UBIQUITY_CLOUD_WORKER_URL, UBIQUITY_CLOUD_API_TOKEN, and UBIQUITY_CLOUD_NAMESPACE_ID to enable");
        return Ok(());
    }

    let config = UnifiedExecutorConfig {
        mode: ExecutionMode::Cloud,
        cloud_worker_url: std::env::var("UBIQUITY_CLOUD_WORKER_URL").ok(),
        cloud_api_token: std::env::var("UBIQUITY_CLOUD_API_TOKEN").ok(),
        cloud_namespace_id: std::env::var("UBIQUITY_CLOUD_NAMESPACE_ID").ok(),
        ..Default::default()
    };

    let executor = UnifiedCommandExecutor::new(config)?;
    
    let output = executor
        .command("echo")
        .args(["Hello", "from", "the", "cloud!"])
        .output()
        .await?;

    info!("Cloud output: {}", output.stdout);

    Ok(())
}

// Example of custom command processing
async fn process_with_progress() -> Result<(), Box<dyn std::error::Error>> {
    info!("\n=== Custom command processing with progress ===");

    let executor = UnifiedCommandExecutor::auto()?;
    let mut stream = executor
        .command("grep")
        .args(["pattern", "file.txt"])
        .execute()
        .await?;

    let mut progress = 0.0;
    while let Some(event) = stream.next().await {
        match event {
            CommandEvent::Progress { percentage, message, .. } => {
                progress = percentage;
                info!("Processing: {}% - {}", percentage, message);
                
                // Update UI progress bar here
            }
            CommandEvent::Stdout { data, .. } => {
                // Process each matching line
                info!("Match found: {}", data);
            }
            _ => {}
        }
    }

    info!("Final progress: {}%", progress);

    Ok(())
}