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::{json, Value};
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        arr.iter().filter_map(|v| v.as_str()).collect()
22    } else {
23        all.to_vec()
24    };
25
26    let mut results: Vec<String> = Vec::new();
27    let mut errors: Vec<String> = Vec::new();
28
29    for component in &components {
30        match *component {
31            "uv" => {
32                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            }
37            "exo" => {
38                match crate::tools::exo_ai::exec_exo_manage(&setup_args, workspace_dir) {
39                    Ok(msg) => results.push(format!("✓ exo: {}", msg)),
40                    Err(e) => errors.push(format!("✗ exo: {}", e)),
41                }
42            }
43            "ollama" => {
44                match crate::tools::ollama::exec_ollama_manage(&setup_args, workspace_dir) {
45                    Ok(msg) => results.push(format!("✓ ollama: {}", msg)),
46                    Err(e) => errors.push(format!("✗ ollama: {}", e)),
47                }
48            }
49            other => {
50                errors.push(format!("✗ unknown component: '{}'", other));
51            }
52        }
53    }
54
55    let mut output = String::new();
56    output.push_str("Agent setup results:\n");
57    for r in &results {
58        output.push_str(&format!("  {}\n", r));
59    }
60    if !errors.is_empty() {
61        output.push_str("\nWarnings/errors:\n");
62        for e in &errors {
63            output.push_str(&format!("  {}\n", e));
64        }
65    }
66
67    if errors.len() == components.len() {
68        Err(output)
69    } else {
70        Ok(output)
71    }
72}