From 6faa13aabf69faa200fe4615cbb63f145684ca16 Mon Sep 17 00:00:00 2001 From: Jeremie Fraeys Date: Mon, 23 Feb 2026 14:12:48 -0500 Subject: [PATCH] refactor(cli): Remove progress UI and update native/server code Delete cli/src/ui/progress.zig (removing progress bars/spinners) Update native GPU detection modules Update server experiment API --- cli/src/native/macos_gpu.zig | 16 ++-- cli/src/native/nvml.zig | 12 +-- cli/src/server/experiment_api.zig | 4 +- cli/src/ui/progress.zig | 151 ------------------------------ 4 files changed, 16 insertions(+), 167 deletions(-) delete mode 100644 cli/src/ui/progress.zig diff --git a/cli/src/native/macos_gpu.zig b/cli/src/native/macos_gpu.zig index 29dc8a0..4035603 100644 --- a/cli/src/native/macos_gpu.zig +++ b/cli/src/native/macos_gpu.zig @@ -229,28 +229,28 @@ pub fn formatMacOSGPUInfo(allocator: std.mem.Allocator, gpus: []const MacOSGPUIn const name = std.mem.sliceTo(&gpu.name, 0); const model = std.mem.sliceTo(&gpu.chipset_model, 0); - try writer.print("🎮 GPU {d}: {s}\n", .{ gpu.index, name }); + try writer.print("GPU {d}: {s}\n", .{ gpu.index, name }); if (!std.mem.eql(u8, model, name)) { - try writer.print(" Model: {s}\n", .{model}); + try writer.print("\tModel: {s}\n", .{model}); } if (gpu.is_integrated) { - try writer.writeAll(" Type: Integrated (Unified Memory)\n"); + try writer.writeAll("\tType: Integrated (Unified Memory)\n"); } else { - try writer.print(" VRAM: {d} MB\n", .{gpu.vram_mb}); + try writer.print("\tVRAM: {d} MB\n", .{gpu.vram_mb}); } if (gpu.utilization_percent) |util| { - try writer.print(" Utilization: {d}%\n", .{util}); + try writer.print("\tUtilization: {d}%\n", .{util}); } if (gpu.temperature_celsius) |temp| { - try writer.print(" Temperature: {d}°C\n", .{temp}); + try writer.print("\tTemperature: {d}°C\n", .{temp}); } if (gpu.power_mw) |power| { - try writer.print(" Power: {d:.1f} W\n", .{@as(f64, @floatFromInt(power)) / 1000.0}); + try writer.print("\tPower: {d:.1f} W\n", .{@as(f64, @floatFromInt(power)) / 1000.0}); } try writer.writeAll("\n"); } - try writer.writeAll("💡 Note: Detailed GPU metrics require powermetrics (sudo)\n"); + try writer.writeAll("Note: Detailed GPU metrics require powermetrics (sudo)\n"); return buf.toOwnedSlice(); } diff --git a/cli/src/native/nvml.zig b/cli/src/native/nvml.zig index 5616db4..5ca29e5 100644 --- a/cli/src/native/nvml.zig +++ b/cli/src/native/nvml.zig @@ -352,18 +352,18 @@ pub fn formatGPUInfo(allocator: std.mem.Allocator, gpus: []const GPUInfo) ![]u8 for (gpus) |gpu| { const name = std.mem.sliceTo(&gpu.name, 0); - try writer.print("🎮 GPU {d}: {s}\n", .{ gpu.index, name }); - try writer.print(" Utilization: {d}%\n", .{gpu.utilization}); - try writer.print(" Memory: {d}/{d} MB\n", .{ + try writer.print("GPU {d}: {s}\n", .{ gpu.index, name }); + try writer.print("\tUtilization: {d}%\n", .{gpu.utilization}); + try writer.print("\tMemory: {d}/{d} MB\n", .{ gpu.memory_used / 1024 / 1024, gpu.memory_total / 1024 / 1024, }); - try writer.print(" Temperature: {d}°C\n", .{gpu.temperature}); + try writer.print("\tTemperature: {d}°C\n", .{gpu.temperature}); if (gpu.power_draw > 0) { - try writer.print(" Power: {d:.1} W\n", .{@as(f64, @floatFromInt(gpu.power_draw)) / 1000.0}); + try writer.print("\tPower: {d:.1} W\n", .{@as(f64, @floatFromInt(gpu.power_draw)) / 1000.0}); } if (gpu.clock_sm > 0) { - try writer.print(" SM Clock: {d} MHz\n", .{gpu.clock_sm}); + try writer.print("\tSM Clock: {d} MHz\n", .{gpu.clock_sm}); } try writer.writeAll("\n"); } diff --git a/cli/src/server/experiment_api.zig b/cli/src/server/experiment_api.zig index 7c3229c..677de02 100644 --- a/cli/src/server/experiment_api.zig +++ b/cli/src/server/experiment_api.zig @@ -113,8 +113,8 @@ pub fn list(allocator: std.mem.Allocator, json: bool) !void { while (idx < max_display) : (idx += 1) { const entry = entries[entries.len - idx - 1]; std.debug.print("{d:2}) Alias: {s}\n", .{ idx + 1, entry.job_name }); - std.debug.print(" Commit: {s}\n", .{entry.commit_id}); - std.debug.print(" Queued: {d}\n\n", .{entry.queued_at}); + std.debug.print("\t\tCommit: {s}\n", .{entry.commit_id}); + std.debug.print("\t\tQueued: {d}\n\n", .{entry.queued_at}); } if (entries.len > max_display) { diff --git a/cli/src/ui/progress.zig b/cli/src/ui/progress.zig deleted file mode 100644 index bee6c2f..0000000 --- a/cli/src/ui/progress.zig +++ /dev/null @@ -1,151 +0,0 @@ -const std = @import("std"); -const colors = @import("../utils/colors.zig"); - -/// ProgressBar provides visual feedback for long-running operations. -/// It displays progress as a percentage, item count, and throughput rate. -pub const ProgressBar = struct { - total: usize, - current: usize, - label: []const u8, - start_time: i64, - width: usize, - - /// Initialize a new progress bar - pub fn init(total: usize, label: []const u8) ProgressBar { - return .{ - .total = total, - .current = 0, - .label = label, - .start_time = std.time.milliTimestamp(), - .width = 40, // Default bar width - }; - } - - /// Update the progress bar with current progress - pub fn update(self: *ProgressBar, current: usize) void { - self.current = current; - self.render(); - } - - /// Increment progress by one step - pub fn increment(self: *ProgressBar) void { - self.current += 1; - self.render(); - } - - /// Render the progress bar to stderr - fn render(self: ProgressBar) void { - const percent = if (self.total > 0) - @divFloor(self.current * 100, self.total) - else - 0; - - const elapsed_ms = std.time.milliTimestamp() - self.start_time; - const rate = if (elapsed_ms > 0 and self.current > 0) - @as(f64, @floatFromInt(self.current)) / (@as(f64, @floatFromInt(elapsed_ms)) / 1000.0) - else - 0.0; - - // Build progress bar - const filled = if (self.total > 0) - @divFloor(self.current * self.width, self.total) - else - 0; - const empty = self.width - filled; - - var bar_buf: [64]u8 = undefined; - var bar_stream = std.io.fixedBufferStream(&bar_buf); - const bar_writer = bar_stream.writer(); - - // Write filled portion - var i: usize = 0; - while (i < filled) : (i += 1) { - _ = bar_writer.write("=") catch {}; - } - // Write empty portion - i = 0; - while (i < empty) : (i += 1) { - _ = bar_writer.write("-") catch {}; - } - - const bar = bar_stream.getWritten(); - - // Clear line and print progress - const stderr = std.io.getStdErr().writer(); - stderr.print("\r{s} [{s}] {d}/{d} {d}% ({d:.1} items/s)", .{ - self.label, - bar, - self.current, - self.total, - percent, - rate, - }) catch {}; - } - - /// Finish the progress bar and print a newline - pub fn finish(self: ProgressBar) void { - self.render(); - const stderr = std.io.getStdErr().writer(); - stderr.print("\n", .{}) catch {}; - } - - /// Complete with a success message - pub fn success(self: ProgressBar, msg: []const u8) void { - self.current = self.total; - self.render(); - colors.printSuccess("\n{s}\n", .{msg}); - } - - /// Get elapsed time in milliseconds - pub fn elapsedMs(self: ProgressBar) i64 { - return std.time.milliTimestamp() - self.start_time; - } - - /// Get current throughput (items per second) - pub fn throughput(self: ProgressBar) f64 { - const elapsed_ms = self.elapsedMs(); - if (elapsed_ms > 0 and self.current > 0) { - return @as(f64, @floatFromInt(self.current)) / (@as(f64, @floatFromInt(elapsed_ms)) / 1000.0); - } - return 0.0; - } -}; - -/// Spinner provides visual feedback for indeterminate operations -pub const Spinner = struct { - label: []const u8, - start_time: i64, - frames: []const u8, - frame_idx: usize, - - const DEFAULT_FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"; - - pub fn init(label: []const u8) Spinner { - return .{ - .label = label, - .start_time = std.time.milliTimestamp(), - .frames = DEFAULT_FRAMES, - .frame_idx = 0, - }; - } - - /// Render one frame of the spinner - pub fn tick(self: *Spinner) void { - const frame = self.frames[self.frame_idx % self.frames.len]; - const stderr = std.io.getStdErr().writer(); - stderr.print("\r{s} {c} ", .{ self.label, frame }) catch {}; - self.frame_idx += 1; - } - - /// Stop the spinner and print a newline - pub fn stop(self: Spinner) void { - _ = self; // Intentionally unused - for API consistency - const stderr = std.io.getStdErr().writer(); - stderr.print("\n", .{}) catch {}; - } - - /// Get elapsed time in seconds - pub fn elapsedSec(self: Spinner) i64 { - return @divFloor(std.time.milliTimestamp() - self.start_time, 1000); - } -};