diff --git a/Makefile b/Makefile index e20c9a5..300589b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ DOCS_PROD_BASEURL ?= $(DOCS_BASEURL) all: build # Build all components (Go binaries + optimized CLI) -build: +build: native-build go build -ldflags="-X main.BuildHash=$(shell git rev-parse --short HEAD) -X main.BuildTime=$(shell date -u +%Y%m%d.%H%M%S)" -o bin/api-server ./cmd/api-server/main.go go build -ldflags="-X main.BuildHash=$(shell git rev-parse --short HEAD) -X main.BuildTime=$(shell date -u +%Y%m%d.%H%M%S)" -o bin/worker ./cmd/worker/worker_server.go go build -ldflags="-X main.BuildHash=$(shell git rev-parse --short HEAD) -X main.BuildTime=$(shell date -u +%Y%m%d.%H%M%S)" -o bin/data_manager ./cmd/data_manager diff --git a/cmd/tui/internal/controller/commands.go b/cmd/tui/internal/controller/commands.go index b95b926..9eda176 100644 --- a/cmd/tui/internal/controller/commands.go +++ b/cmd/tui/internal/controller/commands.go @@ -4,6 +4,7 @@ package controller import ( "fmt" "path/filepath" + "runtime" "strings" "time" @@ -90,24 +91,6 @@ func (c *Controller) loadJobs() tea.Cmd { } } -// loadJobDetails loads full details for a specific job (lazy loading) -func (c *Controller) loadJobDetails(jobName string) tea.Cmd { - return func() tea.Msg { - jobStatus, _ := c.taskQueue.GetJobStatus(jobName) - - // Parse priority - priority := int64(0) - if p, ok := jobStatus["priority"]; ok { - fmt.Sscanf(p, "%d", &priority) - } - - // Build full job with details - // This is called when job is selected for detailed view - - return model.StatusMsg{Text: "Loaded details for " + jobName, Level: "info"} - } -} - func (c *Controller) loadQueue() tea.Cmd { return func() tea.Msg { tasks, err := c.taskQueue.GetQueuedTasks() @@ -129,7 +112,7 @@ func (c *Controller) loadGPU() tea.Cmd { resultChan := make(chan gpuResult, 1) go func() { - // Try NVML first for accurate GPU info + // Try NVML first for accurate GPU info (Linux/Windows with NVIDIA) if worker.IsNVMLAvailable() { gpus, err := worker.GetAllGPUInfo() if err == nil && len(gpus) > 0 { @@ -158,54 +141,22 @@ func (c *Controller) loadGPU() tea.Cmd { } } - // Fall back to nvidia-smi command parsing - cmd := "nvidia-smi --query-gpu=index,name,utilization.gpu," + - "memory.used,memory.total,temperature.gpu --format=csv,noheader,nounits" - out, err := c.server.Exec(cmd) - if err == nil && strings.TrimSpace(out) != "" { - var formatted strings.Builder - formatted.WriteString("GPU Status (nvidia-smi)\n") - formatted.WriteString(strings.Repeat("═", 50) + "\n\n") - lines := strings.Split(strings.TrimSpace(out), "\n") - for _, line := range lines { - parts := strings.Split(line, ", ") - if len(parts) >= 6 { - formatted.WriteString(fmt.Sprintf("šŸŽ® GPU %s: %s\n", parts[0], parts[1])) - formatted.WriteString(fmt.Sprintf(" Utilization: %s%%\n", parts[2])) - formatted.WriteString(fmt.Sprintf(" Memory: %s/%s MB\n", parts[3], parts[4])) - formatted.WriteString(fmt.Sprintf(" Temperature: %s°C\n\n", parts[5])) - } - } - c.logger.Info("loaded GPU status", "type", "nvidia-smi") - resultChan <- gpuResult{content: formatted.String(), err: nil} - return - } - - // Fall back to macOS system_profiler - cmd = "system_profiler SPDisplaysDataType | grep 'Chipset Model\\|VRAM' | head -2" - out, err = c.server.Exec(cmd) - if err != nil { - c.logger.Warn("GPU info unavailable", "error", err) - resultChan <- gpuResult{ - content: "GPU info unavailable\n\nRun on a system with NVIDIA GPU or macOS", - err: err, - } - return - } - - var formatted strings.Builder - formatted.WriteString("GPU Status (macOS)\n") - formatted.WriteString(strings.Repeat("═", 50) + "\n\n") - lines := strings.Split(strings.TrimSpace(out), "\n") - for _, line := range lines { - if strings.Contains(line, "Chipset Model") || strings.Contains(line, "VRAM") { - formatted.WriteString("šŸŽ® " + strings.TrimSpace(line) + "\n") + // Try macOS GPU monitoring (development mode on macOS) + if worker.IsMacOS() { + gpuStatus, err := worker.FormatMacOSGPUStatus() + if err == nil && gpuStatus != "" { + c.logger.Info("loaded GPU status", "type", "macos") + resultChan <- gpuResult{content: gpuStatus, err: nil} + return } } - formatted.WriteString("\nšŸ’” Note: NVIDIA NVML not available on macOS\n") - c.logger.Info("loaded GPU status", "type", "macos") - resultChan <- gpuResult{content: formatted.String(), err: nil} + // No GPU monitoring available + c.logger.Warn("GPU info unavailable", "platform", runtime.GOOS) + resultChan <- gpuResult{ + content: "GPU info unavailable\n\nNVML: NVIDIA driver not installed or incompatible\nmacOS: system_profiler not available", + err: fmt.Errorf("no GPU monitoring available on %s", runtime.GOOS), + } }() result := <-resultChan diff --git a/cmd/tui/internal/controller/controller.go b/cmd/tui/internal/controller/controller.go index 4ddfc66..cea3d2f 100644 --- a/cmd/tui/internal/controller/controller.go +++ b/cmd/tui/internal/controller/controller.go @@ -392,6 +392,8 @@ func (c *Controller) Update(msg tea.Msg, m model.State) (model.State, tea.Cmd) { return c.handleGPUContent(typed, m) case model.ContainerLoadedMsg: return c.handleContainerContent(typed, m) + case model.QueueLoadedMsg: + return c.handleQueueContent(typed, m) case model.DatasetsLoadedMsg: // Format datasets into view content var content strings.Builder