- Add jupyter.zig command with start/stop/status actions - Update main.zig to include jupyter command in CLI - CLI now handles all Jupyter setup transparently - Data scientists only need: ml jupyter start - Auto-detects container runtime (Podman/Docker) - Manages container lifecycle automatically - Provides clear status and error messages
129 lines
5.2 KiB
Zig
129 lines
5.2 KiB
Zig
const std = @import("std");
|
|
const errors = @import("errors.zig");
|
|
const colors = @import("utils/colors.zig");
|
|
|
|
// Global verbosity level
|
|
var verbose_mode: bool = false;
|
|
var quiet_mode: bool = false;
|
|
|
|
const commands = struct {
|
|
const init = @import("commands/init.zig");
|
|
const sync = @import("commands/sync.zig");
|
|
const queue = @import("commands/queue.zig");
|
|
const status = @import("commands/status.zig");
|
|
const monitor = @import("commands/monitor.zig");
|
|
const cancel = @import("commands/cancel.zig");
|
|
const prune = @import("commands/prune.zig");
|
|
const watch = @import("commands/watch.zig");
|
|
const dataset = @import("commands/dataset.zig");
|
|
const experiment = @import("commands/experiment.zig");
|
|
const jupyter = @import("commands/jupyter.zig");
|
|
};
|
|
|
|
pub fn main() !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
// Parse command line arguments
|
|
var args_iter = std.process.args();
|
|
_ = args_iter.next(); // Skip executable name
|
|
|
|
var command_args = std.ArrayList([]const u8).initCapacity(allocator, 10) catch |err| {
|
|
colors.printError("Failed to allocate command args: {}\n", .{err});
|
|
return err;
|
|
};
|
|
defer command_args.deinit(allocator);
|
|
|
|
// Parse global flags first
|
|
while (args_iter.next()) |arg| {
|
|
if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
|
|
printUsage();
|
|
return;
|
|
} else if (std.mem.eql(u8, arg, "--verbose") or std.mem.eql(u8, arg, "-v")) {
|
|
verbose_mode = true;
|
|
quiet_mode = false;
|
|
} else if (std.mem.eql(u8, arg, "--quiet") or std.mem.eql(u8, arg, "-q")) {
|
|
quiet_mode = true;
|
|
verbose_mode = false;
|
|
} else {
|
|
command_args.append(allocator, arg) catch |err| {
|
|
colors.printError("Failed to append argument: {}\n", .{err});
|
|
return err;
|
|
};
|
|
}
|
|
}
|
|
|
|
const args = command_args.items;
|
|
|
|
if (args.len < 1) {
|
|
colors.printError("No command specified.\n", .{});
|
|
printUsage();
|
|
return;
|
|
}
|
|
|
|
const command = args[0];
|
|
|
|
// Handle commands with proper error handling
|
|
if (std.mem.eql(u8, command, "--help") or std.mem.eql(u8, command, "help")) {
|
|
printUsage();
|
|
return;
|
|
}
|
|
|
|
const command_result = if (std.mem.eql(u8, command, "init"))
|
|
commands.init.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "sync"))
|
|
commands.sync.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "queue"))
|
|
commands.queue.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "status"))
|
|
commands.status.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "monitor"))
|
|
commands.monitor.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "cancel"))
|
|
commands.cancel.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "prune"))
|
|
commands.prune.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "watch"))
|
|
commands.watch.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "dataset"))
|
|
commands.dataset.run(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "experiment"))
|
|
commands.experiment.execute(allocator, args[1..])
|
|
else if (std.mem.eql(u8, command, "jupyter"))
|
|
commands.jupyter.run(allocator, args[1..])
|
|
else
|
|
error.InvalidArguments;
|
|
|
|
// Handle any errors that occur during command execution
|
|
command_result catch |err| {
|
|
errors.ErrorHandler.handleCommandError(err, command);
|
|
};
|
|
}
|
|
|
|
pub fn printUsage() void {
|
|
colors.printInfo("ML Experiment Manager\n\n", .{});
|
|
std.debug.print("Usage: ml <command> [options]\n\n", .{});
|
|
std.debug.print("Commands:\n", .{});
|
|
std.debug.print(" init Setup configuration interactively\n", .{});
|
|
std.debug.print(" sync <path> Sync project to server\n", .{});
|
|
std.debug.print(" queue <job> Queue job for execution\n", .{});
|
|
std.debug.print(" status Get system status\n", .{});
|
|
std.debug.print(" monitor Launch TUI via SSH\n", .{});
|
|
std.debug.print(" cancel <job> Cancel running job\n", .{});
|
|
std.debug.print(" prune --keep N Keep N most recent experiments\n", .{});
|
|
std.debug.print(" prune --older-than D Remove experiments older than D days\n", .{});
|
|
std.debug.print(" watch <path> Watch directory for auto-sync\n", .{});
|
|
std.debug.print(" dataset <action> Manage datasets (list, upload, download, delete)\n", .{});
|
|
std.debug.print(" experiment <action> Manage experiments (log, show)\n", .{});
|
|
std.debug.print(" jupyter <action> Manage Jupyter notebooks (start, stop, status)\n\n", .{});
|
|
std.debug.print("Options:\n", .{});
|
|
std.debug.print(" --help Show this help message\n", .{});
|
|
std.debug.print(" --verbose Enable verbose output\n", .{});
|
|
std.debug.print(" --quiet Suppress non-error output\n", .{});
|
|
std.debug.print(" --monitor Monitor progress of long-running operations\n", .{});
|
|
}
|
|
|
|
test "basic test" {
|
|
try std.testing.expectEqual(@as(i32, 10), 10);
|
|
}
|