Respect ollama model baseUrl before default
- commit
- a7ef8c22a1e1694ab93b033628e5d015ab0975a6
- author
- patriceckhart · · 2026-06-08 05:41 UTC
- parent
- 7da9114
- signature
- unsigned
- refs
- tag: v0.2.16
2 files · +44 -4
M packages/agent/build.go +6 -4
| @@ -305,9 +305,6 @@ func Resolve(args Args, requireCred bool) (Resolved, error) { | |||
| 305 | 305 | credErr error | |
| 306 | 306 | ) | |
| 307 | 307 | if provName == "ollama" { | |
| 308 | - | if args.BaseURL == "" { | |
| 309 | - | args.BaseURL = "http://localhost:11434" | |
| 310 | - | } | |
| 311 | 308 | cred = firstNonEmpty(args.APIKey, "ollama") | |
| 312 | 309 | method = "apikey" | |
| 313 | 310 | } else { | |
| @@ -398,10 +395,15 @@ func Resolve(args Args, requireCred bool) (Resolved, error) { | |||
| 398 | 395 | } | |
| 399 | 396 | ||
| 400 | 397 | // If the model defines a base URL (e.g. local ollama) and the | |
| 401 | - | // user didn't pass --base-url, use the model's URL. | |
| 398 | + | // user didn't pass --base-url, use the model's URL. For ollama, | |
| 399 | + | // keep http://localhost:11434 as a fallback only after the model | |
| 400 | + | // metadata has had a chance to provide a custom baseUrl. | |
| 402 | 401 | if args.BaseURL == "" && resolvedModel.BaseURL != "" { | |
| 403 | 402 | args.BaseURL = resolvedModel.BaseURL | |
| 404 | 403 | } | |
| 404 | + | if args.BaseURL == "" && provName == "ollama" { | |
| 405 | + | args.BaseURL = "http://localhost:11434" | |
| 406 | + | } | |
| 405 | 407 | ||
| 406 | 408 | // If the model has a base URL, credentials are optional (local | |
| 407 | 409 | // models like ollama don't need real API keys). | |
| @@ -305,9 +305,6 @@ func Resolve(args Args, requireCred bool) (Resolved, error) { | |||||
| 305 | credErr error | 305 | credErr error | ||
| 306 | ) | 306 | ) | ||
| 307 | if provName == "ollama" { | 307 | if provName == "ollama" { | ||
| 308 | - | if args.BaseURL == "" { | |||
| 309 | - | args.BaseURL = "http://localhost:11434" | |||
| 310 | - | } | |||
| 311 | cred = firstNonEmpty(args.APIKey, "ollama") | 308 | cred = firstNonEmpty(args.APIKey, "ollama") | ||
| 312 | method = "apikey" | 309 | method = "apikey" | ||
| 313 | } else { | 310 | } else { | ||
| @@ -398,10 +395,15 @@ func Resolve(args Args, requireCred bool) (Resolved, error) { | |||||
| 398 | } | 395 | } | ||
| 399 | 396 | ||||
| 400 | // If the model defines a base URL (e.g. local ollama) and the | 397 | // If the model defines a base URL (e.g. local ollama) and the | ||
| 401 | - | // user didn't pass --base-url, use the model's URL. | 398 | + | // user didn't pass --base-url, use the model's URL. For ollama, |
| 399 | + | // keep http://localhost:11434 as a fallback only after the model | |||
| 400 | + | // metadata has had a chance to provide a custom baseUrl. | |||
| 402 | if args.BaseURL == "" && resolvedModel.BaseURL != "" { | 401 | if args.BaseURL == "" && resolvedModel.BaseURL != "" { | ||
| 403 | args.BaseURL = resolvedModel.BaseURL | 402 | args.BaseURL = resolvedModel.BaseURL | ||
| 404 | } | 403 | } | ||
| 404 | + | if args.BaseURL == "" && provName == "ollama" { | |||
| 405 | + | args.BaseURL = "http://localhost:11434" | |||
| 406 | + | } | |||
| 405 | 407 | ||||
| 406 | // If the model has a base URL, credentials are optional (local | 408 | // If the model has a base URL, credentials are optional (local | ||
| 407 | // models like ollama don't need real API keys). | 409 | // models like ollama don't need real API keys). | ||
M packages/agent/build_test.go +38 -0
| @@ -5,6 +5,8 @@ import ( | |||
| 5 | 5 | "path/filepath" | |
| 6 | 6 | "strings" | |
| 7 | 7 | "testing" | |
| 8 | + | ||
| 9 | + | "github.com/patriceckhart/zot/packages/provider" | |
| 8 | 10 | ) | |
| 9 | 11 | ||
| 10 | 12 | func TestReadAgentsContextLoadsGlobalAndAncestors(t *testing.T) { | |
| @@ -109,6 +111,42 @@ func TestResolveExplicitFlagStaleDoesNotRepairConfig(t *testing.T) { | |||
| 109 | 111 | } | |
| 110 | 112 | } | |
| 111 | 113 | ||
| 114 | + | func TestResolveOllamaUsesModelBaseURLBeforeDefault(t *testing.T) { | |
| 115 | + | t.Setenv("ZOT_HOME", t.TempDir()) | |
| 116 | + | provider.SetLiveModels(nil) | |
| 117 | + | defer provider.SetLiveModels(nil) | |
| 118 | + | provider.SetUserModels([]provider.Model{{ | |
| 119 | + | Provider: "ollama", | |
| 120 | + | ID: "qwen-local", | |
| 121 | + | DisplayName: "Qwen Local", | |
| 122 | + | ContextWindow: 32768, | |
| 123 | + | MaxOutput: 8192, | |
| 124 | + | BaseURL: "http://localhost:8000/v1", | |
| 125 | + | }}) | |
| 126 | + | ||
| 127 | + | r, err := Resolve(Args{Provider: "ollama", Model: "qwen-local"}, false) | |
| 128 | + | if err != nil { | |
| 129 | + | t.Fatalf("Resolve failed: %v", err) | |
| 130 | + | } | |
| 131 | + | if r.BaseURL != "http://localhost:8000/v1" { | |
| 132 | + | t.Fatalf("BaseURL = %q, want models.json baseUrl", r.BaseURL) | |
| 133 | + | } | |
| 134 | + | } | |
| 135 | + | ||
| 136 | + | func TestResolveOllamaFallsBackToDefaultBaseURL(t *testing.T) { | |
| 137 | + | t.Setenv("ZOT_HOME", t.TempDir()) | |
| 138 | + | provider.SetLiveModels(nil) | |
| 139 | + | defer provider.SetLiveModels(nil) | |
| 140 | + | ||
| 141 | + | r, err := Resolve(Args{Provider: "ollama", Model: "any-local-model"}, false) | |
| 142 | + | if err != nil { | |
| 143 | + | t.Fatalf("Resolve failed: %v", err) | |
| 144 | + | } | |
| 145 | + | if r.BaseURL != "http://localhost:11434" { | |
| 146 | + | t.Fatalf("BaseURL = %q, want ollama default", r.BaseURL) | |
| 147 | + | } | |
| 148 | + | } | |
| 149 | + | ||
| 112 | 150 | func TestCanonicalProviderResolvesAliases(t *testing.T) { | |
| 113 | 151 | cases := map[string]string{ | |
| 114 | 152 | "bedrock": "amazon-bedrock", | |
| @@ -5,6 +5,8 @@ import ( | |||||
| 5 | "path/filepath" | 5 | "path/filepath" | ||
| 6 | "strings" | 6 | "strings" | ||
| 7 | "testing" | 7 | "testing" | ||
| 8 | + | ||||
| 9 | + | "github.com/patriceckhart/zot/packages/provider" | |||
| 8 | ) | 10 | ) | ||
| 9 | 11 | ||||
| 10 | func TestReadAgentsContextLoadsGlobalAndAncestors(t *testing.T) { | 12 | func TestReadAgentsContextLoadsGlobalAndAncestors(t *testing.T) { | ||
| @@ -109,6 +111,42 @@ func TestResolveExplicitFlagStaleDoesNotRepairConfig(t *testing.T) { | |||||
| 109 | } | 111 | } | ||
| 110 | } | 112 | } | ||
| 111 | 113 | ||||
| 114 | + | func TestResolveOllamaUsesModelBaseURLBeforeDefault(t *testing.T) { | |||
| 115 | + | t.Setenv("ZOT_HOME", t.TempDir()) | |||
| 116 | + | provider.SetLiveModels(nil) | |||
| 117 | + | defer provider.SetLiveModels(nil) | |||
| 118 | + | provider.SetUserModels([]provider.Model{{ | |||
| 119 | + | Provider: "ollama", | |||
| 120 | + | ID: "qwen-local", | |||
| 121 | + | DisplayName: "Qwen Local", | |||
| 122 | + | ContextWindow: 32768, | |||
| 123 | + | MaxOutput: 8192, | |||
| 124 | + | BaseURL: "http://localhost:8000/v1", | |||
| 125 | + | }}) | |||
| 126 | + | ||||
| 127 | + | r, err := Resolve(Args{Provider: "ollama", Model: "qwen-local"}, false) | |||
| 128 | + | if err != nil { | |||
| 129 | + | t.Fatalf("Resolve failed: %v", err) | |||
| 130 | + | } | |||
| 131 | + | if r.BaseURL != "http://localhost:8000/v1" { | |||
| 132 | + | t.Fatalf("BaseURL = %q, want models.json baseUrl", r.BaseURL) | |||
| 133 | + | } | |||
| 134 | + | } | |||
| 135 | + | ||||
| 136 | + | func TestResolveOllamaFallsBackToDefaultBaseURL(t *testing.T) { | |||
| 137 | + | t.Setenv("ZOT_HOME", t.TempDir()) | |||
| 138 | + | provider.SetLiveModels(nil) | |||
| 139 | + | defer provider.SetLiveModels(nil) | |||
| 140 | + | ||||
| 141 | + | r, err := Resolve(Args{Provider: "ollama", Model: "any-local-model"}, false) | |||
| 142 | + | if err != nil { | |||
| 143 | + | t.Fatalf("Resolve failed: %v", err) | |||
| 144 | + | } | |||
| 145 | + | if r.BaseURL != "http://localhost:11434" { | |||
| 146 | + | t.Fatalf("BaseURL = %q, want ollama default", r.BaseURL) | |||
| 147 | + | } | |||
| 148 | + | } | |||
| 149 | + | ||||
| 112 | func TestCanonicalProviderResolvesAliases(t *testing.T) { | 150 | func TestCanonicalProviderResolvesAliases(t *testing.T) { | ||
| 113 | cases := map[string]string{ | 151 | cases := map[string]string{ | ||
| 114 | "bedrock": "amazon-bedrock", | 152 | "bedrock": "amazon-bedrock", | ||