aprender-orchestrate 0.30.0

Sovereign AI orchestration: autonomous agents, ML serving, code analysis, and transpilation pipelines
Documentation
//! Agent pool and status command handlers.
//!
//! Extracted from `agent_runtime_cmds.rs` for QA-002 compliance (≤500 lines).

use std::path::PathBuf;
use std::sync::Arc;

use crate::ansi_colors::Colorize;

use super::agent_helpers::{build_driver, build_memory, load_manifest, print_manifest_summary};

/// Fan-out multiple agents and collect results.
pub(super) fn cmd_agent_pool(
    manifest_paths: &[PathBuf],
    prompt: &str,
    concurrency: Option<usize>,
) -> anyhow::Result<()> {
    use batuta::agent::pool::{AgentPool, SpawnConfig};

    let manifests: Vec<batuta::agent::AgentManifest> =
        manifest_paths.iter().map(load_manifest).collect::<Result<_, _>>()?;

    let max_concurrent = concurrency.unwrap_or(manifests.len());

    println!("{} Multi-Agent Pool", "🔀".bright_cyan().bold());
    println!("{}", "".repeat(60).dimmed());
    println!("  Agents: {}  Concurrency: {}", manifests.len(), max_concurrent,);
    println!("  Prompt: {}", prompt.bright_yellow());
    println!();

    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .map_err(|e| anyhow::anyhow!("tokio runtime: {e}"))?;

    let driver =
        build_driver(manifests.first().unwrap_or(&batuta::agent::AgentManifest::default()))?;
    let driver: Arc<dyn batuta::agent::driver::LlmDriver> = Arc::from(driver);
    let memory: Arc<dyn batuta::agent::memory::MemorySubstrate> = Arc::from(build_memory());

    let configs: Vec<SpawnConfig> = manifests
        .iter()
        .map(|m| SpawnConfig { manifest: m.clone(), query: prompt.to_string() })
        .collect();

    let agent_count = configs.len();

    rt.block_on(async {
        let mut pool = AgentPool::new(driver, max_concurrent).with_memory(memory);

        println!("{} Spawning {} agents...", "".bright_green(), agent_count,);

        let ids = pool.fan_out(configs).map_err(|e| anyhow::anyhow!("pool fan-out: {e}"))?;
        for id in &ids {
            println!("  {} Agent {id} spawned", "".bright_blue(),);
        }
        println!();

        println!("{} Waiting for results...", "".bright_blue(),);
        let results = pool.join_all().await;

        println!();
        println!("{} Results ({}/{})", "".green(), results.len(), ids.len(),);
        println!("{}", "".repeat(60).dimmed());

        for (id, result) in &results {
            match result {
                Ok(r) => {
                    println!("  {} Agent {id}: {}", "".green(), r.text,);
                    println!(
                        "    {}",
                        format!(
                            "[iter={}, tools={}, tokens={}/{}]",
                            r.iterations, r.tool_calls, r.usage.input_tokens, r.usage.output_tokens,
                        )
                        .dimmed()
                    );
                }
                Err(e) => {
                    println!("  {} Agent {id}: {e}", "".bright_red(),);
                }
            }
        }

        Ok::<(), anyhow::Error>(())
    })?;

    Ok(())
}

/// Display agent manifest status and configuration.
pub(super) fn cmd_agent_status(manifest_path: &PathBuf) -> anyhow::Result<()> {
    let manifest = load_manifest(manifest_path)?;
    if let Err(errors) = manifest.validate() {
        println!("{} Manifest has validation errors:", "".bright_yellow());
        for e in &errors {
            println!("  {} {e}", "".red());
        }
        println!();
    }
    print_manifest_summary(&manifest);
    println!();

    let r = &manifest.resources;
    println!("{}", "Resource Quotas".bright_cyan().bold());
    println!("{}", "".repeat(40).dimmed());
    println!("  Max iterations:  {}", r.max_iterations);
    println!("  Max tool calls:  {}", r.max_tool_calls);
    let budget = if r.max_cost_usd > 0.0 {
        format!("${:.4}", r.max_cost_usd)
    } else {
        "unlimited (sovereign)".to_string()
    };
    println!("  Cost budget:     {budget}");
    println!();

    let m = &manifest.model;
    println!("{}", "Model Configuration".bright_cyan().bold());
    println!("{}", "".repeat(40).dimmed());
    println!("  Max tokens:      {}", m.max_tokens);
    println!("  Temperature:     {}", m.temperature);
    match m.context_window {
        Some(ref ctx) => println!("  Context window:  {ctx}"),
        None => println!("  Context window:  auto-detect"),
    }
    if let Some(ref repo) = m.model_repo {
        let quant = m.model_quantization.as_deref().unwrap_or("q4_k_m");
        println!("  Model repo:      {repo}");
        println!("  Quantization:    {quant}");
        if let Some(resolved) = m.resolve_model_path() {
            let exists = if resolved.exists() { "found" } else { "not found" };
            println!("  Resolved path:   {} ({exists})", resolved.display());
        }
    }
    if let Some(ref remote) = m.remote_model {
        println!("  Remote model:    {remote}");
    }
    println!();

    println!("{}", "Capabilities".bright_cyan().bold());
    println!("{}", "".repeat(40).dimmed());
    if manifest.capabilities.is_empty() {
        println!("  (none — deny-by-default)");
    }
    for cap in &manifest.capabilities {
        println!("  {} {cap:?}", "".bright_blue());
    }
    println!();
    println!("{} {}", "".green(), "Agent manifest loaded successfully.".green());
    Ok(())
}