aidaemon 0.9.35

A personal AI agent that runs as a background daemon, accessible via Telegram, Slack, or Discord, with tool use, MCP integration, and persistent memory
use async_trait::async_trait;
use serde_json::{json, Value};

use crate::traits::{Tool, ToolCapabilities, ToolRole};

pub struct SystemInfoTool;

#[async_trait]
impl Tool for SystemInfoTool {
    fn name(&self) -> &str {
        "system_info"
    }

    fn description(&self) -> &str {
        "Get system information including CPU and memory usage"
    }

    fn schema(&self) -> Value {
        json!({
            "name": "system_info",
            "description": "Get system information including CPU and memory usage",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
            }
        })
    }

    fn tool_role(&self) -> ToolRole {
        ToolRole::Universal
    }

    fn capabilities(&self) -> ToolCapabilities {
        ToolCapabilities {
            read_only: true,
            external_side_effect: false,
            needs_approval: false,
            idempotent: true,
            high_impact_write: false,
        }
    }

    async fn call(&self, _arguments: &str) -> anyhow::Result<String> {
        let mut info = String::new();

        // Current date and time
        if let Ok(output) = tokio::process::Command::new("date").output().await {
            let date = String::from_utf8_lossy(&output.stdout).trim().to_string();
            info.push_str(&format!("Date: {}\n", date));
        }

        // Hostname
        if let Ok(output) = tokio::process::Command::new("hostname").output().await {
            let hostname = String::from_utf8_lossy(&output.stdout).trim().to_string();
            info.push_str(&format!("Hostname: {}\n", hostname));
        }

        // OS info
        if let Ok(output) = tokio::process::Command::new("uname")
            .arg("-a")
            .output()
            .await
        {
            let uname = String::from_utf8_lossy(&output.stdout).trim().to_string();
            info.push_str(&format!("OS: {}\n", uname));
        }

        // Uptime
        if let Ok(output) = tokio::process::Command::new("uptime").output().await {
            let uptime = String::from_utf8_lossy(&output.stdout).trim().to_string();
            info.push_str(&format!("Uptime: {}\n", uptime));
        }

        // Memory (works on both Linux and macOS)
        #[cfg(target_os = "linux")]
        {
            if let Ok(output) = tokio::process::Command::new("free")
                .arg("-h")
                .output()
                .await
            {
                let mem = String::from_utf8_lossy(&output.stdout).trim().to_string();
                info.push_str(&format!("Memory:\n{}\n", mem));
            }
        }

        #[cfg(target_os = "macos")]
        {
            if let Ok(output) = tokio::process::Command::new("vm_stat").output().await {
                let mem = String::from_utf8_lossy(&output.stdout).trim().to_string();
                info.push_str(&format!("Memory:\n{}\n", mem));
            }
        }

        if info.is_empty() {
            info.push_str("Could not retrieve system information.");
        }

        Ok(info)
    }
}