From 04404f43148ca624d0b1a9624b810b5f7faa3073 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 14:23:11 -0500 Subject: [PATCH 01/32] Start on 'view' command --- cmd/root.go | 2 ++ cmd/view/view.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 cmd/view/view.go diff --git a/cmd/root.go b/cmd/root.go index ed72d299..014f4ee1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/github/gh-models/cmd/list" "github.com/github/gh-models/cmd/run" + "github.com/github/gh-models/cmd/view" "github.com/spf13/cobra" ) @@ -14,6 +15,7 @@ func NewRootCommand() *cobra.Command { cmd.AddCommand(list.NewListCommand()) cmd.AddCommand(run.NewRunCommand()) + cmd.AddCommand(view.NewViewCommand()) return cmd } diff --git a/cmd/view/view.go b/cmd/view/view.go new file mode 100644 index 00000000..133e5f06 --- /dev/null +++ b/cmd/view/view.go @@ -0,0 +1,15 @@ +package view + +import "github.com/spf13/cobra" + +func NewViewCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "view", + Short: "View details about a model", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return nil + }, + } + return cmd +} From 2ac9122d2b34809f8ad534711d01624a7b942c63 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 14:31:30 -0500 Subject: [PATCH 02/32] Prompt to select a model if none specified As taken from the run command. --- cmd/view/view.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/cmd/view/view.go b/cmd/view/view.go index 133e5f06..ad8e5888 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -1,13 +1,79 @@ package view -import "github.com/spf13/cobra" +import ( + "errors" + "io" + "strings" + + "github.com/AlecAivazis/survey/v2" + "github.com/cli/go-gh/v2/pkg/auth" + "github.com/cli/go-gh/v2/pkg/term" + "github.com/github/gh-models/internal/azure_models" + "github.com/github/gh-models/internal/ux" + "github.com/spf13/cobra" +) func NewViewCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "view", + Use: "view [model]", Short: "View details about a model", - Args: cobra.NoArgs, + Args: cobra.ArbitraryArgs, RunE: func(cmd *cobra.Command, args []string) error { + terminal := term.FromEnv() + out := terminal.Out() + + token, _ := auth.TokenForHost("github.com") + if token == "" { + io.WriteString(out, "No GitHub token found. Please run 'gh auth login' to authenticate.\n") + return nil + } + + client := azure_models.NewClient(token) + + models, err := client.ListModels() + if err != nil { + return err + } + + ux.SortModels(models) + + modelName := "" + switch { + case len(args) == 0: + // Need to prompt for a model + prompt := &survey.Select{ + Message: "Select a model:", + Options: []string{}, + } + + for _, model := range models { + if !ux.IsChatModel(model) { + continue + } + prompt.Options = append(prompt.Options, model.FriendlyName) + } + + err = survey.AskOne(prompt, &modelName, survey.WithPageSize(10)) + if err != nil { + return err + } + + case len(args) >= 1: + modelName = args[0] + } + + for _, model := range models { + if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { + modelName = model.Name + break + } + } + + if modelName == "" { + return errors.New("the specified model name is not supported") + } + + io.WriteString(out, "You selected: "+modelName+"\n") return nil }, } From 08b184a313159d073f5d134290778fd79b985cef Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 14:52:17 -0500 Subject: [PATCH 03/32] Add util.GetValidModelName --- pkg/util/models.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 pkg/util/models.go diff --git a/pkg/util/models.go b/pkg/util/models.go new file mode 100644 index 00000000..a3b33635 --- /dev/null +++ b/pkg/util/models.go @@ -0,0 +1,18 @@ +package util + +import ( + "strings" + + "github.com/github/gh-models/internal/azure_models" +) + +// GetValidModelName checks whether the given raw model name is a valid one, based on the provided list of models. +// If the given name does not represent a valid model, it returns nil. +func GetValidModelName(candidateModelName string, models []*azure_models.ModelSummary) *string { + for _, model := range models { + if strings.EqualFold(model.FriendlyName, candidateModelName) || strings.EqualFold(model.Name, candidateModelName) { + return &model.Name + } + } + return nil +} From 5ebf021497c22aeae80e19db8a3bbae27db76a66 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 14:52:40 -0500 Subject: [PATCH 04/32] Bail early when specified model name is invalid --- cmd/view/view.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/cmd/view/view.go b/cmd/view/view.go index ad8e5888..9e776a5e 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -1,15 +1,15 @@ package view import ( - "errors" + "fmt" "io" - "strings" "github.com/AlecAivazis/survey/v2" "github.com/cli/go-gh/v2/pkg/auth" "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" "github.com/github/gh-models/internal/ux" + "github.com/github/gh-models/pkg/util" "github.com/spf13/cobra" ) @@ -62,15 +62,11 @@ func NewViewCommand() *cobra.Command { modelName = args[0] } - for _, model := range models { - if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { - modelName = model.Name - break - } - } - - if modelName == "" { - return errors.New("the specified model name is not supported") + validModelName := util.GetValidModelName(modelName, models) + if validModelName == nil { + return fmt.Errorf("the specified model name is not supported: %s", modelName) + } else { + modelName = *validModelName } io.WriteString(out, "You selected: "+modelName+"\n") From 1e92fd91bc2bfd3d55c7bebd199e6a75270b2a17 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 14:54:19 -0500 Subject: [PATCH 05/32] Bail early when provided model name for 'run' is invalid --- cmd/run/run.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/cmd/run/run.go b/cmd/run/run.go index 69928884..2290cef6 100644 --- a/cmd/run/run.go +++ b/cmd/run/run.go @@ -16,6 +16,7 @@ import ( "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" "github.com/github/gh-models/internal/ux" + "github.com/github/gh-models/pkg/util" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -226,15 +227,11 @@ func NewRunCommand() *cobra.Command { modelName = args[0] } - for _, model := range models { - if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { - modelName = model.Name - break - } - } - - if modelName == "" { - return errors.New("the specified model name is not supported") + validModelName := util.GetValidModelName(modelName, models) + if validModelName == nil { + return fmt.Errorf("the specified model name is not supported: %s", modelName) + } else { + modelName = *validModelName } initialPrompt := "" From f9b76949c448bfa2d2a45b83aef3ba2b473c03d7 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:09:46 -0500 Subject: [PATCH 06/32] Replace with ValidateModelName --- cmd/run/run.go | 8 +++----- cmd/view/view.go | 9 +++------ pkg/util/models.go | 12 ++++++------ 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/cmd/run/run.go b/cmd/run/run.go index 2290cef6..f0be2f01 100644 --- a/cmd/run/run.go +++ b/cmd/run/run.go @@ -227,11 +227,9 @@ func NewRunCommand() *cobra.Command { modelName = args[0] } - validModelName := util.GetValidModelName(modelName, models) - if validModelName == nil { - return fmt.Errorf("the specified model name is not supported: %s", modelName) - } else { - modelName = *validModelName + modelName, err = util.ValidateModelName(modelName, models) + if err != nil { + return err } initialPrompt := "" diff --git a/cmd/view/view.go b/cmd/view/view.go index 9e776a5e..02cba1cf 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -1,7 +1,6 @@ package view import ( - "fmt" "io" "github.com/AlecAivazis/survey/v2" @@ -62,11 +61,9 @@ func NewViewCommand() *cobra.Command { modelName = args[0] } - validModelName := util.GetValidModelName(modelName, models) - if validModelName == nil { - return fmt.Errorf("the specified model name is not supported: %s", modelName) - } else { - modelName = *validModelName + modelName, err = util.ValidateModelName(modelName, models) + if err != nil { + return err } io.WriteString(out, "You selected: "+modelName+"\n") diff --git a/pkg/util/models.go b/pkg/util/models.go index a3b33635..d19a2393 100644 --- a/pkg/util/models.go +++ b/pkg/util/models.go @@ -1,18 +1,18 @@ package util import ( + "fmt" "strings" "github.com/github/gh-models/internal/azure_models" ) -// GetValidModelName checks whether the given raw model name is a valid one, based on the provided list of models. -// If the given name does not represent a valid model, it returns nil. -func GetValidModelName(candidateModelName string, models []*azure_models.ModelSummary) *string { +// ValidateModelName checks whether the given model name is a valid one, based on the provided list of models. +func ValidateModelName(modelName string, models []*azure_models.ModelSummary) (string, error) { for _, model := range models { - if strings.EqualFold(model.FriendlyName, candidateModelName) || strings.EqualFold(model.Name, candidateModelName) { - return &model.Name + if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { + return model.Name, nil } } - return nil + return "", fmt.Errorf("the specified model name is not supported: %s", modelName) } From c873994b7999f419c7785a6f359dd98ddae44c10 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:16:49 -0500 Subject: [PATCH 07/32] Replace with GetModelByName, output friendly name --- cmd/run/run.go | 3 ++- cmd/view/view.go | 4 ++-- pkg/util/models.go | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cmd/run/run.go b/cmd/run/run.go index f0be2f01..bf81a11d 100644 --- a/cmd/run/run.go +++ b/cmd/run/run.go @@ -227,10 +227,11 @@ func NewRunCommand() *cobra.Command { modelName = args[0] } - modelName, err = util.ValidateModelName(modelName, models) + model, err := util.GetModelByName(modelName, models) if err != nil { return err } + modelName = model.Name initialPrompt := "" singleShot := false diff --git a/cmd/view/view.go b/cmd/view/view.go index 02cba1cf..5dd96a01 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -61,12 +61,12 @@ func NewViewCommand() *cobra.Command { modelName = args[0] } - modelName, err = util.ValidateModelName(modelName, models) + model, err := util.GetModelByName(modelName, models) if err != nil { return err } - io.WriteString(out, "You selected: "+modelName+"\n") + io.WriteString(out, "You selected: "+model.FriendlyName+"\n") return nil }, } diff --git a/pkg/util/models.go b/pkg/util/models.go index d19a2393..a7af7c49 100644 --- a/pkg/util/models.go +++ b/pkg/util/models.go @@ -7,12 +7,12 @@ import ( "github.com/github/gh-models/internal/azure_models" ) -// ValidateModelName checks whether the given model name is a valid one, based on the provided list of models. -func ValidateModelName(modelName string, models []*azure_models.ModelSummary) (string, error) { +// GetModelByName returns the model with the specified name, or an error if no such model exists within the given list. +func GetModelByName(modelName string, models []*azure_models.ModelSummary) (*azure_models.ModelSummary, error) { for _, model := range models { if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { - return model.Name, nil + return model, nil } } - return "", fmt.Errorf("the specified model name is not supported: %s", modelName) + return nil, fmt.Errorf("the specified model name is not supported: %s", modelName) } From 07858b8d9e8a18e932afc5dad061d5bee98b028f Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:20:33 -0500 Subject: [PATCH 08/32] Pull out LightGrayUnderline shared color --- cmd/list/list.go | 8 ++------ pkg/util/colors.go | 7 +++++++ 2 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 pkg/util/colors.go diff --git a/cmd/list/list.go b/cmd/list/list.go index 2a3c73f0..cd7e7127 100644 --- a/cmd/list/list.go +++ b/cmd/list/list.go @@ -9,14 +9,10 @@ import ( "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" "github.com/github/gh-models/internal/ux" - "github.com/mgutz/ansi" + "github.com/github/gh-models/pkg/util" "github.com/spf13/cobra" ) -var ( - lightGrayUnderline = ansi.ColorFunc("white+du") -) - func NewListCommand() *cobra.Command { cmd := &cobra.Command{ Use: "list", @@ -55,7 +51,7 @@ func NewListCommand() *cobra.Command { width, _, _ := terminal.Size() printer := tableprinter.New(out, isTTY, width) - printer.AddHeader([]string{"Display Name", "Model Name"}, tableprinter.WithColor(lightGrayUnderline)) + printer.AddHeader([]string{"Display Name", "Model Name"}, tableprinter.WithColor(util.LightGrayUnderline)) printer.EndRow() for _, model := range models { diff --git a/pkg/util/colors.go b/pkg/util/colors.go new file mode 100644 index 00000000..0a541c2f --- /dev/null +++ b/pkg/util/colors.go @@ -0,0 +1,7 @@ +package util + +import "github.com/mgutz/ansi" + +var ( + LightGrayUnderline = ansi.ColorFunc("white+du") +) From 8602571557f252391235abc0c634c38f1b592e77 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:34:22 -0500 Subject: [PATCH 09/32] Pull out modelPrinter type --- cmd/view/model_printer.go | 37 +++++++++++++++++++++++++++++++++++++ cmd/view/view.go | 11 ++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 cmd/view/model_printer.go diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go new file mode 100644 index 00000000..dae46a24 --- /dev/null +++ b/cmd/view/model_printer.go @@ -0,0 +1,37 @@ +package view + +import ( + "github.com/cli/go-gh/v2/pkg/tableprinter" + "github.com/cli/go-gh/v2/pkg/term" + "github.com/github/gh-models/internal/azure_models" + "github.com/github/gh-models/pkg/util" +) + +type modelPrinter struct { + model *azure_models.ModelSummary + printer tableprinter.TablePrinter +} + +func newModelPrinter(model *azure_models.ModelSummary, terminal term.Term) modelPrinter { + width, _, _ := terminal.Size() + printer := tableprinter.New(terminal.Out(), terminal.IsTerminalOutput(), width) + return modelPrinter{model: model, printer: printer} +} + +func (p *modelPrinter) render() error { + p.addLabeledValue("Display Name", p.model.FriendlyName) + p.addLabeledValue("Model Name", p.model.Name) + + err := p.printer.Render() + if err != nil { + return err + } + + return nil +} + +func (p *modelPrinter) addLabeledValue(label string, value string) { + p.printer.AddField(label, tableprinter.WithColor(util.LightGrayUnderline)) + p.printer.AddField(value) + p.printer.EndRow() +} diff --git a/cmd/view/view.go b/cmd/view/view.go index 5dd96a01..ff3d3056 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -19,11 +19,10 @@ func NewViewCommand() *cobra.Command { Args: cobra.ArbitraryArgs, RunE: func(cmd *cobra.Command, args []string) error { terminal := term.FromEnv() - out := terminal.Out() token, _ := auth.TokenForHost("github.com") if token == "" { - io.WriteString(out, "No GitHub token found. Please run 'gh auth login' to authenticate.\n") + io.WriteString(terminal.Out(), "No GitHub token found. Please run 'gh auth login' to authenticate.\n") return nil } @@ -66,7 +65,13 @@ func NewViewCommand() *cobra.Command { return err } - io.WriteString(out, "You selected: "+model.FriendlyName+"\n") + modelPrinter := newModelPrinter(model, terminal) + + err = modelPrinter.render() + if err != nil { + return err + } + return nil }, } From b995626e39812fec02442340a1d261bdd6e9b379 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:40:46 -0500 Subject: [PATCH 10/32] Show publisher and summary fields --- cmd/view/model_printer.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index dae46a24..205eadc0 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -19,8 +19,10 @@ func newModelPrinter(model *azure_models.ModelSummary, terminal term.Term) model } func (p *modelPrinter) render() error { - p.addLabeledValue("Display Name", p.model.FriendlyName) - p.addLabeledValue("Model Name", p.model.Name) + p.addLabeledValue("Display name:", p.model.FriendlyName) + p.addLabeledValue("Model name:", p.model.Name) + p.addLabeledValue("Publisher:", p.model.Publisher) + p.addLabeledValue("Summary:", p.model.Summary) err := p.printer.Render() if err != nil { From 7aa576eb2511cbf9fc86b6b2ea8813e04a811b76 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:45:27 -0500 Subject: [PATCH 11/32] Pull out azureAiStudioURL constant --- internal/azure_models/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 2fcfbe5f..7c2325ac 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -19,7 +19,8 @@ type Client struct { const ( prodInferenceURL = "https://models.inference.ai.azure.com/chat/completions" - prodModelsURL = "https://api.catalog.azureml.ms/asset-gallery/v1.0/models" + azureAiStudioURL = "https://api.catalog.azureml.ms" + prodModelsURL = azureAiStudioURL + "/asset-gallery/v1.0/models" ) func NewClient(authToken string) *Client { From d75afc96304149bd2497546fd5f13f364379f0c5 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:45:56 -0500 Subject: [PATCH 12/32] Start on client GetModelDetails Based on https://github.com/github/github/blob/e8381fbe7672a009dc8e76045148b7af8fcd7a28/packages/marketplace/app/models/azure_models/client.rb#L36-L43 --- internal/azure_models/client.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 7c2325ac..d2d9de47 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "io" "net/http" "strings" @@ -84,6 +85,29 @@ func (c *Client) GetChatCompletionStream(req ChatCompletionOptions) (*ChatComple return &chatCompletionResponse, nil } +func (c *Client) GetModelDetails(registry string, modelName string, version string) error { + url := fmt.Sprintf("%s/asset-gallery/v1.0/%s/models/%s/version/%s", azureAiStudioURL, registry, modelName, version) + httpReq, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + + httpReq.Header.Set("Content-Type", "application/json") + + resp, err := c.client.Do(httpReq) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return c.handleHTTPError(resp) + } + + fmt.Println(resp.Body) + + return nil +} + func (c *Client) ListModels() ([]*ModelSummary, error) { body := bytes.NewReader([]byte(` { From 02ca3975b8c311cacd9e912e7a384651d17f97c7 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:53:20 -0500 Subject: [PATCH 13/32] Get the version and registry name, too Necessary for fetching details of a particular model. --- internal/azure_models/client.go | 2 ++ internal/azure_models/types.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index d2d9de47..66d51150 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -160,6 +160,8 @@ func (c *Client) ListModels() ([]*ModelSummary, error) { Task: inferenceTask, Publisher: summary.Publisher, Summary: summary.Summary, + Version: summary.Version, + RegistryName: summary.RegistryName, }) } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index c3f7acfb..29e3c725 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -65,6 +65,7 @@ type modelCatalogSearchSummary struct { Popularity json.Number `json:"popularity"` Publisher string `json:"publisher"` RegistryName string `json:"registryName"` + Version string `json:"version"` Summary string `json:"summary"` } @@ -75,6 +76,8 @@ type ModelSummary struct { Task string `json:"task"` Publisher string `json:"publisher"` Summary string `json:"summary"` + Version string `json:"version"` + RegistryName string `json:"registry_name"` } func Ptr[T any](value T) *T { From a042eb68a7e1321eb5b54be1c9521c5f96de6ca7 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 15:57:29 -0500 Subject: [PATCH 14/32] Dump out model details at the end --- cmd/view/view.go | 5 +++++ internal/azure_models/client.go | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/view/view.go b/cmd/view/view.go index ff3d3056..a660977a 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -72,6 +72,11 @@ func NewViewCommand() *cobra.Command { return err } + err = client.GetModelDetails(model.RegistryName, model.Name, model.Version) + if err != nil { + return err + } + return nil }, } diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 66d51150..0684f931 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -103,7 +103,11 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri return c.handleHTTPError(resp) } - fmt.Println(resp.Body) + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + fmt.Println(string(bodyBytes)) return nil } From 4f833dcf165bc67b332132d58f53057c2f3562ac Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 16:09:26 -0500 Subject: [PATCH 15/32] Add modelCatalogDetailsResponse type --- internal/azure_models/client.go | 9 +++++++-- internal/azure_models/types.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 0684f931..a90a49d0 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -103,11 +103,16 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri return c.handleHTTPError(resp) } - bodyBytes, err := io.ReadAll(resp.Body) + decoder := json.NewDecoder(resp.Body) + decoder.UseNumber() + + var detailsResponse modelCatalogDetailsResponse + err = decoder.Decode(&detailsResponse) if err != nil { return err } - fmt.Println(string(bodyBytes)) + + fmt.Println(detailsResponse.AssetID) return nil } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 29e3c725..bc39d638 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -80,6 +80,36 @@ type ModelSummary struct { RegistryName string `json:"registry_name"` } +type modelCatalogDetailsResponse struct { + AssetID string `json:"assetId"` + Name string `json:"name"` + DisplayName string `json:"displayName"` + Publisher string `json:"publisher"` + Version string `json:"version"` + RegistryName string `json:"registryName"` + Evaluation string `json:"evaluation"` + Summary string `json:"summary"` + Description string `json:"description"` + License string `json:"license"` + LicenseDescription string `json:"licenseDescription"` + Notes string `json:"notes"` + Keywords []string `json:"keywords"` + InferenceTasks []string `json:"inferenceTasks"` + FineTuningTasks []string `json:"fineTuningTasks"` + Labels []string `json:"labels"` + TradeRestricted bool `json:"tradeRestricted"` + CreatedTime string `json:"createdTime"` + ModelLimits struct { + SupportedLanguages []string `json:"supportedLanguages"` + TextLimits struct { + MaxOutputTokens int `json:"maxOutputTokens"` + InputContextWindow int `json:"inputContextWindow"` + } `json:"textLimits"` + SupportedInputModalities []string `json:"supportedInputModalities"` + SupportedOutputModalities []string `json:"supportedOutputModalities"` + } `json:"modelLimits"` +} + func Ptr[T any](value T) *T { return &value } From 0a56b203f8b49b8dd87b9f9fc794eb3a434b9963 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 16:26:33 -0500 Subject: [PATCH 16/32] Display model description from details --- cmd/view/model_printer.go | 33 ++++++++++++++++++++++++--------- cmd/view/view.go | 10 +++++----- internal/azure_models/client.go | 16 ++++++++-------- internal/azure_models/types.go | 4 ++++ 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 205eadc0..03c15e82 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -8,21 +8,32 @@ import ( ) type modelPrinter struct { - model *azure_models.ModelSummary - printer tableprinter.TablePrinter + modelSummary *azure_models.ModelSummary + modelDetails *azure_models.ModelDetails + printer tableprinter.TablePrinter } -func newModelPrinter(model *azure_models.ModelSummary, terminal term.Term) modelPrinter { +func newModelPrinter(summary *azure_models.ModelSummary, details *azure_models.ModelDetails, terminal term.Term) modelPrinter { width, _, _ := terminal.Size() printer := tableprinter.New(terminal.Out(), terminal.IsTerminalOutput(), width) - return modelPrinter{model: model, printer: printer} + return modelPrinter{modelSummary: summary, modelDetails: details, printer: printer} } func (p *modelPrinter) render() error { - p.addLabeledValue("Display name:", p.model.FriendlyName) - p.addLabeledValue("Model name:", p.model.Name) - p.addLabeledValue("Publisher:", p.model.Publisher) - p.addLabeledValue("Summary:", p.model.Summary) + modelSummary := p.modelSummary + if modelSummary != nil { + p.addLabeledValue("Display name:", modelSummary.FriendlyName) + p.addLabeledValue("Summary name:", modelSummary.Name) + p.addLabeledValue("Publisher:", modelSummary.Publisher) + p.addLabeledValue("Summary:", modelSummary.Summary) + } + + modelDetails := p.modelDetails + if modelDetails != nil { + p.addLabel("Description:") + p.printer.AddField(modelDetails.Description, tableprinter.WithTruncate(nil)) + p.printer.EndRow() + } err := p.printer.Render() if err != nil { @@ -32,8 +43,12 @@ func (p *modelPrinter) render() error { return nil } +func (p *modelPrinter) addLabel(label string) { + p.printer.AddField(label, tableprinter.WithTruncate(nil), tableprinter.WithColor(util.LightGrayUnderline)) +} + func (p *modelPrinter) addLabeledValue(label string, value string) { - p.printer.AddField(label, tableprinter.WithColor(util.LightGrayUnderline)) + p.addLabel(label) p.printer.AddField(value) p.printer.EndRow() } diff --git a/cmd/view/view.go b/cmd/view/view.go index a660977a..8db5cb2f 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -60,19 +60,19 @@ func NewViewCommand() *cobra.Command { modelName = args[0] } - model, err := util.GetModelByName(modelName, models) + modelSummary, err := util.GetModelByName(modelName, models) if err != nil { return err } - modelPrinter := newModelPrinter(model, terminal) - - err = modelPrinter.render() + modelDetails, err := client.GetModelDetails(modelSummary.RegistryName, modelSummary.Name, modelSummary.Version) if err != nil { return err } - err = client.GetModelDetails(model.RegistryName, model.Name, model.Version) + modelPrinter := newModelPrinter(modelSummary, modelDetails, terminal) + + err = modelPrinter.render() if err != nil { return err } diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index a90a49d0..464f299f 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -85,22 +85,22 @@ func (c *Client) GetChatCompletionStream(req ChatCompletionOptions) (*ChatComple return &chatCompletionResponse, nil } -func (c *Client) GetModelDetails(registry string, modelName string, version string) error { +func (c *Client) GetModelDetails(registry string, modelName string, version string) (*ModelDetails, error) { url := fmt.Sprintf("%s/asset-gallery/v1.0/%s/models/%s/version/%s", azureAiStudioURL, registry, modelName, version) httpReq, err := http.NewRequest("GET", url, nil) if err != nil { - return err + return nil, err } httpReq.Header.Set("Content-Type", "application/json") resp, err := c.client.Do(httpReq) if err != nil { - return err + return nil, err } if resp.StatusCode != http.StatusOK { - return c.handleHTTPError(resp) + return nil, c.handleHTTPError(resp) } decoder := json.NewDecoder(resp.Body) @@ -109,12 +109,12 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri var detailsResponse modelCatalogDetailsResponse err = decoder.Decode(&detailsResponse) if err != nil { - return err + return nil, err } - fmt.Println(detailsResponse.AssetID) - - return nil + return &ModelDetails{ + Description: detailsResponse.Description, + }, nil } func (c *Client) ListModels() ([]*ModelSummary, error) { diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index bc39d638..9f1f0e46 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -110,6 +110,10 @@ type modelCatalogDetailsResponse struct { } `json:"modelLimits"` } +type ModelDetails struct { + Description string `json:"description"` +} + func Ptr[T any](value T) *T { return &value } From bb9e140ec7e72ecba78fd33ac6242e02b597a8e3 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Tue, 8 Oct 2024 16:43:47 -0500 Subject: [PATCH 17/32] Output license details with 'view' command --- cmd/view/model_printer.go | 28 +++++++++++++++++----------- internal/azure_models/client.go | 4 +++- internal/azure_models/types.go | 4 +++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 03c15e82..452661d9 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -22,17 +22,17 @@ func newModelPrinter(summary *azure_models.ModelSummary, details *azure_models.M func (p *modelPrinter) render() error { modelSummary := p.modelSummary if modelSummary != nil { - p.addLabeledValue("Display name:", modelSummary.FriendlyName) - p.addLabeledValue("Summary name:", modelSummary.Name) - p.addLabeledValue("Publisher:", modelSummary.Publisher) - p.addLabeledValue("Summary:", modelSummary.Summary) + p.printLabelledLine("Display name:", modelSummary.FriendlyName) + p.printLabelledLine("Summary name:", modelSummary.Name) + p.printLabelledLine("Publisher:", modelSummary.Publisher) + p.printLabelledLine("Summary:", modelSummary.Summary) } modelDetails := p.modelDetails if modelDetails != nil { - p.addLabel("Description:") - p.printer.AddField(modelDetails.Description, tableprinter.WithTruncate(nil)) - p.printer.EndRow() + p.printLabelledLine("License:", modelDetails.License) + p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) + p.printMultipleLinesWithLabel("Description:", modelDetails.Description) } err := p.printer.Render() @@ -43,12 +43,18 @@ func (p *modelPrinter) render() error { return nil } -func (p *modelPrinter) addLabel(label string) { - p.printer.AddField(label, tableprinter.WithTruncate(nil), tableprinter.WithColor(util.LightGrayUnderline)) +func (p *modelPrinter) printLabelledLine(label string, value string) { + p.addLabel(label) + p.printer.AddField(value) + p.printer.EndRow() } -func (p *modelPrinter) addLabeledValue(label string, value string) { +func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { p.addLabel(label) - p.printer.AddField(value) + p.printer.AddField(value, tableprinter.WithTruncate(nil)) p.printer.EndRow() } + +func (p *modelPrinter) addLabel(label string) { + p.printer.AddField(label, tableprinter.WithTruncate(nil), tableprinter.WithColor(util.LightGrayUnderline)) +} diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 464f299f..795aadb4 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -113,7 +113,9 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri } return &ModelDetails{ - Description: detailsResponse.Description, + Description: detailsResponse.Description, + License: detailsResponse.License, + LicenseDescription: detailsResponse.LicenseDescription, }, nil } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 9f1f0e46..2072c33a 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -111,7 +111,9 @@ type modelCatalogDetailsResponse struct { } type ModelDetails struct { - Description string `json:"description"` + Description string `json:"description"` + License string `json:"license"` + LicenseDescription string `json:"license_description"` } func Ptr[T any](value T) *T { From 584ac6e1a9b0f3ee892bfe4843dce00001da9066 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:26:40 -0500 Subject: [PATCH 18/32] Drop centralized colors Only used in two places, and I'm not convinced I like the light gray + underline for the 'view' command. --- cmd/list/list.go | 8 ++++++-- cmd/view/model_printer.go | 8 ++++++-- pkg/util/colors.go | 7 ------- 3 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 pkg/util/colors.go diff --git a/cmd/list/list.go b/cmd/list/list.go index f87f2865..8ea9e115 100644 --- a/cmd/list/list.go +++ b/cmd/list/list.go @@ -9,10 +9,14 @@ import ( "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" "github.com/github/gh-models/internal/ux" - "github.com/github/gh-models/pkg/util" + "github.com/mgutz/ansi" "github.com/spf13/cobra" ) +var ( + lightGrayUnderline = ansi.ColorFunc("white+du") +) + func NewListCommand() *cobra.Command { cmd := &cobra.Command{ Use: "list", @@ -51,7 +55,7 @@ func NewListCommand() *cobra.Command { width, _, _ := terminal.Size() printer := tableprinter.New(out, isTTY, width) - printer.AddHeader([]string{"DISPLAY NAME", "MODEL NAME"}, tableprinter.WithColor(util.LightGrayUnderline)) + printer.AddHeader([]string{"DISPLAY NAME", "MODEL NAME"}, tableprinter.WithColor(lightGrayUnderline)) printer.EndRow() for _, model := range models { diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 452661d9..acf43728 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -4,7 +4,11 @@ import ( "github.com/cli/go-gh/v2/pkg/tableprinter" "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" - "github.com/github/gh-models/pkg/util" + "github.com/mgutz/ansi" +) + +var ( + lightGrayUnderline = ansi.ColorFunc("white+du") ) type modelPrinter struct { @@ -56,5 +60,5 @@ func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { } func (p *modelPrinter) addLabel(label string) { - p.printer.AddField(label, tableprinter.WithTruncate(nil), tableprinter.WithColor(util.LightGrayUnderline)) + p.printer.AddField(label, tableprinter.WithTruncate(nil), tableprinter.WithColor(lightGrayUnderline)) } diff --git a/pkg/util/colors.go b/pkg/util/colors.go deleted file mode 100644 index 0a541c2f..00000000 --- a/pkg/util/colors.go +++ /dev/null @@ -1,7 +0,0 @@ -package util - -import "github.com/mgutz/ansi" - -var ( - LightGrayUnderline = ansi.ColorFunc("white+du") -) From fdd8d0334342889150ce8a574cb8dff882aa625e Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:27:28 -0500 Subject: [PATCH 19/32] Move getModelByName into view package Only used there now, after fixing merge conflicts. --- cmd/view/view.go | 15 +++++++++++++-- pkg/util/models.go | 17 ----------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/cmd/view/view.go b/cmd/view/view.go index 8db5cb2f..e1657815 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -1,14 +1,15 @@ package view import ( + "fmt" "io" + "strings" "github.com/AlecAivazis/survey/v2" "github.com/cli/go-gh/v2/pkg/auth" "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" "github.com/github/gh-models/internal/ux" - "github.com/github/gh-models/pkg/util" "github.com/spf13/cobra" ) @@ -60,7 +61,7 @@ func NewViewCommand() *cobra.Command { modelName = args[0] } - modelSummary, err := util.GetModelByName(modelName, models) + modelSummary, err := getModelByName(modelName, models) if err != nil { return err } @@ -82,3 +83,13 @@ func NewViewCommand() *cobra.Command { } return cmd } + +// getModelByName returns the model with the specified name, or an error if no such model exists within the given list. +func getModelByName(modelName string, models []*azure_models.ModelSummary) (*azure_models.ModelSummary, error) { + for _, model := range models { + if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { + return model, nil + } + } + return nil, fmt.Errorf("the specified model name is not supported: %s", modelName) +} diff --git a/pkg/util/models.go b/pkg/util/models.go index a7af7c49..c7d86821 100644 --- a/pkg/util/models.go +++ b/pkg/util/models.go @@ -1,18 +1 @@ package util - -import ( - "fmt" - "strings" - - "github.com/github/gh-models/internal/azure_models" -) - -// GetModelByName returns the model with the specified name, or an error if no such model exists within the given list. -func GetModelByName(modelName string, models []*azure_models.ModelSummary) (*azure_models.ModelSummary, error) { - for _, model := range models { - if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { - return model, nil - } - } - return nil, fmt.Errorf("the specified model name is not supported: %s", modelName) -} From c924fe45d6bce28a3c637cb77634faa6efe30004 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:29:52 -0500 Subject: [PATCH 20/32] Add HasName to ModelSummary --- cmd/run/run.go | 2 +- cmd/view/view.go | 3 +-- internal/azure_models/types.go | 5 +++++ pkg/util/models.go | 1 - 4 files changed, 7 insertions(+), 4 deletions(-) delete mode 100644 pkg/util/models.go diff --git a/cmd/run/run.go b/cmd/run/run.go index 54dd4715..064b9148 100644 --- a/cmd/run/run.go +++ b/cmd/run/run.go @@ -234,7 +234,7 @@ func NewRunCommand() *cobra.Command { foundMatch := false for _, model := range models { - if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { + if model.HasName(modelName) { modelName = model.Name foundMatch = true break diff --git a/cmd/view/view.go b/cmd/view/view.go index e1657815..f36a051d 100644 --- a/cmd/view/view.go +++ b/cmd/view/view.go @@ -3,7 +3,6 @@ package view import ( "fmt" "io" - "strings" "github.com/AlecAivazis/survey/v2" "github.com/cli/go-gh/v2/pkg/auth" @@ -87,7 +86,7 @@ func NewViewCommand() *cobra.Command { // getModelByName returns the model with the specified name, or an error if no such model exists within the given list. func getModelByName(modelName string, models []*azure_models.ModelSummary) (*azure_models.ModelSummary, error) { for _, model := range models { - if strings.EqualFold(model.FriendlyName, modelName) || strings.EqualFold(model.Name, modelName) { + if model.HasName(modelName) { return model, nil } } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 2072c33a..f0d2d811 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -2,6 +2,7 @@ package azure_models import ( "encoding/json" + "strings" "github.com/github/gh-models/internal/sse" ) @@ -80,6 +81,10 @@ type ModelSummary struct { RegistryName string `json:"registry_name"` } +func (m *ModelSummary) HasName(name string) bool { + return strings.EqualFold(m.FriendlyName, name) || strings.EqualFold(m.Name, name) +} + type modelCatalogDetailsResponse struct { AssetID string `json:"assetId"` Name string `json:"name"` diff --git a/pkg/util/models.go b/pkg/util/models.go deleted file mode 100644 index c7d86821..00000000 --- a/pkg/util/models.go +++ /dev/null @@ -1 +0,0 @@ -package util From 287062af52727be01fdea80c4b8759618fc6da85 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:33:14 -0500 Subject: [PATCH 21/32] Display model notes, add blank line between multi-line fields --- cmd/view/model_printer.go | 7 +++++++ internal/azure_models/client.go | 1 + internal/azure_models/types.go | 1 + 3 files changed, 9 insertions(+) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index acf43728..c1a77617 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -37,6 +37,7 @@ func (p *modelPrinter) render() error { p.printLabelledLine("License:", modelDetails.License) p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) + p.printMultipleLinesWithLabel("Notes:", modelDetails.Notes) } err := p.printer.Render() @@ -57,6 +58,12 @@ func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { p.addLabel(label) p.printer.AddField(value, tableprinter.WithTruncate(nil)) p.printer.EndRow() + p.printBlankLine() +} + +func (p *modelPrinter) printBlankLine() { + p.printer.AddField("") + p.printer.EndRow() } func (p *modelPrinter) addLabel(label string) { diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 795aadb4..579bfa11 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -116,6 +116,7 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri Description: detailsResponse.Description, License: detailsResponse.License, LicenseDescription: detailsResponse.LicenseDescription, + Notes: detailsResponse.Notes, }, nil } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index f0d2d811..50471d34 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -119,6 +119,7 @@ type ModelDetails struct { Description string `json:"description"` License string `json:"license"` LicenseDescription string `json:"license_description"` + Notes string `json:"notes"` } func Ptr[T any](value T) *T { From 260684827be39d7908605867b443487fd82528f2 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:40:39 -0500 Subject: [PATCH 22/32] Include tags in view output Labelling keywords as tags and lowercasing them like we do to present on the Models Marketplace. --- cmd/view/model_printer.go | 3 +++ internal/azure_models/client.go | 9 +++++++++ internal/azure_models/types.go | 9 +++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index c1a77617..a0cf7c38 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -1,6 +1,8 @@ package view import ( + "strings" + "github.com/cli/go-gh/v2/pkg/tableprinter" "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" @@ -34,6 +36,7 @@ func (p *modelPrinter) render() error { modelDetails := p.modelDetails if modelDetails != nil { + p.printLabelledLine("Tags:", strings.Join(modelDetails.Tags, ", ")) p.printLabelledLine("License:", modelDetails.License) p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 579bfa11..a553bf6d 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -117,9 +117,18 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri License: detailsResponse.License, LicenseDescription: detailsResponse.LicenseDescription, Notes: detailsResponse.Notes, + Tags: lowercaseStrings(detailsResponse.Keywords), }, nil } +func lowercaseStrings(input []string) []string { + output := make([]string, len(input)) + for i, s := range input { + output[i] = strings.ToLower(s) + } + return output +} + func (c *Client) ListModels() ([]*ModelSummary, error) { body := bytes.NewReader([]byte(` { diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 50471d34..54fb6797 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -116,10 +116,11 @@ type modelCatalogDetailsResponse struct { } type ModelDetails struct { - Description string `json:"description"` - License string `json:"license"` - LicenseDescription string `json:"license_description"` - Notes string `json:"notes"` + Description string `json:"description"` + License string `json:"license"` + LicenseDescription string `json:"license_description"` + Notes string `json:"notes"` + Tags []string `json:"tags"` } func Ptr[T any](value T) *T { From 4ecefd92bda9b22f7480136acf141593cde6e008 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 11:55:58 -0500 Subject: [PATCH 23/32] Don't output labels for blank values --- cmd/view/model_printer.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index a0cf7c38..52804042 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -52,12 +52,18 @@ func (p *modelPrinter) render() error { } func (p *modelPrinter) printLabelledLine(label string, value string) { + if value == "" { + return + } p.addLabel(label) p.printer.AddField(value) p.printer.EndRow() } func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { + if value == "" { + return + } p.addLabel(label) p.printer.AddField(value, tableprinter.WithTruncate(nil)) p.printer.EndRow() From c1da574fccb1f5ef3e0a8095b81f40d581675f32 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:04:37 -0500 Subject: [PATCH 24/32] Display supported inputs and outputs --- cmd/view/model_printer.go | 2 ++ internal/azure_models/client.go | 12 ++++++++++-- internal/azure_models/types.go | 14 ++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 52804042..5aa0a542 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -37,6 +37,8 @@ func (p *modelPrinter) render() error { modelDetails := p.modelDetails if modelDetails != nil { p.printLabelledLine("Tags:", strings.Join(modelDetails.Tags, ", ")) + p.printLabelledLine("Supported input types:", strings.Join(modelDetails.SupportedInputModalities, ", ")) + p.printLabelledLine("Supported output types:", strings.Join(modelDetails.SupportedOutputModalities, ", ")) p.printLabelledLine("License:", modelDetails.License) p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index a553bf6d..2f3d8ca8 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -112,13 +112,21 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri return nil, err } - return &ModelDetails{ + modelDetails := &ModelDetails{ Description: detailsResponse.Description, License: detailsResponse.License, LicenseDescription: detailsResponse.LicenseDescription, Notes: detailsResponse.Notes, Tags: lowercaseStrings(detailsResponse.Keywords), - }, nil + } + + modelLimits := detailsResponse.ModelLimits + if modelLimits != nil { + modelDetails.SupportedInputModalities = modelLimits.SupportedInputModalities + modelDetails.SupportedOutputModalities = modelLimits.SupportedOutputModalities + } + + return modelDetails, nil } func lowercaseStrings(input []string) []string { diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 54fb6797..46a9ec82 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -104,7 +104,7 @@ type modelCatalogDetailsResponse struct { Labels []string `json:"labels"` TradeRestricted bool `json:"tradeRestricted"` CreatedTime string `json:"createdTime"` - ModelLimits struct { + ModelLimits *struct { SupportedLanguages []string `json:"supportedLanguages"` TextLimits struct { MaxOutputTokens int `json:"maxOutputTokens"` @@ -116,11 +116,13 @@ type modelCatalogDetailsResponse struct { } type ModelDetails struct { - Description string `json:"description"` - License string `json:"license"` - LicenseDescription string `json:"license_description"` - Notes string `json:"notes"` - Tags []string `json:"tags"` + Description string `json:"description"` + License string `json:"license"` + LicenseDescription string `json:"license_description"` + Notes string `json:"notes"` + Tags []string `json:"tags"` + SupportedInputModalities []string `json:"supportedInputModalities"` + SupportedOutputModalities []string `json:"supportedOutputModalities"` } func Ptr[T any](value T) *T { From 73fd7874f0113c35773ce137431a710c695f79c8 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:05:27 -0500 Subject: [PATCH 25/32] Display 'evaluation' field --- cmd/view/model_printer.go | 1 + internal/azure_models/client.go | 1 + internal/azure_models/types.go | 1 + 3 files changed, 3 insertions(+) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 5aa0a542..e2ee2bd3 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -43,6 +43,7 @@ func (p *modelPrinter) render() error { p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) p.printMultipleLinesWithLabel("Notes:", modelDetails.Notes) + p.printMultipleLinesWithLabel("Evaluation:", modelDetails.Evaluation) } err := p.printer.Render() diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 2f3d8ca8..a47944b3 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -118,6 +118,7 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri LicenseDescription: detailsResponse.LicenseDescription, Notes: detailsResponse.Notes, Tags: lowercaseStrings(detailsResponse.Keywords), + Evaluation: detailsResponse.Evaluation, } modelLimits := detailsResponse.ModelLimits diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 46a9ec82..2056910b 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -117,6 +117,7 @@ type modelCatalogDetailsResponse struct { type ModelDetails struct { Description string `json:"description"` + Evaluation string `json:"evaluation"` License string `json:"license"` LicenseDescription string `json:"license_description"` Notes string `json:"notes"` From 360009736f1ba3b66336f55a7d3ce5531347e456 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:23:49 -0500 Subject: [PATCH 26/32] Use snake case for JSON fields like our other external-facing types --- internal/azure_models/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 2056910b..b05a44fd 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -122,8 +122,8 @@ type ModelDetails struct { LicenseDescription string `json:"license_description"` Notes string `json:"notes"` Tags []string `json:"tags"` - SupportedInputModalities []string `json:"supportedInputModalities"` - SupportedOutputModalities []string `json:"supportedOutputModalities"` + SupportedInputModalities []string `json:"supported_input_modalities"` + SupportedOutputModalities []string `json:"supported_output_modalities"` } func Ptr[T any](value T) *T { From b761cee912797482ab764d81ce32fa1511945cff Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:28:35 -0500 Subject: [PATCH 27/32] Display supported languages --- cmd/view/model_printer.go | 9 +++++++-- internal/azure_models/client.go | 13 +++++++++++++ internal/azure_models/types.go | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index e2ee2bd3..880eff83 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -37,8 +37,9 @@ func (p *modelPrinter) render() error { modelDetails := p.modelDetails if modelDetails != nil { p.printLabelledLine("Tags:", strings.Join(modelDetails.Tags, ", ")) - p.printLabelledLine("Supported input types:", strings.Join(modelDetails.SupportedInputModalities, ", ")) - p.printLabelledLine("Supported output types:", strings.Join(modelDetails.SupportedOutputModalities, ", ")) + p.printLabelledList("Supported input types:", modelDetails.SupportedInputModalities) + p.printLabelledList("Supported output types:", modelDetails.SupportedOutputModalities) + p.printLabelledList("Supported languages:", modelDetails.SupportedLanguages) p.printLabelledLine("License:", modelDetails.License) p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) @@ -63,6 +64,10 @@ func (p *modelPrinter) printLabelledLine(label string, value string) { p.printer.EndRow() } +func (p *modelPrinter) printLabelledList(label string, values []string) { + p.printLabelledLine(label, strings.Join(values, ", ")) +} + func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { if value == "" { return diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index a47944b3..d72d1533 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -11,6 +11,8 @@ import ( "github.com/cli/go-gh/v2/pkg/api" "github.com/github/gh-models/internal/sse" + "golang.org/x/text/language" + "golang.org/x/text/language/display" ) type Client struct { @@ -125,11 +127,22 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri if modelLimits != nil { modelDetails.SupportedInputModalities = modelLimits.SupportedInputModalities modelDetails.SupportedOutputModalities = modelLimits.SupportedOutputModalities + modelDetails.SupportedLanguages = convertLanguageCodesToNames(modelLimits.SupportedLanguages) } return modelDetails, nil } +func convertLanguageCodesToNames(input []string) []string { + output := make([]string, len(input)) + english := display.English.Languages() + for i, code := range input { + tag := language.MustParse(code) + output[i] = english.Name(tag) + } + return output +} + func lowercaseStrings(input []string) []string { output := make([]string, len(input)) for i, s := range input { diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index b05a44fd..c22c1af1 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -124,6 +124,7 @@ type ModelDetails struct { Tags []string `json:"tags"` SupportedInputModalities []string `json:"supported_input_modalities"` SupportedOutputModalities []string `json:"supported_output_modalities"` + SupportedLanguages []string `json:"supported_languages"` } func Ptr[T any](value T) *T { From adfefec681553b41615e82a085ef975276dea42b Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:33:38 -0500 Subject: [PATCH 28/32] Display context max tokens --- cmd/view/model_printer.go | 3 ++- internal/azure_models/client.go | 6 ++++++ internal/azure_models/types.go | 9 ++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 880eff83..528d3f92 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -36,7 +36,8 @@ func (p *modelPrinter) render() error { modelDetails := p.modelDetails if modelDetails != nil { - p.printLabelledLine("Tags:", strings.Join(modelDetails.Tags, ", ")) + p.printLabelledLine("Context:", modelDetails.ContextLimits()) + p.printLabelledList("Tags:", modelDetails.Tags) p.printLabelledList("Supported input types:", modelDetails.SupportedInputModalities) p.printLabelledList("Supported output types:", modelDetails.SupportedOutputModalities) p.printLabelledList("Supported languages:", modelDetails.SupportedLanguages) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index d72d1533..63551f4d 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -128,6 +128,12 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri modelDetails.SupportedInputModalities = modelLimits.SupportedInputModalities modelDetails.SupportedOutputModalities = modelLimits.SupportedOutputModalities modelDetails.SupportedLanguages = convertLanguageCodesToNames(modelLimits.SupportedLanguages) + + textLimits := modelLimits.TextLimits + if textLimits != nil { + modelDetails.MaxOutputTokens = textLimits.MaxOutputTokens + modelDetails.MaxInputTokens = textLimits.InputContextWindow + } } return modelDetails, nil diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index c22c1af1..0f2fde74 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -2,6 +2,7 @@ package azure_models import ( "encoding/json" + "fmt" "strings" "github.com/github/gh-models/internal/sse" @@ -106,7 +107,7 @@ type modelCatalogDetailsResponse struct { CreatedTime string `json:"createdTime"` ModelLimits *struct { SupportedLanguages []string `json:"supportedLanguages"` - TextLimits struct { + TextLimits *struct { MaxOutputTokens int `json:"maxOutputTokens"` InputContextWindow int `json:"inputContextWindow"` } `json:"textLimits"` @@ -125,6 +126,12 @@ type ModelDetails struct { SupportedInputModalities []string `json:"supported_input_modalities"` SupportedOutputModalities []string `json:"supported_output_modalities"` SupportedLanguages []string `json:"supported_languages"` + MaxOutputTokens int `json:"max_output_tokens"` + MaxInputTokens int `json:"max_input_tokens"` +} + +func (m *ModelDetails) ContextLimits() string { + return fmt.Sprintf("up to %d input tokens and %d output tokens", m.MaxInputTokens, m.MaxOutputTokens) } func Ptr[T any](value T) *T { From d2ccb2036f492c823bcdda29282c0121e712acf7 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 12:35:28 -0500 Subject: [PATCH 29/32] Display rate limit tier --- cmd/view/model_printer.go | 1 + internal/azure_models/client.go | 5 +++++ internal/azure_models/types.go | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 528d3f92..4c166fec 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -37,6 +37,7 @@ func (p *modelPrinter) render() error { modelDetails := p.modelDetails if modelDetails != nil { p.printLabelledLine("Context:", modelDetails.ContextLimits()) + p.printLabelledLine("Rate limit tier:", modelDetails.RateLimitTier) p.printLabelledList("Tags:", modelDetails.Tags) p.printLabelledList("Supported input types:", modelDetails.SupportedInputModalities) p.printLabelledList("Supported output types:", modelDetails.SupportedOutputModalities) diff --git a/internal/azure_models/client.go b/internal/azure_models/client.go index 63551f4d..996c270a 100644 --- a/internal/azure_models/client.go +++ b/internal/azure_models/client.go @@ -136,6 +136,11 @@ func (c *Client) GetModelDetails(registry string, modelName string, version stri } } + playgroundLimits := detailsResponse.PlaygroundLimits + if playgroundLimits != nil { + modelDetails.RateLimitTier = playgroundLimits.RateLimitTier + } + return modelDetails, nil } diff --git a/internal/azure_models/types.go b/internal/azure_models/types.go index 0f2fde74..de76846b 100644 --- a/internal/azure_models/types.go +++ b/internal/azure_models/types.go @@ -105,7 +105,10 @@ type modelCatalogDetailsResponse struct { Labels []string `json:"labels"` TradeRestricted bool `json:"tradeRestricted"` CreatedTime string `json:"createdTime"` - ModelLimits *struct { + PlaygroundLimits *struct { + RateLimitTier string `json:"rateLimitTier"` + } `json:"playgroundLimits"` + ModelLimits *struct { SupportedLanguages []string `json:"supportedLanguages"` TextLimits *struct { MaxOutputTokens int `json:"maxOutputTokens"` @@ -128,6 +131,7 @@ type ModelDetails struct { SupportedLanguages []string `json:"supported_languages"` MaxOutputTokens int `json:"max_output_tokens"` MaxInputTokens int `json:"max_input_tokens"` + RateLimitTier string `json:"rateLimitTier"` } func (m *ModelDetails) ContextLimits() string { From 0e6197009eeabe7cfc4db3dfc2ba52959609c98c Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 15:26:31 -0500 Subject: [PATCH 30/32] Do some Markdown processing on multi-line fields Better display of tables and links. --- cmd/view/model_printer.go | 17 ++++++--- go.mod | 33 +++++++++++----- go.sum | 79 ++++++++++++++++++++++++++++----------- 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 4c166fec..0180cd17 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -3,6 +3,7 @@ package view import ( "strings" + "github.com/cli/cli/v2/pkg/markdown" "github.com/cli/go-gh/v2/pkg/tableprinter" "github.com/cli/go-gh/v2/pkg/term" "github.com/github/gh-models/internal/azure_models" @@ -14,15 +15,16 @@ var ( ) type modelPrinter struct { - modelSummary *azure_models.ModelSummary - modelDetails *azure_models.ModelDetails - printer tableprinter.TablePrinter + modelSummary *azure_models.ModelSummary + modelDetails *azure_models.ModelDetails + printer tableprinter.TablePrinter + terminalWidth int } func newModelPrinter(summary *azure_models.ModelSummary, details *azure_models.ModelDetails, terminal term.Term) modelPrinter { width, _, _ := terminal.Size() printer := tableprinter.New(terminal.Out(), terminal.IsTerminalOutput(), width) - return modelPrinter{modelSummary: summary, modelDetails: details, printer: printer} + return modelPrinter{modelSummary: summary, modelDetails: details, printer: printer, terminalWidth: width} } func (p *modelPrinter) render() error { @@ -75,7 +77,12 @@ func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { return } p.addLabel(label) - p.printer.AddField(value, tableprinter.WithTruncate(nil)) + renderedValue, err := markdown.Render(value, markdown.WithWrap(p.terminalWidth)) + displayValue := value + if err == nil { + displayValue = renderedValue + } + p.printer.AddField(displayValue, tableprinter.WithTruncate(nil)) p.printer.EndRow() p.printBlankLine() } diff --git a/go.mod b/go.mod index 3078407d..27a21d5a 100644 --- a/go.mod +++ b/go.mod @@ -1,23 +1,33 @@ module github.com/github/gh-models -go 1.22 +go 1.22.5 + +toolchain go1.22.8 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/briandowns/spinner v1.23.1 - github.com/cli/go-gh/v2 v2.9.0 - github.com/spf13/cobra v1.8.0 + github.com/cli/cli/v2 v2.58.0 + github.com/cli/go-gh/v2 v2.10.0 + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 + golang.org/x/text v0.18.0 ) require ( + github.com/alecthomas/chroma/v2 v2.8.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/charmbracelet/glamour v0.7.0 // indirect github.com/charmbracelet/lipgloss v0.10.1-0.20240413172830-d0be07ea6b9c // indirect github.com/charmbracelet/x/exp/term v0.0.0-20240425164147-ba2a9512b05f // indirect - github.com/cli/safeexec v1.0.0 // indirect + github.com/cli/safeexec v1.0.1 // indirect github.com/cli/shurcooL-graphql v0.0.4 // indirect - github.com/fatih/color v1.7.0 // indirect - github.com/henvic/httpretty v0.0.6 // indirect + github.com/dlclark/regexp2 v1.4.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/henvic/httpretty v0.1.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/text v0.2.0 // indirect @@ -25,13 +35,16 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.2 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + github.com/yuin/goldmark v1.5.4 // indirect + github.com/yuin/goldmark-emoji v1.0.2 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 040efe9e..ca0b25dd 100644 --- a/go.sum +++ b/go.sum @@ -4,33 +4,53 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= +github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/alecthomas/chroma/v2 v2.8.0 h1:w9WJUjFFmHHB2e8mRpL9jjy3alYDlU0QLDezj1xE264= +github.com/alecthomas/chroma/v2 v2.8.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw= +github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650= github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= +github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= +github.com/charmbracelet/glamour v0.7.0/go.mod h1:jUMh5MeihljJPQbJ/wf4ldw2+yBP59+ctV36jASy7ps= github.com/charmbracelet/lipgloss v0.10.1-0.20240413172830-d0be07ea6b9c h1:0FwZb0wTiyalb8QQlILWyIuh3nF5wok6j9D9oUQwfQY= github.com/charmbracelet/lipgloss v0.10.1-0.20240413172830-d0be07ea6b9c/go.mod h1:EPP2QJ0ectp3zo6gx9f8oJGq8keirqPJ3XpYEI8wrrs= github.com/charmbracelet/x/exp/term v0.0.0-20240425164147-ba2a9512b05f h1:1BXkZqDueTOBECyDoFGRi0xMYgjJ6vvoPIkWyKOwzTc= github.com/charmbracelet/x/exp/term v0.0.0-20240425164147-ba2a9512b05f/go.mod h1:yQqGHmheaQfkqiJWjklPHVAq1dKbk8uGbcoS/lcKCJ0= -github.com/cli/go-gh/v2 v2.9.0 h1:D3lTjEneMYl54M+WjZ+kRPrR5CEJ5BHS05isBPOV3LI= -github.com/cli/go-gh/v2 v2.9.0/go.mod h1:MeRoKzXff3ygHu7zP+NVTT+imcHW6p3tpuxHAzRM2xE= -github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI= -github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= +github.com/cli/cli/v2 v2.58.0 h1:sH4UIxaiFU794cV+XtVU8Etqk9Aw823v8+8JsEOd1EI= +github.com/cli/cli/v2 v2.58.0/go.mod h1:vTLS6aiHoA74ijRJ8TV7waYlAFhVWfxByilQymxpzJ4= +github.com/cli/go-gh/v2 v2.10.0 h1:GMflBKoErBXlLvN2euxzL+p7JaM8erlSmw0cT7uZr7M= +github.com/cli/go-gh/v2 v2.10.0/go.mod h1:MeRoKzXff3ygHu7zP+NVTT+imcHW6p3tpuxHAzRM2xE= +github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00= +github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= github.com/cli/shurcooL-graphql v0.0.4 h1:6MogPnQJLjKkaXPyGqPRXOI2qCsQdqNfUY1QSJu2GuY= github.com/cli/shurcooL-graphql v0.0.4/go.mod h1:3waN4u02FiZivIV+p1y4d0Jo1jc6BViMA73C+sZo2fk= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= +github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs= -github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo= +github.com/henvic/httpretty v0.1.4 h1:Jo7uwIRWVFxkqOnErcoYfH90o3ddQyVrSANeS4cxYmU= +github.com/henvic/httpretty v0.1.4/go.mod h1:Dn60sQTZfbt2dYsdUSNsCljyF4AfdqnuJFDLJA1I4AM= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -50,40 +70,53 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8= github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e/go.mod h1:/Tnicc6m/lsJE0irFMA0LfIwTBo4QP7A8IfyIv4zZKI= +github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU= +github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= +github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -95,21 +128,23 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= From c62a6cc527f8d82fb97bc761ff990154ab6bda06 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 16:53:54 -0500 Subject: [PATCH 31/32] Don't truncate list of languages --- cmd/view/model_printer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 0180cd17..29c40729 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -43,7 +43,7 @@ func (p *modelPrinter) render() error { p.printLabelledList("Tags:", modelDetails.Tags) p.printLabelledList("Supported input types:", modelDetails.SupportedInputModalities) p.printLabelledList("Supported output types:", modelDetails.SupportedOutputModalities) - p.printLabelledList("Supported languages:", modelDetails.SupportedLanguages) + p.printLabelledMultiLineList("Supported languages:", modelDetails.SupportedLanguages) p.printLabelledLine("License:", modelDetails.License) p.printMultipleLinesWithLabel("License description:", modelDetails.LicenseDescription) p.printMultipleLinesWithLabel("Description:", modelDetails.Description) @@ -72,6 +72,10 @@ func (p *modelPrinter) printLabelledList(label string, values []string) { p.printLabelledLine(label, strings.Join(values, ", ")) } +func (p *modelPrinter) printLabelledMultiLineList(label string, values []string) { + p.printMultipleLinesWithLabel(label, strings.Join(values, ", ")) +} + func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { if value == "" { return From 4c441d9ab7e776bbddad99b893d371ce22982526 Mon Sep 17 00:00:00 2001 From: Sarah Vessels Date: Wed, 9 Oct 2024 16:55:55 -0500 Subject: [PATCH 32/32] Reduce whitespace in output --- cmd/view/model_printer.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cmd/view/model_printer.go b/cmd/view/model_printer.go index 29c40729..d3f20b7f 100644 --- a/cmd/view/model_printer.go +++ b/cmd/view/model_printer.go @@ -64,7 +64,7 @@ func (p *modelPrinter) printLabelledLine(label string, value string) { return } p.addLabel(label) - p.printer.AddField(value) + p.printer.AddField(strings.TrimSpace(value)) p.printer.EndRow() } @@ -81,19 +81,13 @@ func (p *modelPrinter) printMultipleLinesWithLabel(label string, value string) { return } p.addLabel(label) - renderedValue, err := markdown.Render(value, markdown.WithWrap(p.terminalWidth)) + renderedValue, err := markdown.Render(strings.TrimSpace(value), markdown.WithWrap(p.terminalWidth)) displayValue := value if err == nil { displayValue = renderedValue } p.printer.AddField(displayValue, tableprinter.WithTruncate(nil)) p.printer.EndRow() - p.printBlankLine() -} - -func (p *modelPrinter) printBlankLine() { - p.printer.AddField("") - p.printer.EndRow() } func (p *modelPrinter) addLabel(label string) {