Skip to content

Commit 75adbb3

Browse files
Alexey Panfilovclaude
andcommitted
feat(llm): provider base URLs come with sensible defaults
New llm.ApplyProviderDefaults fills base_url from env vars (OPENROUTER_BASE_URL, CLAUDE_BRIDGE_URL, OLLAMA_BASE_URL) falling back to hardcoded values — so standard Docker deployments can omit the field entirely in config.yaml. The main.go dispatch and BuildBackendFactories both call it before constructing providers. claude-bridge's startup check relaxes from \"base_url required\" to \"api_key required\" since the URL is now defaulted; users running the bridge on a non-default host set CLAUDE_BRIDGE_URL. Gemini ignores base_url (native endpoint is a const); keep for future openai-compat proxy support only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 420d6d9 commit 75adbb3

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

cmd/agent/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ func main() {
6363
if name == "embedding" {
6464
continue
6565
}
66+
// Fill in well-known defaults (base URLs etc.) so config entries can
67+
// omit them. See llm.ApplyProviderDefaults for the policy.
68+
mc = llm.ApplyProviderDefaults(mc)
6669
switch mc.Provider {
6770
case "openrouter":
6871
if mc.APIKey == "" || mc.Model == "" {
@@ -83,7 +86,9 @@ func main() {
8386
p, e := llm.NewOllama(mc)
8487
addProvider(name, p, e)
8588
case "claude-bridge":
86-
if mc.BaseURL == "" {
89+
// base_url now has a default (host.docker.internal:9900); api_key
90+
// (bridge token) is still mandatory.
91+
if mc.APIKey == "" {
8792
continue
8893
}
8994
p, e := llm.NewClaudeBridge(mc)

internal/llm/defaults.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package llm
2+
3+
import (
4+
"os"
5+
6+
"telegram-agent/internal/config"
7+
)
8+
9+
// Default base URLs for each provider type. The ones that never change
10+
// (OpenRouter, Google) are hardcoded; Docker-host-bound ones (Claude Bridge,
11+
// Ollama) read an env var first so non-Docker deployments can override.
12+
const (
13+
DefaultOpenRouterBaseURL = "https://openrouter.ai/api/v1"
14+
// GeminiNativeProvider has its own endpoint constant — this is only used
15+
// if someone ever wires Gemini through an OpenAI-compat proxy.
16+
DefaultGeminiOpenAIBaseURL = "https://generativelanguage.googleapis.com/v1beta/openai/"
17+
// DefaultClaudeBridgeURL assumes bot-in-Docker + bridge-on-host; override
18+
// with CLAUDE_BRIDGE_URL for other topologies.
19+
DefaultClaudeBridgeURL = "http://host.docker.internal:9900"
20+
DefaultOllamaBaseURL = "http://host.docker.internal:11434"
21+
)
22+
23+
// ApplyProviderDefaults fills in fields that have well-known defaults when
24+
// they're absent from the config entry. Returns a copy — the original is
25+
// never mutated so callers that keep cfg.Models references around don't
26+
// see surprise changes.
27+
//
28+
// Current defaults:
29+
// - openrouter → base_url = OPENROUTER_BASE_URL env or DefaultOpenRouterBaseURL
30+
// - claude-bridge→ base_url = CLAUDE_BRIDGE_URL env or DefaultClaudeBridgeURL
31+
// - ollama → base_url = OLLAMA_BASE_URL env or DefaultOllamaBaseURL
32+
// - gemini → base_url is unused by the native provider (kept for the
33+
// openai-compat variant only).
34+
//
35+
// Secrets (api_key) are NOT filled here — callers should already expand
36+
// ${ENV_VAR} before reaching this function.
37+
func ApplyProviderDefaults(cfg config.ModelConfig) config.ModelConfig {
38+
if cfg.BaseURL != "" {
39+
return cfg
40+
}
41+
switch cfg.Provider {
42+
case "openrouter":
43+
cfg.BaseURL = firstNonEmpty(os.Getenv("OPENROUTER_BASE_URL"), DefaultOpenRouterBaseURL)
44+
case "claude-bridge":
45+
cfg.BaseURL = firstNonEmpty(os.Getenv("CLAUDE_BRIDGE_URL"), DefaultClaudeBridgeURL)
46+
case "ollama":
47+
cfg.BaseURL = firstNonEmpty(os.Getenv("OLLAMA_BASE_URL"), DefaultOllamaBaseURL)
48+
case "gemini":
49+
// Native provider ignores BaseURL. Keep empty.
50+
}
51+
return cfg
52+
}
53+
54+
func firstNonEmpty(vals ...string) string {
55+
for _, v := range vals {
56+
if v != "" {
57+
return v
58+
}
59+
}
60+
return ""
61+
}

internal/llm/factory.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func BuildBackendFactories(cfg *config.Config) map[string]BackendFactory {
3030
if seen[mc.Provider] {
3131
continue
3232
}
33+
mc = ApplyProviderDefaults(mc)
3334
switch mc.Provider {
3435
case "openrouter":
3536
base := mc

0 commit comments

Comments
 (0)