diff --git a/pkg/tools/system.go b/pkg/tools/system.go index 5b84678..465147a 100644 --- a/pkg/tools/system.go +++ b/pkg/tools/system.go @@ -9,7 +9,7 @@ import ( "syscall" ) -type SystemInfoTool struct {} +type SystemInfoTool struct{} func NewSystemInfoTool() *SystemInfoTool { return &SystemInfoTool{} @@ -20,25 +20,48 @@ func (t *SystemInfoTool) Name() string { } func (t *SystemInfoTool) Description() string { - return "Get current system status (CPU, RAM, Disk)." + return "Get current system status (CPU, RAM, Disk, Uptime)." } func (t *SystemInfoTool) Parameters() map[string]interface{} { return map[string]interface{}{ - "type": "object", + "type": "object", "properties": map[string]interface{}{}, } } func (t *SystemInfoTool) Execute(ctx context.Context, args map[string]interface{}) (string, error) { - info := fmt.Sprintf("System Info:\n") - info += fmt.Sprintf("OS: %s %s\n", runtime.GOOS, runtime.GOARCH) + var sb strings.Builder + sb.WriteString("System Info:\n") + sb.WriteString(fmt.Sprintf("OS: %s %s\n", runtime.GOOS, runtime.GOARCH)) + + // Uptime + if data, err := os.ReadFile("/proc/uptime"); err == nil { + var up, idle float64 + fmt.Sscanf(string(data), "%f %f", &up, &idle) + days := int(up / 86400) + hours := int(up) % 86400 / 3600 + mins := int(up) % 3600 / 60 + sb.WriteString(fmt.Sprintf("Uptime: %dd %dh %dm\n", days, hours, mins)) + } // Load Average if data, err := os.ReadFile("/proc/loadavg"); err == nil { - info += fmt.Sprintf("Load Avg: %s", string(data)) - } else { - info += "Load Avg: N/A\n" + sb.WriteString(fmt.Sprintf("Load Avg: %s", string(data))) + } + + // CPU Model + if data, err := os.ReadFile("/proc/cpuinfo"); err == nil { + lines := strings.Split(string(data), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "model name") { + parts := strings.SplitN(line, ":", 2) + if len(parts) > 1 { + sb.WriteString(fmt.Sprintf("CPU: %s\n", strings.TrimSpace(parts[1]))) + break + } + } + } } // RAM from /proc/meminfo @@ -55,31 +78,25 @@ func (t *SystemInfoTool) Execute(ctx context.Context, args map[string]interface{ } } if total > 0 { - // fallback if Available not present (older kernels) if available == 0 { - available = free // very rough approximation + available = free } used := total - available - info += fmt.Sprintf("RAM: Used %.2f GB / Total %.2f GB (%.2f%%)\n", - float64(used)/1024/1024, float64(total)/1024/1024, float64(used)/float64(total)*100) + sb.WriteString(fmt.Sprintf("RAM: Used %.2f GB / Total %.2f GB (%.2f%%)\n", + float64(used)/1024/1024, float64(total)/1024/1024, float64(used)/float64(total)*100)) } - } else { - info += "RAM: N/A\n" } // Disk usage for / var stat syscall.Statfs_t if err := syscall.Statfs("/", &stat); err == nil { - // Cast to uint64 to avoid overflow/type mismatch bsize := uint64(stat.Bsize) total := stat.Blocks * bsize free := stat.Bfree * bsize used := total - free - info += fmt.Sprintf("Disk (/): Used %.2f GB / Total %.2f GB (%.2f%%)\n", - float64(used)/1024/1024/1024, float64(total)/1024/1024/1024, float64(used)/float64(total)*100) - } else { - info += "Disk: N/A\n" + sb.WriteString(fmt.Sprintf("Disk (/): Used %.2f GB / Total %.2f GB (%.2f%%)\n", + float64(used)/1024/1024/1024, float64(total)/1024/1024/1024, float64(used)/float64(total)*100)) } - return info, nil + return sb.String(), nil }