mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-11 23:40:28 -10:00
* Polish model status and reasoning streams
* Polish custom provider setup flow
* Clean up pending composer hints
* Address custom provider setup review
* Polish composer overflow handling
* Fix composer paste and wheel edge cases
* Use line counts for paste previews
* Revert "Use line counts for paste previews"
This reverts commit 4feb814d09.
* Fix composer paste preview deletion
* Disable textinput ctrl-v paste binding
* Preserve paste previews through file suggestions
* Clarify composer paste preview behavior
* Keep OpenAI reasoning out of answer text
222 lines
6.4 KiB
Go
222 lines
6.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/Gitlawb/zero/internal/config"
|
|
"github.com/Gitlawb/zero/internal/providercatalog"
|
|
"github.com/Gitlawb/zero/internal/tui"
|
|
)
|
|
|
|
func TestSetupMissingCredentialEnv(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
profile config.ProviderProfile
|
|
wantEnv string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "catalog provider",
|
|
profile: config.ProviderProfile{
|
|
Name: "groq",
|
|
CatalogID: "groq",
|
|
},
|
|
wantEnv: "GROQ_API_KEY",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "openai compatible without catalog",
|
|
profile: config.ProviderProfile{
|
|
Name: "custom",
|
|
ProviderKind: config.ProviderKindOpenAICompatible,
|
|
},
|
|
wantEnv: "OPENAI_API_KEY",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "local provider",
|
|
profile: config.ProviderProfile{
|
|
Name: "local",
|
|
CatalogID: "ollama",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "ollama cloud provider",
|
|
profile: config.ProviderProfile{
|
|
Name: "ollama-cloud",
|
|
CatalogID: "ollama-cloud",
|
|
},
|
|
wantEnv: "OLLAMA_API_KEY",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "credential resolved",
|
|
profile: config.ProviderProfile{
|
|
Name: "openai",
|
|
ProviderKind: config.ProviderKindOpenAI,
|
|
APIKey: "sk-test",
|
|
},
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
gotEnv, got := setupMissingCredentialEnv(tt.profile)
|
|
if got != tt.want || gotEnv != tt.wantEnv {
|
|
t.Fatalf("setupMissingCredentialEnv() = (%q, %v), want (%q, %v)", gotEnv, got, tt.wantEnv, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetupProviderOptionsUseRuntimeSupportedCatalog(t *testing.T) {
|
|
options := setupProviderOptions()
|
|
got := make([]string, 0, len(options))
|
|
for _, option := range options {
|
|
got = append(got, option.ID)
|
|
}
|
|
|
|
want := make([]string, 0)
|
|
for _, descriptor := range providercatalog.All() {
|
|
if providercatalog.RuntimeSupported(descriptor) {
|
|
want = append(want, descriptor.ID)
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("setupProviderOptions IDs = %#v, want runtime-supported catalog IDs %#v", got, want)
|
|
}
|
|
for _, excluded := range []string{"bedrock", "vertex"} {
|
|
for _, id := range got {
|
|
if id == excluded {
|
|
t.Fatalf("setupProviderOptions included unsupported provider %q in %#v", excluded, got)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSaveSetupProviderStoresPastedAPIKey(t *testing.T) {
|
|
configPath := filepath.Join(t.TempDir(), "zero", "config.json")
|
|
|
|
result, err := saveSetupProvider(appDeps{
|
|
userConfigPath: func() (string, error) {
|
|
return configPath, nil
|
|
},
|
|
}, tui.SetupSelection{
|
|
CatalogID: "ollama-cloud",
|
|
Model: "qwen3-coder:480b",
|
|
APIKey: "sk-pasted-secret",
|
|
}, setupSaveOptions{})
|
|
if err != nil {
|
|
t.Fatalf("saveSetupProvider() error = %v", err)
|
|
}
|
|
|
|
if result.Provider.APIKey != "sk-pasted-secret" {
|
|
t.Fatalf("Provider.APIKey = %q, want pasted key", result.Provider.APIKey)
|
|
}
|
|
if result.Provider.APIKeyEnv != "" {
|
|
t.Fatalf("Provider.APIKeyEnv = %q, want empty when API key is pasted", result.Provider.APIKeyEnv)
|
|
}
|
|
|
|
cfg := readFileConfig(t, configPath)
|
|
if cfg.ActiveProvider != "ollama-cloud" {
|
|
t.Fatalf("ActiveProvider = %q, want ollama-cloud", cfg.ActiveProvider)
|
|
}
|
|
if len(cfg.Providers) != 1 {
|
|
t.Fatalf("Providers = %#v, want one provider", cfg.Providers)
|
|
}
|
|
if cfg.Providers[0].APIKey != "sk-pasted-secret" || cfg.Providers[0].APIKeyEnv != "" {
|
|
t.Fatalf("stored provider credentials = APIKey %q APIKeyEnv %q, want pasted key only", cfg.Providers[0].APIKey, cfg.Providers[0].APIKeyEnv)
|
|
}
|
|
}
|
|
|
|
func TestSaveSetupProviderStoresCustomEndpointSelection(t *testing.T) {
|
|
configPath := filepath.Join(t.TempDir(), "zero", "config.json")
|
|
|
|
result, err := saveSetupProvider(appDeps{
|
|
userConfigPath: func() (string, error) {
|
|
return configPath, nil
|
|
},
|
|
}, tui.SetupSelection{
|
|
CatalogID: "custom-openai-compatible",
|
|
Name: "minimax",
|
|
BaseURL: "https://api.minimax.io/v1",
|
|
Model: "MiniMax-M3",
|
|
}, setupSaveOptions{})
|
|
if err != nil {
|
|
t.Fatalf("saveSetupProvider() error = %v", err)
|
|
}
|
|
|
|
if result.Provider.Name != "minimax" {
|
|
t.Fatalf("Provider.Name = %q, want minimax", result.Provider.Name)
|
|
}
|
|
if result.Provider.BaseURL != "https://api.minimax.io/v1" {
|
|
t.Fatalf("Provider.BaseURL = %q, want custom endpoint", result.Provider.BaseURL)
|
|
}
|
|
if result.Provider.Model != "MiniMax-M3" {
|
|
t.Fatalf("Provider.Model = %q, want typed model", result.Provider.Model)
|
|
}
|
|
|
|
cfg := readFileConfig(t, configPath)
|
|
if cfg.ActiveProvider != "minimax" {
|
|
t.Fatalf("ActiveProvider = %q, want minimax", cfg.ActiveProvider)
|
|
}
|
|
if len(cfg.Providers) != 1 {
|
|
t.Fatalf("Providers = %#v, want one provider", cfg.Providers)
|
|
}
|
|
profile := cfg.Providers[0]
|
|
if profile.Name != "minimax" || profile.CatalogID != "custom-openai-compatible" {
|
|
t.Fatalf("stored provider identity = %#v, want minimax custom-openai-compatible", profile)
|
|
}
|
|
if profile.BaseURL != "https://api.minimax.io/v1" || profile.Model != "MiniMax-M3" {
|
|
t.Fatalf("stored provider endpoint/model = %#v", profile)
|
|
}
|
|
}
|
|
|
|
func TestSaveSetupProviderCLIOptionsOverrideCustomEndpointSelection(t *testing.T) {
|
|
configPath := filepath.Join(t.TempDir(), "zero", "config.json")
|
|
|
|
result, err := saveSetupProvider(appDeps{
|
|
userConfigPath: func() (string, error) {
|
|
return configPath, nil
|
|
},
|
|
}, tui.SetupSelection{
|
|
CatalogID: "custom-openai-compatible",
|
|
Name: "selection-name",
|
|
BaseURL: "https://selection.example/v1",
|
|
Model: "selection-model",
|
|
}, setupSaveOptions{
|
|
name: "cli-name",
|
|
baseURL: "https://cli.example/v1",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("saveSetupProvider() error = %v", err)
|
|
}
|
|
|
|
if result.Provider.Name != "cli-name" {
|
|
t.Fatalf("Provider.Name = %q, want CLI name", result.Provider.Name)
|
|
}
|
|
if result.Provider.BaseURL != "https://cli.example/v1" {
|
|
t.Fatalf("Provider.BaseURL = %q, want CLI endpoint", result.Provider.BaseURL)
|
|
}
|
|
if result.Provider.Model != "selection-model" {
|
|
t.Fatalf("Provider.Model = %q, want selection model", result.Provider.Model)
|
|
}
|
|
|
|
cfg := readFileConfig(t, configPath)
|
|
if cfg.ActiveProvider != "cli-name" {
|
|
t.Fatalf("ActiveProvider = %q, want cli-name", cfg.ActiveProvider)
|
|
}
|
|
if len(cfg.Providers) != 1 {
|
|
t.Fatalf("Providers = %#v, want one provider", cfg.Providers)
|
|
}
|
|
profile := cfg.Providers[0]
|
|
if profile.Name != "cli-name" || profile.BaseURL != "https://cli.example/v1" || profile.Model != "selection-model" {
|
|
t.Fatalf("stored provider = %#v, want CLI name/baseURL and selection model", profile)
|
|
}
|
|
}
|