From c1e3265b96a341d366fa796b1c61b50702109a0d Mon Sep 17 00:00:00 2001 From: ChethanUK Date: Mon, 6 Jul 2026 13:08:24 +0200 Subject: [PATCH] feat(llm): add built-in Ollama Cloud provider preset Add an ollama-cloud entry to the provider registry: OpenAI protocol, base URL https://ollama.com/v1, env OLLAMA_API_KEY, models gpt-oss:120b and gpt-oss:20b. Values match Ollama Cloud's OpenAI-compatible endpoint. Tests cover provider order/count and per-field lookup details. Closes #305 --- internal/llm/providers.go | 11 +++++++++++ internal/llm/providers_test.go | 30 +++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/internal/llm/providers.go b/internal/llm/providers.go index 9a80981f..cccd3448 100644 --- a/internal/llm/providers.go +++ b/internal/llm/providers.go @@ -225,6 +225,17 @@ var registry = []Provider{ "kimi-k2.6", }, }, + { + Name: "ollama-cloud", + DisplayName: "Ollama Cloud API", + Protocol: "openai", + BaseURL: "https://ollama.com/v1", + EnvVar: "OLLAMA_API_KEY", + Models: []string{ + "gpt-oss:120b", + "gpt-oss:20b", + }, + }, } var registryMap map[string]Provider diff --git a/internal/llm/providers_test.go b/internal/llm/providers_test.go index 4f3fdf42..684a1848 100644 --- a/internal/llm/providers_test.go +++ b/internal/llm/providers_test.go @@ -40,7 +40,7 @@ func TestListProviders_Order(t *testing.T) { if len(providers) < 3 { t.Fatalf("expected at least 3 providers, got %d", len(providers)) } - expected := []string{"anthropic", "baidu-qianfan", "dashscope", "dashscope-tokenplan", "deepseek", "hy-tokenplan", "kimi", "mimo", "minimax", "openai", "tencent-tokenhub", "volcengine", "z-ai", "z-ai-coding"} + expected := []string{"anthropic", "baidu-qianfan", "dashscope", "dashscope-tokenplan", "deepseek", "hy-tokenplan", "kimi", "mimo", "minimax", "ollama-cloud", "openai", "tencent-tokenhub", "volcengine", "z-ai", "z-ai-coding"} if len(providers) != len(expected) { t.Fatalf("expected %d providers, got %d", len(expected), len(providers)) } @@ -126,3 +126,31 @@ func TestLookupProvider_OpenAIDetails(t *testing.T) { t.Errorf("AuthHeader = %q, want empty", p.AuthHeader) } } + +func TestLookupProvider_OllamaCloudDetails(t *testing.T) { + p, ok := LookupProvider("ollama-cloud") + if !ok { + t.Fatal("ollama-cloud not found") + } + if p.Protocol != "openai" { + t.Errorf("Protocol = %q, want %q", p.Protocol, "openai") + } + if p.BaseURL != "https://ollama.com/v1" { + t.Errorf("BaseURL = %q, want %q", p.BaseURL, "https://ollama.com/v1") + } + if p.EnvVar != "OLLAMA_API_KEY" { + t.Errorf("EnvVar = %q, want %q", p.EnvVar, "OLLAMA_API_KEY") + } + if p.AuthHeader != "" { + t.Errorf("AuthHeader = %q, want empty", p.AuthHeader) + } + expectedModels := []string{"gpt-oss:120b", "gpt-oss:20b"} + if len(p.Models) != len(expectedModels) { + t.Fatalf("expected %d models, got %d", len(expectedModels), len(p.Models)) + } + for i, model := range expectedModels { + if p.Models[i] != model { + t.Errorf("Models[%d] = %q, want %q", i, p.Models[i], model) + } + } +}