From ae74bfd407e163df01f787c434b505a437f18d30 Mon Sep 17 00:00:00 2001 From: Oliver Kwun-Morfitt Date: Sat, 20 Sep 2025 21:55:46 -0400 Subject: [PATCH 01/12] set up kong and got initial file structure and "mist help" working --- .DS_Store | Bin 0 -> 6148 bytes cli/cmd/help.go | 16 +++++++++++ cli/cmd/job.go | 14 +++++++++ cli/cmd/job_list.go | 67 ++++++++++++++++++++++++++++++++++++++++++++ cli/cmd/root.go | 26 +++++++++++++++++ cli/docs/setup.md | 8 ++++++ cli/go.mod | 5 ++++ cli/go.sum | 2 ++ cli/main.go | 5 ++++ 9 files changed, 143 insertions(+) create mode 100644 .DS_Store create mode 100644 cli/cmd/help.go create mode 100644 cli/cmd/job.go create mode 100644 cli/cmd/job_list.go create mode 100644 cli/cmd/root.go create mode 100644 cli/docs/setup.md create mode 100644 cli/go.mod create mode 100644 cli/go.sum create mode 100644 cli/main.go diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6df9d253a2aae9e0f803c35c0ecf0c9a0108d468 GIT binary patch literal 6148 zcmeHK-AcnS6i(c98AIrW!Y%{e4&09nhc~6p7qFriDzl|Si?tbR=Pt&e*ZM*}iO=IX zNeT{oE#l6BM`ap#soA(j!K1~yE3$6lMy+NkCjK!D(;Zk*iU^+mR=O z;dRP7Z8q*|%82J1BNFul_tuRQd>>GP}$oBnF59Vt^RfZU*eR zAX?i^1FfDIAO6T?p*=uD!Mp+$5YRU+0bt-h($+x}m#9OYYq2nhqo7}x Q1JXr66G9y^@Cyul0r>VwYybcN literal 0 HcmV?d00001 diff --git a/cli/cmd/help.go b/cli/cmd/help.go new file mode 100644 index 0000000..cf571e2 --- /dev/null +++ b/cli/cmd/help.go @@ -0,0 +1,16 @@ +package cmd + +import "fmt" + +type HelpCmd struct{} + +func (h *HelpCmd) Run() error { + fmt.Println("MIST CLI Help") + fmt.Println("Usage: mist [command] [options]") + fmt.Println("Commands:") + fmt.Println(" auth Authentication commands") + fmt.Println(" job Job management commands") + fmt.Println(" config Configuration commands") + fmt.Println(" help Show help information") + return nil +} diff --git a/cli/cmd/job.go b/cli/cmd/job.go new file mode 100644 index 0000000..45dce23 --- /dev/null +++ b/cli/cmd/job.go @@ -0,0 +1,14 @@ +package cmd + +type JobCmd struct { + // Submit SubmitCmd `cmd:"" help:"Submit a new job"` + // Status StatusCmd `cmd:"" help:"Check the status of a job"` + // Cancel CancelCmd `cmd:"" help:"Cancel a running job"` + List ListCmd `cmd:"" help:"List all jobs" default:1` +} + +func (j *JobCmd) Run() error { + // Possible fallback if no subcommand is provided + // fmt.Println("(job root) – try 'mist job submit|status|list|cancel' or mist help") + return nil +} diff --git a/cli/cmd/job_list.go b/cli/cmd/job_list.go new file mode 100644 index 0000000..118df0e --- /dev/null +++ b/cli/cmd/job_list.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "fmt" + "os" + "text/tabwriter" + "time" +) + +type ListCmd struct { + All bool `help:"List all jobs, including completed and failed ones." short:"a"` +} + +type Job struct { + ID string + Name string + Status string + GPUType string + CreatedAt time.Time +} + +func (l *ListCmd) Run() error { + // Mock data - pull from API in real implementation + jobs := []Job{ + { + ID: "ID:1", + Name: "docker_container_name_1", + Status: "Running", + GPUType: "AMD", + CreatedAt: time.Now(), + }, + { + ID: "ID:2", + Name: "docker_container_name_2", + Status: "Enqueued", + GPUType: "TT", + CreatedAt: time.Now().Add(-time.Hour * 24), + }, + { + ID: "ID:3", + Name: "docker_container_name_3", + Status: "Running", + GPUType: "TT", + CreatedAt: time.Now().Add(-time.Hour * 24), + }, + } + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + fmt.Fprintln(w, "Job ID\tName\tStatus\tGPU Type\tCreated At") + fmt.Fprintln(w, "--------------------------------------------------------------") + + for _, job := range jobs { + // Maybe filter based on running? + fmt.Fprintf( + w, + "%s\t%s\t%s\t%s\t%s\n", + job.ID, + job.Name, + job.Status, + job.GPUType, + job.CreatedAt.Format(time.RFC1123), + ) + } + + w.Flush() + + return nil +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go new file mode 100644 index 0000000..791f860 --- /dev/null +++ b/cli/cmd/root.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "github.com/alecthomas/kong" +) + +type CLI struct { + // Define your CLI structure here + // Auth AuthCmd `cmd:"" help:"Authentication commands"` + Job JobCmd `cmd:"" help:"Job management commands"` + // Config ConfigCmd `cmd:"" help:"Configuration commands"` + Help HelpCmd `cmd:"" help:"Show help information"` +} + +func Main() { + var cli CLI + ctx := kong.Parse(&cli, + kong.Name("mist"), + kong.Description("MIST CLI - Manage your MIST jobs and configurations"), + kong.UsageOnError(), + ) + + err := ctx.Run() + ctx.FatalIfErrorf(err) + // fmt.Println("Command executed successfully") +} diff --git a/cli/docs/setup.md b/cli/docs/setup.md new file mode 100644 index 0000000..47f1e99 --- /dev/null +++ b/cli/docs/setup.md @@ -0,0 +1,8 @@ +## Trying out cli + +If you want to try running the cli: +- ```cd cli``` +- ```go build -o ../bin/mist .``` +- ```../bin/mist {parentcommand} {subcommand}``` + + diff --git a/cli/go.mod b/cli/go.mod new file mode 100644 index 0000000..f6e8a65 --- /dev/null +++ b/cli/go.mod @@ -0,0 +1,5 @@ +module mist/cli + +go 1.23.2 + +require github.com/alecthomas/kong v1.12.1 // indirect diff --git a/cli/go.sum b/cli/go.sum new file mode 100644 index 0000000..0b45e8f --- /dev/null +++ b/cli/go.sum @@ -0,0 +1,2 @@ +github.com/alecthomas/kong v1.12.1 h1:iq6aMJDcFYP9uFrLdsiZQ2ZMmcshduyGv4Pek0MQPW0= +github.com/alecthomas/kong v1.12.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= diff --git a/cli/main.go b/cli/main.go new file mode 100644 index 0000000..038f096 --- /dev/null +++ b/cli/main.go @@ -0,0 +1,5 @@ +package main + +import "mist/cli/cmd" + +func main() { cmd.Main() } From 1346eaa5961799e3cf24fb99e3690a5f1222166a Mon Sep 17 00:00:00 2001 From: Oliver Kwun-Morfitt Date: Thu, 25 Sep 2025 14:01:07 -0400 Subject: [PATCH 02/12] added job status command --- cli/cmd/job.go | 2 +- cli/cmd/job_status.go | 45 ++++++++++++++++++++++++++++++++++++ cli/docs/Mist.code-workspace | 10 ++++++++ cli/docs/setup.md | 2 -- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 cli/cmd/job_status.go create mode 100644 cli/docs/Mist.code-workspace diff --git a/cli/cmd/job.go b/cli/cmd/job.go index 45dce23..3fa9a3d 100644 --- a/cli/cmd/job.go +++ b/cli/cmd/job.go @@ -2,7 +2,7 @@ package cmd type JobCmd struct { // Submit SubmitCmd `cmd:"" help:"Submit a new job"` - // Status StatusCmd `cmd:"" help:"Check the status of a job"` + Status JobStatusCmd `cmd:"" help:"Check the status of a job"` // Cancel CancelCmd `cmd:"" help:"Cancel a running job"` List ListCmd `cmd:"" help:"List all jobs" default:1` } diff --git a/cli/cmd/job_status.go b/cli/cmd/job_status.go new file mode 100644 index 0000000..907d8a6 --- /dev/null +++ b/cli/cmd/job_status.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "fmt" + "os" + "text/tabwriter" + "time" +) + +type JobStatusCmd struct { + JobID string `arg:"" help:"The ID of the job to check the status for"` +} + +func (j *JobStatusCmd) Run() error { + + // Get job by id + // job, err := api.GetJob(j.JobID) + // if err != nil { + // fmt.Println("Error fetching job/Job id not found", err) + + job := Job{ + ID: j.JobID, + Name: "docker_container_name_1", + Status: "Running", + GPUType: "AMD", + CreatedAt: time.Now(), + } + + println("Checking status for job ID:", j.JobID) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + fmt.Fprintln(w, "Job ID\tName\tStatus\tGPU Type\tCreated At") + fmt.Fprintln(w, "--------------------------------------------------------------") + + fmt.Fprintf( + w, + "%s\t%s\t%s\t%s\t%s\n", + job.ID, + job.Name, + job.Status, + job.GPUType, + job.CreatedAt.Format(time.RFC1123), + ) + w.Flush() + return nil +} diff --git a/cli/docs/Mist.code-workspace b/cli/docs/Mist.code-workspace new file mode 100644 index 0000000..39f0155 --- /dev/null +++ b/cli/docs/Mist.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "../.." + }, + { + "path": "../.." + } + ] +} \ No newline at end of file diff --git a/cli/docs/setup.md b/cli/docs/setup.md index 47f1e99..f796f0a 100644 --- a/cli/docs/setup.md +++ b/cli/docs/setup.md @@ -4,5 +4,3 @@ If you want to try running the cli: - ```cd cli``` - ```go build -o ../bin/mist .``` - ```../bin/mist {parentcommand} {subcommand}``` - - From c2a04484ef07b262a2b07ab27f73d6fcd0c7df64 Mon Sep 17 00:00:00 2001 From: Oliver Kwun-Morfitt Date: Thu, 25 Sep 2025 18:57:24 -0400 Subject: [PATCH 03/12] Added some logic and files for login and auth. --- cli/cmd/auth.go | 13 +++++++++++++ cli/cmd/auth_login.go | 35 +++++++++++++++++++++++++++++++++++ cli/cmd/root.go | 4 ++-- 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 cli/cmd/auth.go create mode 100644 cli/cmd/auth_login.go diff --git a/cli/cmd/auth.go b/cli/cmd/auth.go new file mode 100644 index 0000000..6df3e45 --- /dev/null +++ b/cli/cmd/auth.go @@ -0,0 +1,13 @@ +package cmd + +type AuthCmd struct { + Login LoginCmd `cmd:"" help:"Log in to your account"` + // Logout LogoutCmd `cmd:"" help:"Log out of your account"` + // Status AuthStatusCmd `cmd:"" help:"Check your authentication status" default:1` +} + +func (a *AuthCmd) Run() error { + // Possible fallback if no subcommand is provided + // fmt.Println("(auth root) – try 'mist auth login|logout|status' or mist help") + return nil +} diff --git a/cli/cmd/auth_login.go b/cli/cmd/auth_login.go new file mode 100644 index 0000000..dc7bdfe --- /dev/null +++ b/cli/cmd/auth_login.go @@ -0,0 +1,35 @@ +package cmd + +import ( + "errors" + "fmt" +) + +// TODO: What credentials are we taking? +type LoginCmd struct { + Username string `arg:"" help:"Your account username"` + Password string `arg:"" help:"Your account password"` +} + +func verifyUser(username, password string) error { + // Placeholder for actual authentication logic + if username == "admin" && password == "password" { + return nil + } + return errors.New("invalid credentials") +} + +// TODO: Figure out how to handle password input without exposing it in the terminal history +// TODO: Where are we storing auth token? Are we getting JWT? +func (l *LoginCmd) Run() error { + // mist auth login + + err := verifyUser(l.Username, l.Password) + if err != nil { + fmt.Println("Error during authentication:", err) + } + + fmt.Println("Logging in with username:", l.Username) + + return nil +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 791f860..386ca30 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -6,8 +6,8 @@ import ( type CLI struct { // Define your CLI structure here - // Auth AuthCmd `cmd:"" help:"Authentication commands"` - Job JobCmd `cmd:"" help:"Job management commands"` + Auth AuthCmd `cmd:"" help:"Authentication commands"` + Job JobCmd `cmd:"" help:"Job management commands"` // Config ConfigCmd `cmd:"" help:"Configuration commands"` Help HelpCmd `cmd:"" help:"Show help information"` } From 5b14b8b0f8d1464447d8cdce541440df4acb23e6 Mon Sep 17 00:00:00 2001 From: Oliver Kwun-Morfitt Date: Thu, 25 Sep 2025 19:25:40 -0400 Subject: [PATCH 04/12] Added initial logic for submitting job --- cli/cmd/job.go | 2 +- cli/cmd/job_submit.go | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 cli/cmd/job_submit.go diff --git a/cli/cmd/job.go b/cli/cmd/job.go index 3fa9a3d..faef3bf 100644 --- a/cli/cmd/job.go +++ b/cli/cmd/job.go @@ -1,7 +1,7 @@ package cmd type JobCmd struct { - // Submit SubmitCmd `cmd:"" help:"Submit a new job"` + Submit JobSubmitCmd `cmd:"" help:"Submit a new job"` Status JobStatusCmd `cmd:"" help:"Check the status of a job"` // Cancel CancelCmd `cmd:"" help:"Cancel a running job"` List ListCmd `cmd:"" help:"List all jobs" default:1` diff --git a/cli/cmd/job_submit.go b/cli/cmd/job_submit.go new file mode 100644 index 0000000..0c1a7be --- /dev/null +++ b/cli/cmd/job_submit.go @@ -0,0 +1,62 @@ +package cmd + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +type JobSubmitCmd struct { + Script string `arg:"" help:"Path to the job script file to submit"` + Compute string `help:"Type of compute required for the job: AMD|TT|CPU" default:"AMD"` +} + +func (j *JobSubmitCmd) Run() error { + // mist job submit