-
Notifications
You must be signed in to change notification settings - Fork 309
fix(tui): include OpenCode runtime custom models in picker #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,8 +4,10 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "encoding/json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os/exec" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path/filepath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sort" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // DefaultCachePath returns the default path to the OpenCode models cache file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -117,6 +119,32 @@ var envLookup = os.Getenv | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // authPath is a package-level variable for testing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var authPath = DefaultAuthPath | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // listModelsForProvider returns runtime-visible model IDs for a provider using | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the installed `opencode` binary. The CLI is the source of truth for custom | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // models that may not appear in ~/.cache/opencode/models.json yet. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var listModelsForProvider = func(providerID string) ([]string, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd := exec.Command("opencode", "models", providerID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| output, err := cmd.Output() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var models []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, line := range strings.Split(string(output), "\n") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| line = strings.TrimSpace(line) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if line == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parts := strings.SplitN(line, "/", 2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(parts) != 2 || parts[0] != providerID || parts[1] == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| models = append(models, parts[1]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return models, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+122
to
+147
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // listModelsForProvider returns runtime-visible model IDs for a provider using | |
| // the installed `opencode` binary. The CLI is the source of truth for custom | |
| // models that may not appear in ~/.cache/opencode/models.json yet. | |
| var listModelsForProvider = func(providerID string) ([]string, error) { | |
| cmd := exec.Command("opencode", "models", providerID) | |
| output, err := cmd.Output() | |
| if err != nil { | |
| return nil, err | |
| } | |
| var models []string | |
| for _, line := range strings.Split(string(output), "\n") { | |
| line = strings.TrimSpace(line) | |
| if line == "" { | |
| continue | |
| } | |
| parts := strings.SplitN(line, "/", 2) | |
| if len(parts) != 2 || parts[0] != providerID || parts[1] == "" { | |
| continue | |
| } | |
| models = append(models, parts[1]) | |
| } | |
| return models, nil | |
| } | |
| // parseModelsForProviderOutput extracts model IDs for a provider from | |
| // `opencode models` CLI output. Lines that are empty, malformed, for a | |
| // different provider, or have an empty model suffix are ignored. | |
| func parseModelsForProviderOutput(providerID, output string) []string { | |
| var models []string | |
| for _, line := range strings.Split(output, "\n") { | |
| line = strings.TrimSpace(line) | |
| if line == "" { | |
| continue | |
| } | |
| parts := strings.SplitN(line, "/", 2) | |
| if len(parts) != 2 || parts[0] != providerID || parts[1] == "" { | |
| continue | |
| } | |
| models = append(models, parts[1]) | |
| } | |
| return models | |
| } | |
| // listModelsForProvider returns runtime-visible model IDs for a provider using | |
| // the installed `opencode` binary. The CLI is the source of truth for custom | |
| // models that may not appear in ~/.cache/opencode/models.json yet. | |
| var listModelsForProvider = func(providerID string) ([]string, error) { | |
| cmd := exec.Command("opencode", "models", providerID) | |
| output, err := cmd.Output() | |
| if err != nil { | |
| return nil, err | |
| } | |
| return parseModelsForProviderOutput(providerID, string(output)), nil | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,7 @@ func NewModelPickerState(cachePath string) ModelPickerState { | |
| } | ||
|
|
||
| available := opencode.DetectAvailableProviders(providers) | ||
| opencode.EnrichProvidersWithRuntimeModels(providers, available) | ||
|
|
||
|
Comment on lines
63
to
65
|
||
| sddModels := make(map[string][]opencode.Model, len(available)) | ||
| for _, id := range available { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
listModelsForProviderrunsopencode models <provider>withexec.Command(...).Output()and no timeout/context. Because this is invoked during TUI initialization, a slow/hungopencodeprocess can freeze the UI. Consider usingexec.CommandContextwith a short timeout (and optionallyexec.LookPathupfront) and capturing stderr (e.g., viaCombinedOutput) so failures return quickly and are diagnosable.