diff --git a/.env.example b/.env.example index 66010b1f5..012d68e39 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,7 @@ # GEMINI_API_KEY=xxx # MODELSCOPE_API_KEY=xxx # CLAUDE_CODE_OAUTH=xxx +# NOVITA_API_KEY=sk-xxx # ── Chat Channel ────────────────────────── # TELEGRAM_BOT_TOKEN=123456:ABC... # DISCORD_BOT_TOKEN=xxx diff --git a/pkg/config/config.go b/pkg/config/config.go index 35de48f23..eb6df77a0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -523,6 +523,7 @@ type ProvidersConfig struct { Cerebras ProviderConfig `json:"cerebras"` Vivgrid ProviderConfig `json:"vivgrid"` VolcEngine ProviderConfig `json:"volcengine"` + Novita ProviderConfig `json:"novita"` GitHubCopilot ProviderConfig `json:"github_copilot"` Antigravity ProviderConfig `json:"antigravity"` Qwen ProviderConfig `json:"qwen"` @@ -552,6 +553,7 @@ func (p ProvidersConfig) IsEmpty() bool { p.Cerebras.APIKey == "" && p.Cerebras.APIBase == "" && p.Vivgrid.APIKey == "" && p.Vivgrid.APIBase == "" && p.VolcEngine.APIKey == "" && p.VolcEngine.APIBase == "" && + p.Novita.APIKey == "" && p.Novita.APIBase == "" && p.GitHubCopilot.APIKey == "" && p.GitHubCopilot.APIBase == "" && p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" && p.Qwen.APIKey == "" && p.Qwen.APIBase == "" && diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 2b177d5de..a149d4a6c 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -377,6 +377,26 @@ func DefaultConfig() *Config { APIKey: "", }, + // Novita AI - https://novita.ai + { + ModelName: "deepseek-v3.2", + Model: "novita/deepseek/deepseek-v3.2", + APIBase: "https://api.novita.ai/openai", + APIKey: "", + }, + { + ModelName: "glm-5", + Model: "novita/zai-org/glm-5", + APIBase: "https://api.novita.ai/openai", + APIKey: "", + }, + { + ModelName: "minimax-m2.5", + Model: "novita/minimax/minimax-m2.5", + APIBase: "https://api.novita.ai/openai", + APIKey: "", + }, + // VLLM (local) - http://localhost:8000 { ModelName: "local-model", diff --git a/pkg/providers/factory.go b/pkg/providers/factory.go index d2afe2943..94914d919 100644 --- a/pkg/providers/factory.go +++ b/pkg/providers/factory.go @@ -230,6 +230,15 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) { sel.apiBase = "https://api.longcat.chat/openai" } } + case "novita": + if cfg.Providers.Novita.APIKey != "" { + sel.apiKey = cfg.Providers.Novita.APIKey + sel.apiBase = cfg.Providers.Novita.APIBase + sel.proxy = cfg.Providers.Novita.Proxy + if sel.apiBase == "" { + sel.apiBase = "https://api.novita.ai/openai" + } + } case "github_copilot", "copilot": sel.providerType = providerTypeGitHubCopilot if cfg.Providers.GitHubCopilot.APIBase != "" { @@ -368,6 +377,13 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) { if sel.apiBase == "" { sel.apiBase = "https://api.longcat.chat/openai" } + case (strings.Contains(lowerModel, "novita") || strings.HasPrefix(model, "novita/")) && cfg.Providers.Novita.APIKey != "": + sel.apiKey = cfg.Providers.Novita.APIKey + sel.apiBase = cfg.Providers.Novita.APIBase + sel.proxy = cfg.Providers.Novita.Proxy + if sel.apiBase == "" { + sel.apiBase = "https://api.novita.ai/openai" + } case cfg.Providers.VLLM.APIBase != "": sel.apiKey = cfg.Providers.VLLM.APIKey sel.apiBase = cfg.Providers.VLLM.APIBase diff --git a/pkg/providers/factory_test.go b/pkg/providers/factory_test.go index 91469f25b..53a82d2b7 100644 --- a/pkg/providers/factory_test.go +++ b/pkg/providers/factory_test.go @@ -189,6 +189,17 @@ func TestResolveProviderSelection(t *testing.T) { wantAPIBase: "https://api.longcat.chat/openai", wantProxy: "http://127.0.0.1:7890", }, + { + name: "explicit novita provider uses defaults", + setup: func(cfg *config.Config) { + cfg.Agents.Defaults.Provider = "novita" + cfg.Providers.Novita.APIKey = "novita-key" + cfg.Providers.Novita.Proxy = "http://127.0.0.1:7890" + }, + wantType: providerTypeHTTPCompat, + wantAPIBase: "https://api.novita.ai/openai", + wantProxy: "http://127.0.0.1:7890", + }, { name: "longcat model fallback uses longcat base default", setup: func(cfg *config.Config) { @@ -198,6 +209,15 @@ func TestResolveProviderSelection(t *testing.T) { wantType: providerTypeHTTPCompat, wantAPIBase: "https://api.longcat.chat/openai", }, + { + name: "novita model fallback uses novita base default", + setup: func(cfg *config.Config) { + cfg.Agents.Defaults.Model = "novita/deepseek/deepseek-v3.2" + cfg.Providers.Novita.APIKey = "novita-key" + }, + wantType: providerTypeHTTPCompat, + wantAPIBase: "https://api.novita.ai/openai", + }, { name: "missing keys returns model config error", setup: func(cfg *config.Config) {