Skip to main content

rustyclaw_core/tools/
agent_setup.rs

1// Agent setup orchestrator for RustyClaw.
2//
3// Orchestrates the installation and configuration of all local-model
4// infrastructure: uv (Python env), exo (distributed cluster), and
5// ollama (local model server).  Can be invoked via `/agent setup`,
6// the `rustyclaw setup` CLI, or as an agent-callable tool.
7
8use serde_json::{Value, json};
9use std::path::Path;
10
11/// `agent_setup` — install + verify uv, exo, and ollama in one shot.
12///
13/// Optional `components` array lets the caller pick a subset:
14///   `["uv"]`, `["ollama","exo"]`, etc.  Default: all three.
15pub fn exec_agent_setup(args: &Value, workspace_dir: &Path) -> Result<String, String> {
16    let setup_args = json!({"action": "setup"});
17
18    // Which components to set up
19    let all = ["uv", "exo", "ollama"];
20    let components: Vec<&str> = if let Some(arr) = args.get("components").and_then(|v| v.as_array())
21    {
22        arr.iter().filter_map(|v| v.as_str()).collect()
23    } else {
24        all.to_vec()
25    };
26
27    let mut results: Vec<String> = Vec::new();
28    let mut errors: Vec<String> = Vec::new();
29
30    for component in &components {
31        match *component {
32            "uv" => match crate::tools::uv::exec_uv_manage(&setup_args, workspace_dir) {
33                Ok(msg) => results.push(format!("✓ uv: {}", msg)),
34                Err(e) => errors.push(format!("✗ uv: {}", e)),
35            },
36            "exo" => match crate::tools::exo_ai::exec_exo_manage(&setup_args, workspace_dir) {
37                Ok(msg) => results.push(format!("✓ exo: {}", msg)),
38                Err(e) => errors.push(format!("✗ exo: {}", e)),
39            },
40            "ollama" => {
41                match crate::tools::ollama::exec_ollama_manage(&setup_args, workspace_dir) {
42                    Ok(msg) => results.push(format!("✓ ollama: {}", msg)),
43                    Err(e) => errors.push(format!("✗ ollama: {}", e)),
44                }
45            }
46            other => {
47                errors.push(format!("✗ unknown component: '{}'", other));
48            }
49        }
50    }
51
52    let mut output = String::new();
53    output.push_str("Agent setup results:\n");
54    for r in &results {
55        output.push_str(&format!("  {}\n", r));
56    }
57    if !errors.is_empty() {
58        output.push_str("\nWarnings/errors:\n");
59        for e in &errors {
60            output.push_str(&format!("  {}\n", e));
61        }
62    }
63
64    if errors.len() == components.len() {
65        Err(output)
66    } else {
67        Ok(output)
68    }
69}