use crate::executors::types::{Skill, SkillParameter};
use anyhow::Result;
use serde_json::{Value, json};
use std::collections::HashMap;
use sysinfo::{Disks, Networks, System, Users};
#[derive(Debug)]
pub struct OsRebootSkill;
#[async_trait::async_trait]
impl Skill for OsRebootSkill {
fn name(&self) -> &str {
"os_reboot"
}
fn description(&self) -> &str {
"Reboot the system"
}
fn usage_hint(&self) -> &str {
"Use this skill when you need to restart the system for updates or troubleshooting"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![
SkillParameter {
name: "delay".to_string(),
param_type: "integer".to_string(),
description: "Delay in seconds before reboot (default: 0)".to_string(),
required: false,
default: Some(json!(0)),
example: Some(json!(60)),
enum_values: None,
},
SkillParameter {
name: "force".to_string(),
param_type: "boolean".to_string(),
description: "Force reboot without asking (default: false)".to_string(),
required: false,
default: Some(json!(false)),
example: Some(json!(true)),
enum_values: None,
},
]
}
fn example_call(&self) -> Value {
json!({
"action": "os_reboot",
"parameters": {
"delay": 10
}
})
}
fn example_output(&self) -> String {
"System will reboot in 10 seconds".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let delay = parameters
.get("delay")
.and_then(|v| v.as_u64())
.unwrap_or(0);
let force = parameters
.get("force")
.and_then(|v| v.as_bool())
.unwrap_or(false);
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
let mut args: Vec<String> = vec!["/r".to_string()];
if delay > 0 {
args.push("/t".to_string());
args.push(delay.to_string());
}
if force {
args.push("/f".to_string());
}
let args_ref: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
exec_async("shutdown", &args_ref, None).await?;
}
#[cfg(not(target_os = "windows"))]
{
let mut args = vec!["shutdown"];
if delay > 0 {
args.push("-h");
args.push(&format!("+{}", delay / 60));
} else {
args.push("-r");
args.push("now");
}
if force {
args.push("-f");
}
let _ = exec_async("sudo", &args, None).await;
}
Ok(format!("System will reboot in {} seconds", delay))
}
}
#[derive(Debug)]
pub struct OsShutdownSkill;
#[async_trait::async_trait]
impl Skill for OsShutdownSkill {
fn name(&self) -> &str {
"os_shutdown"
}
fn description(&self) -> &str {
"Shutdown the system"
}
fn usage_hint(&self) -> &str {
"Use this skill when you need to power off the system"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![
SkillParameter {
name: "delay".to_string(),
param_type: "integer".to_string(),
description: "Delay in seconds before shutdown (default: 0)".to_string(),
required: false,
default: Some(json!(0)),
example: Some(json!(120)),
enum_values: None,
},
SkillParameter {
name: "force".to_string(),
param_type: "boolean".to_string(),
description: "Force shutdown without asking (default: false)".to_string(),
required: false,
default: Some(json!(false)),
example: Some(json!(true)),
enum_values: None,
},
]
}
fn example_call(&self) -> Value {
json!({
"action": "os_shutdown",
"parameters": {
"delay": 30
}
})
}
fn example_output(&self) -> String {
"System will shutdown in 30 seconds".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let delay = parameters
.get("delay")
.and_then(|v| v.as_u64())
.unwrap_or(0);
let force = parameters
.get("force")
.and_then(|v| v.as_bool())
.unwrap_or(false);
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
let mut args: Vec<String> = vec!["/r".to_string()];
if delay > 0 {
args.push("/t".to_string());
args.push(delay.to_string());
}
if force {
args.push("/f".to_string());
}
let args_ref: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
exec_async("shutdown", &args_ref, None).await?;
}
#[cfg(not(target_os = "windows"))]
{
let mut args = vec!["shutdown"];
if delay > 0 {
args.push("-h");
args.push(&format!("+{}", delay / 60));
} else {
args.push("-h");
args.push("now");
}
if force {
args.push("-f");
}
let _ = exec_async("sudo", &args, None).await;
}
Ok(format!("System will shutdown in {} seconds", delay))
}
}
#[derive(Debug)]
pub struct OsSleepSkill;
#[async_trait::async_trait]
impl Skill for OsSleepSkill {
fn name(&self) -> &str {
"os_sleep"
}
fn description(&self) -> &str {
"Put the system to sleep (suspend to RAM)"
}
fn usage_hint(&self) -> &str {
"Use this skill to save power by putting the system into low-power sleep mode"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_sleep"
})
}
fn example_output(&self) -> String {
"System is going to sleep".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
exec_async(
"rundll32.exe",
&["powrprof.dll,SetSuspendState", "0", "1", "0"],
None,
)
.await?;
}
#[cfg(target_os = "macos")]
{
exec_async("pmset", &["sleepnow"], None).await?;
}
#[cfg(target_os = "linux")]
{
exec_async("systemctl", &["suspend"], None).await?;
}
Ok("System is going to sleep".to_string())
}
}
#[derive(Debug)]
pub struct OsLockSkill;
#[async_trait::async_trait]
impl Skill for OsLockSkill {
fn name(&self) -> &str {
"os_lock"
}
fn description(&self) -> &str {
"Lock the system screen"
}
fn usage_hint(&self) -> &str {
"Use this skill when you need to secure the system without logging out"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_lock"
})
}
fn example_output(&self) -> String {
"Screen locked".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
exec_async("rundll32.exe", &["user32.dll,LockWorkStation"], None).await?;
}
#[cfg(target_os = "macos")]
{
let _ = exec_async("osascript", &["-e", "tell application \"System Events\" to keystroke \"q\" using {command down, control down}"], None).await;
}
#[cfg(target_os = "linux")]
{
let _ = exec_async("gnome-screensaver-command", &["-l"], None).await;
let _ = exec_async("xdg-screensaver", &["lock"], None).await;
}
Ok("Screen locked".to_string())
}
}
#[derive(Debug)]
pub struct OsLogoutSkill;
#[async_trait::async_trait]
impl Skill for OsLogoutSkill {
fn name(&self) -> &str {
"os_logout"
}
fn description(&self) -> &str {
"Log out the current user"
}
fn usage_hint(&self) -> &str {
"Use this skill to end the current user session"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "force".to_string(),
param_type: "boolean".to_string(),
description: "Force logout without confirmation (default: false)".to_string(),
required: false,
default: Some(json!(false)),
example: Some(json!(true)),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_logout"
})
}
fn example_output(&self) -> String {
"Logging out current user".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let _force = parameters
.get("force")
.and_then(|v| v.as_bool())
.unwrap_or(false);
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
exec_async("shutdown", &["/l"], None).await?;
}
#[cfg(target_os = "macos")]
{
let _ = exec_async(
"osascript",
&["-e", "tell application \"System Events\" to log out"],
None,
)
.await;
}
#[cfg(target_os = "linux")]
{
let _ = exec_async("gnome-session-quit", &["--no-prompt"], None).await;
let _ = exec_async("pkill", &["-KILL", "-u", "$USER"], None).await;
}
Ok("Logging out current user".to_string())
}
}
#[derive(Debug)]
pub struct OsHibernateSkill;
#[async_trait::async_trait]
impl Skill for OsHibernateSkill {
fn name(&self) -> &str {
"os_hibernate"
}
fn description(&self) -> &str {
"Hibernate the system (suspend to disk)"
}
fn usage_hint(&self) -> &str {
"Use this skill to save power while preserving system state to disk"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_hibernate"
})
}
fn example_output(&self) -> String {
"System is hibernating".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
exec_async("shutdown", &["/h"], None).await?;
}
#[cfg(target_os = "linux")]
{
exec_async("systemctl", &["hibernate"], None).await?;
}
#[cfg(target_os = "macos")]
{
exec_async("pmset", &["sleepnow"], None).await?;
}
Ok("System is hibernating".to_string())
}
}
#[derive(Debug)]
pub struct OsGetUptimeSkill;
#[async_trait::async_trait]
impl Skill for OsGetUptimeSkill {
fn name(&self) -> &str {
"os_get_uptime"
}
fn description(&self) -> &str {
"Get system uptime information"
}
fn usage_hint(&self) -> &str {
"Use this skill to check how long the system has been running"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "human_readable".to_string(),
param_type: "boolean".to_string(),
description: "Return human-readable format (default: true)".to_string(),
required: false,
default: Some(json!(true)),
example: Some(json!(false)),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_get_uptime"
})
}
fn example_output(&self) -> String {
"System uptime: 5 days, 3 hours, 22 minutes".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let human_readable = parameters
.get("human_readable")
.and_then(|v| v.as_bool())
.unwrap_or(true);
let mut system = System::new();
system.refresh_all();
let uptime_secs = System::uptime();
if human_readable {
let days = uptime_secs / 86400;
let hours = (uptime_secs % 86400) / 3600;
let minutes = (uptime_secs % 3600) / 60;
let seconds = uptime_secs % 60;
let mut parts = Vec::new();
if days > 0 {
parts.push(format!("{} days", days));
}
if hours > 0 {
parts.push(format!("{} hours", hours));
}
if minutes > 0 {
parts.push(format!("{} minutes", minutes));
}
if seconds > 0 && days == 0 && hours == 0 {
parts.push(format!("{} seconds", seconds));
}
Ok(format!("System uptime: {}", parts.join(", ")))
} else {
Ok(format!("System uptime: {} seconds", uptime_secs))
}
}
}
#[derive(Debug)]
pub struct OsGetLoadAverageSkill;
#[async_trait::async_trait]
impl Skill for OsGetLoadAverageSkill {
fn name(&self) -> &str {
"os_get_load_average"
}
fn description(&self) -> &str {
"Get system load average (1, 5, 15 minutes)"
}
fn usage_hint(&self) -> &str {
"Use this skill to check system load and performance"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_get_load_average"
})
}
fn example_output(&self) -> String {
"Load average: 1 min: 2.5, 5 min: 1.8, 15 min: 1.2".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
let load_avg = System::load_average();
Ok(format!(
"Load average: 1 min: {:.2}, 5 min: {:.2}, 15 min: {:.2}",
load_avg.one, load_avg.five, load_avg.fifteen
))
}
}
#[derive(Debug)]
pub struct OsGetHostnameSkill;
#[async_trait::async_trait]
impl Skill for OsGetHostnameSkill {
fn name(&self) -> &str {
"os_get_hostname"
}
fn description(&self) -> &str {
"Get or set the system hostname"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the current hostname or set a new one (requires admin privileges)"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "set_hostname".to_string(),
param_type: "string".to_string(),
description: "New hostname to set (requires admin)".to_string(),
required: false,
default: None,
example: Some(json!("my-server")),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_get_hostname"
})
}
fn example_output(&self) -> String {
"Current hostname: my-computer".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let new_hostname = parameters.get("set_hostname").and_then(|v| v.as_str());
if let Some(name) = new_hostname {
#[cfg(not(target_os = "windows"))]
{
let _ = exec_async("sudo", &["hostname", name], None).await;
}
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
let _ = exec_async(
"powershell",
&["-Command", &format!("Rename-Computer -NewName '{}'", name)],
None,
)
.await;
}
Ok(format!("Hostname changed to: {}", name))
} else {
let hostname = System::host_name();
Ok(format!(
"Current hostname: {}",
hostname.unwrap_or_else(|| "unknown".to_string())
))
}
}
}
#[derive(Debug)]
pub struct OsGetTimeSkill;
#[async_trait::async_trait]
impl Skill for OsGetTimeSkill {
fn name(&self) -> &str {
"os_get_time"
}
fn description(&self) -> &str {
"Get current system time and timezone"
}
fn usage_hint(&self) -> &str {
"Use this skill to check the current date, time, and timezone"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "format".to_string(),
param_type: "string".to_string(),
description: "Output format: full, date, time, timestamp".to_string(),
required: false,
default: Some(json!("full")),
example: Some(json!("date")),
enum_values: Some(vec![
"full".to_string(),
"date".to_string(),
"time".to_string(),
"timestamp".to_string(),
]),
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_get_time"
})
}
fn example_output(&self) -> String {
"Current time: 2024-01-15 14:30:45 (UTC+8)".to_string()
}
fn category(&self) -> &str {
"time"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let format = parameters
.get("format")
.and_then(|v| v.as_str())
.unwrap_or("full");
let now = chrono::Local::now();
let tz = now.offset();
match format {
"date" => Ok(format!("Current date: {}", now.format("%Y-%m-%d"))),
"time" => Ok(format!("Current time: {}", now.format("%H:%M:%S"))),
"timestamp" => Ok(format!("Unix timestamp: {}", now.timestamp())),
_ => Ok(format!(
"Current time: {} ({})",
now.format("%Y-%m-%d %H:%M:%S"),
tz
)),
}
}
}
#[derive(Debug)]
pub struct OsSetTimeSkill;
#[async_trait::async_trait]
impl Skill for OsSetTimeSkill {
fn name(&self) -> &str {
"os_set_time"
}
fn description(&self) -> &str {
"Set system time (requires administrator privileges)"
}
fn usage_hint(&self) -> &str {
"Use this skill to adjust system time"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "datetime".to_string(),
param_type: "string".to_string(),
description: "New datetime in format 'YYYY-MM-DD HH:MM:SS'".to_string(),
required: true,
default: None,
example: Some(json!("2024-01-15 12:00:00")),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_set_time",
"parameters": {
"datetime": "2024-01-15 10:00:00"
}
})
}
fn example_output(&self) -> String {
"System time updated successfully".to_string()
}
fn category(&self) -> &str {
"time"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let datetime = parameters
.get("datetime")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: datetime"))?;
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
exec_async(
"powershell",
&["-Command", &format!("Set-Date -Date '{}'", datetime)],
None,
)
.await?;
}
#[cfg(not(target_os = "windows"))]
{
exec_async("sudo", &["date", "-s", datetime], None).await?;
}
Ok("System time updated successfully".to_string())
}
}
#[derive(Debug)]
pub struct OsGetUserSkill;
#[async_trait::async_trait]
impl Skill for OsGetUserSkill {
fn name(&self) -> &str {
"os_get_user"
}
fn description(&self) -> &str {
"Get current user information"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the current username, home directory, and user ID"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_get_user"
})
}
fn example_output(&self) -> String {
"Username: john\nUID: 1000\nGroups: sudo, docker".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
let users = Users::new_with_refreshed_list();
let current_user = users.iter().next();
if let Some(user) = current_user {
let groups: Vec<String> = user.groups().iter().map(|g| g.name().to_string()).collect();
Ok(format!(
"Username: {}\nUID: {}\nGroups: {}",
user.name().to_string(),
user.id().to_string(),
groups.join(", ")
))
} else {
Ok("User information could not be found.".to_string())
}
}
}
#[derive(Debug)]
pub struct OsDiskUsageSkill;
#[async_trait::async_trait]
impl Skill for OsDiskUsageSkill {
fn name(&self) -> &str {
"os_disk_usage"
}
fn description(&self) -> &str {
"Get disk usage information for all mounted filesystems"
}
fn usage_hint(&self) -> &str {
"Use this skill to check available disk space and usage percentages"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Specific path to check (default: all mounts)".to_string(),
required: false,
default: None,
example: Some(json!("/")),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_disk_usage",
"parameters": {
"path": "/home"
}
})
}
fn example_output(&self) -> String {
"Filesystem Size Used Avail Use%\n/dev/sda1 100G 45G 55G 45%"
.to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let _specific_path = parameters.get("path").and_then(|v| v.as_str());
let disks = Disks::new_with_refreshed_list();
let mut output = vec![format!(
"{:<20} {:<10} {:<10} {:<10} {:<6}",
"Filesystem", "Total", "Used", "Avail", "Use%"
)];
output.push("-".repeat(56));
for disk in disks.list() {
let total_gb = disk.total_space() as f64 / (1024.0 * 1024.0 * 1024.0);
let available_gb = disk.available_space() as f64 / (1024.0 * 1024.0 * 1024.0);
let used_gb = total_gb - available_gb;
let used_percent = if total_gb > 0.0 {
(used_gb / total_gb) * 100.0
} else {
0.0
};
let mount_point = disk.mount_point().display().to_string();
if mount_point.len() > 20 {
output.push(format!(
"{}\n{:<20} {:<10.1}G {:<10.1}G {:<10.1}G {:<6.1}%",
mount_point, "", total_gb, used_gb, available_gb, used_percent
));
} else {
output.push(format!(
"{:<20} {:<10.1}G {:<10.1}G {:<10.1}G {:<6.1}%",
mount_point, total_gb, used_gb, available_gb, used_percent
));
}
}
Ok(output.join("\n"))
}
}
#[derive(Debug)]
pub struct OsMemoryInfoSkill;
#[async_trait::async_trait]
impl Skill for OsMemoryInfoSkill {
fn name(&self) -> &str {
"os_memory_info"
}
fn description(&self) -> &str {
"Get system memory (RAM) information"
}
fn usage_hint(&self) -> &str {
"Use this skill to check total, used, and available memory"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_memory_info"
})
}
fn example_output(&self) -> String {
"Total Memory: 16.0 GB\nUsed Memory: 8.2 GB (51%)\nAvailable Memory: 7.8 GB".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
let mut system = System::new();
system.refresh_memory();
let total_gb = system.total_memory() as f64 / (1024.0 * 1024.0);
let used_gb = system.used_memory() as f64 / (1024.0 * 1024.0);
let free_gb = system.free_memory() as f64 / (1024.0 * 1024.0);
let used_percent = (used_gb / total_gb) * 100.0;
Ok(format!(
"Total Memory: {:.1} GB\nUsed Memory: {:.1} GB ({:.0}%)\nFree Memory: {:.1} GB\nAvailable Memory: {:.1} GB",
total_gb,
used_gb,
used_percent,
free_gb,
system.available_memory() as f64 / (1024.0 * 1024.0)
))
}
}
#[derive(Debug)]
pub struct OsCpuInfoSkill;
#[async_trait::async_trait]
impl Skill for OsCpuInfoSkill {
fn name(&self) -> &str {
"os_cpu_info"
}
fn description(&self) -> &str {
"Get CPU information including cores, frequency, and usage"
}
fn usage_hint(&self) -> &str {
"Use this skill to check CPU specifications and current usage"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![]
}
fn example_call(&self) -> Value {
json!({
"action": "os_cpu_info"
})
}
fn example_output(&self) -> String {
"CPU cores: 8\nPhysical cores: 4\nCPU usage: 15%\nFrequency: 2.4 GHz".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, _parameters: &HashMap<String, Value>) -> Result<String> {
let mut system = System::new();
system.refresh_cpu_all();
let physical_cores = System::physical_core_count().unwrap_or(0);
let total_cores = system.cpus().len();
let cpu_usage = system.global_cpu_usage();
let frequency_info = if let Some(freq_mhz) = system.cpus().first().map(|c| c.frequency()) {
format!("Frequency: {:.1} GHz", freq_mhz as f64 / 1000.0)
} else {
"Frequency: unknown".to_string()
};
Ok(format!(
"CPU cores: {}\nPhysical cores: {}\nCPU usage: {:.1}%\n{}",
total_cores, physical_cores, cpu_usage, frequency_info
))
}
}
#[derive(Debug)]
pub struct OsNetworkInfoSkill;
#[async_trait::async_trait]
impl Skill for OsNetworkInfoSkill {
fn name(&self) -> &str {
"os_network_info"
}
fn description(&self) -> &str {
"Get network interface information"
}
fn usage_hint(&self) -> &str {
"Use this skill to check network interfaces, IP addresses, and MAC addresses"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "interface".to_string(),
param_type: "string".to_string(),
description: "Specific interface to show (default: all)".to_string(),
required: false,
default: None,
example: Some(json!("eth0")),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_network_info"
})
}
fn example_output(&self) -> String {
"eth0: 192.168.1.100 (MAC: 00:11:22:33:44:55)\nwlan0: 10.0.0.1 (MAC: AA:BB:CC:DD:EE:FF)"
.to_string()
}
fn category(&self) -> &str {
"net"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let filter_interface = parameters.get("interface").and_then(|v| v.as_str());
let networks = Networks::new_with_refreshed_list();
let mut output = Vec::new();
for (interface_name, data) in networks.list() {
if let Some(filter) = filter_interface {
if !interface_name.to_string().contains(filter) {
continue;
}
}
let ips: Vec<String> = data
.ip_networks()
.iter()
.map(|ip| ip.addr.to_string())
.collect();
let mac = data.mac_address().to_string();
let mac = if mac == "00:00:00:00:00:00" {
"N/A".to_string()
} else {
mac
};
output.push(format!(
"{}: {} (MAC: {})",
interface_name.to_string(),
ips.join(", "),
mac
));
}
if output.is_empty() {
Ok("No network interfaces found".to_string())
} else {
Ok(output.join("\n"))
}
}
}
#[derive(Debug)]
pub struct OsBatteryInfoSkill;
#[async_trait::async_trait]
impl Skill for OsBatteryInfoSkill {
fn name(&self) -> &str {
"os_battery_info"
}
fn description(&self) -> &str {
"Get battery status and information (for laptops)"
}
fn usage_hint(&self) -> &str {
"Use this skill to check battery percentage, charging status, and estimated time"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![SkillParameter {
name: "detailed".to_string(),
param_type: "boolean".to_string(),
description: "Show detailed battery information".to_string(),
required: false,
default: Some(json!(false)),
example: Some(json!(true)),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "os_battery_info"
})
}
fn example_output(&self) -> String {
"Battery: 75% (Charging)\nTime remaining: 2h 30m".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let detailed = parameters
.get("detailed")
.and_then(|v| v.as_bool())
.unwrap_or(false);
#[cfg(target_os = "linux")]
{
let result = exec_async(
"upower",
&["-i", "/org/freedesktop/UPower/devices/battery_BAT0"],
None,
)
.await;
if let Ok(out) = result {
let info = out.stdout;
if detailed {
return Ok(info);
}
let percentage = info
.lines()
.find(|l| l.contains("percentage"))
.and_then(|l| l.split(':').nth(1))
.map(|s| s.trim());
let state = info
.lines()
.find(|l| l.contains("state"))
.and_then(|l| l.split(':').nth(1))
.map(|s| s.trim());
if let (Some(pct), Some(st)) = (percentage, state) {
return Ok(format!(
"Battery: {} ({})\nTime remaining: check detailed",
pct, st
));
}
}
}
#[cfg(target_os = "macos")]
{
let result = exec_async("pmset", &["-g", "batt"], None).await?;
let info = result.stdout;
if detailed {
return Ok(info);
}
if let Some(line) = info.lines().find(|l| l.contains('%')) {
return Ok(format!("Battery: {}", line.trim()));
}
}
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
let result = exec_async("powercfg", &["/getbatteryreport"], None).await?;
if detailed {
return Ok(result.stdout);
}
}
Ok("Battery information not available or system is not a laptop".to_string())
}
}
#[derive(Debug)]
pub struct OsNotificationSkill;
#[async_trait::async_trait]
impl Skill for OsNotificationSkill {
fn name(&self) -> &str {
"os_notification"
}
fn description(&self) -> &str {
"Send a desktop notification"
}
fn usage_hint(&self) -> &str {
"Use this skill to display notifications to the user"
}
fn parameters(&self) -> Vec<SkillParameter> {
vec![
SkillParameter {
name: "title".to_string(),
param_type: "string".to_string(),
description: "Notification title".to_string(),
required: true,
default: None,
example: Some(json!("Task Complete")),
enum_values: None,
},
SkillParameter {
name: "message".to_string(),
param_type: "string".to_string(),
description: "Notification message body".to_string(),
required: true,
default: None,
example: Some(json!("Your task has finished successfully")),
enum_values: None,
},
SkillParameter {
name: "urgency".to_string(),
param_type: "string".to_string(),
description: "Urgency level: low, normal, critical".to_string(),
required: false,
default: Some(json!("normal")),
example: Some(json!("critical")),
enum_values: Some(vec![
"low".to_string(),
"normal".to_string(),
"critical".to_string(),
]),
},
]
}
fn example_call(&self) -> Value {
json!({
"action": "os_notification",
"parameters": {
"title": "Alert",
"message": "Something happened"
}
})
}
fn example_output(&self) -> String {
"Notification sent".to_string()
}
fn category(&self) -> &str {
"system"
}
async fn execute(&self, parameters: &HashMap<String, Value>) -> Result<String> {
let title = parameters
.get("title")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: title"))?;
let message = parameters
.get("message")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: message"))?;
let urgency = parameters
.get("urgency")
.and_then(|v| v.as_str())
.unwrap_or("normal");
#[cfg(target_os = "linux")]
{
let urgency_flag = match urgency {
"critical" => "--urgency=critical",
"low" => "--urgency=low",
_ => "--urgency=normal",
};
let _ = exec_async("notify-send", &[urgency_flag, title, message], None).await;
}
#[cfg(target_os = "macos")]
{
let _ = exec_async(
"osascript",
&[
"-e",
&format!(
"display notification \"{}\" with title \"{}\"",
message, title
),
],
None,
)
.await;
}
#[cfg(target_os = "windows")]
{
use crate::executors::exec_async;
let _ = exec_async(
"powershell",
&[
"-Command",
&format!(
"New-BurntToastNotification -Text \"{}\", \"{}\"",
title, message
),
],
None,
)
.await;
}
Ok("Notification sent".to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_os_get_uptime() {
let skill = OsGetUptimeSkill;
let params = HashMap::new();
let result = skill.execute(¶ms).await.unwrap();
assert!(result.contains("uptime"));
}
#[tokio::test]
async fn test_os_get_load_average() {
let skill = OsGetLoadAverageSkill;
let params = HashMap::new();
let result = skill.execute(¶ms).await.unwrap();
assert!(result.contains("Load average"));
}
#[tokio::test]
async fn test_os_get_time() {
let skill = OsGetTimeSkill;
let params = HashMap::new();
let result = skill.execute(¶ms).await.unwrap();
assert!(result.contains("Current time"));
}
#[tokio::test]
async fn test_os_memory_info() {
let skill = OsMemoryInfoSkill;
let params = HashMap::new();
let result = skill.execute(¶ms).await.unwrap();
assert!(result.contains("Memory"));
}
#[tokio::test]
async fn test_os_cpu_info() {
let skill = OsCpuInfoSkill;
let params = HashMap::new();
let result = skill.execute(¶ms).await.unwrap();
assert!(result.contains("CPU"));
}
}