rho-coding-agent 0.24.1

A lightweight agent harness inspired by Pi
Documentation
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub mod bash;
mod diff;
pub mod edit_file;
pub mod list_dir;
#[cfg(windows)]
pub mod powershell;
mod process;
pub mod read_file;
pub mod rtk;
pub mod skill;
pub mod web;
pub mod write_file;

use crate::{config::Config, tool::ToolRegistry};

pub fn registry(config: &Config) -> ToolRegistry {
    let mut r = ToolRegistry::new();
    r.register(list_dir::ListDir);
    r.register(read_file::ReadFile);
    r.register(write_file::WriteFile);
    r.register(edit_file::EditFile);
    let processes = process::ProcessManager::new(process::ProcessLimits::default());
    r.register(process::StartProcess::new(processes.clone()));
    r.register(process::PollProcess::new(processes.clone()));
    r.register(process::WriteProcess::new(processes.clone()));
    r.register(process::StopProcess::new(processes.clone()));
    r.register(process::ListProcesses::new(processes.clone()));
    r.set_shutdown(processes);
    let rtk_enabled = config.rtk && rtk::is_available();
    #[cfg(any(target_os = "linux", target_os = "macos"))]
    r.register(bash::Bash::new(rtk_enabled));
    #[cfg(windows)]
    r.register(powershell::PowerShell::new(rtk_enabled));
    r.register(skill::Skill);
    let (web_search, fetch_content) = web::access_tools(config);
    if web_search.is_available() {
        r.register(web_search);
    }
    r.register(fetch_content);
    r.register(web::GetSearchContent);
    r
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn registry_includes_available_web_access_tools() {
        let registry = registry(&Config::default());
        let names = registry
            .specs()
            .into_iter()
            .map(|spec| spec.name)
            .collect::<Vec<_>>();

        assert_eq!(
            names.contains(&"web_search".to_string()),
            web::access_tools(&Config::default()).0.is_available()
        );
        assert!(names.contains(&"fetch_content".to_string()));
        assert!(names.contains(&"get_search_content".to_string()));
        for process_tool in [
            "start_process",
            "poll_process",
            "write_process",
            "stop_process",
            "list_processes",
        ] {
            assert!(
                names.contains(&process_tool.to_string()),
                "missing {process_tool}"
            );
        }
    }

    #[test]
    fn registry_omits_web_search_when_disabled() {
        let config = Config {
            web_search_provider: crate::config::SearchProvider::Disabled,
            ..Config::default()
        };
        let names = registry(&config)
            .specs()
            .into_iter()
            .map(|spec| spec.name)
            .collect::<Vec<_>>();

        assert!(!names.contains(&"web_search".to_string()));
        assert!(names.contains(&"fetch_content".to_string()));
        assert!(names.contains(&"get_search_content".to_string()));
        for process_tool in [
            "start_process",
            "poll_process",
            "write_process",
            "stop_process",
            "list_processes",
        ] {
            assert!(
                names.contains(&process_tool.to_string()),
                "missing {process_tool}"
            );
        }
    }
}