From 47a626fb61a3d94baa52491c4f1f6120dfe320f1 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 18 Feb 2026 18:57:37 +0000 Subject: [PATCH] fix: don't migrate Moonshot API keys to Z.ai (incompatible APIs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moonshot (Kimi) and Z.ai are separate services with incompatible API keys. The previous migration blindly copied Moonshot config to Zai, which would cause auth failures since a Moonshot key can't authenticate against api.z.ai. Changes: - migrateProviders() now only migrates Zhipu→Zai (same company rebrand) - Provider fallback for kimi/moonshot models tries Zai first, then falls back to legacy Moonshot config with api.moonshot.cn endpoint - Explicit "moonshot"/"kimi" provider names also fallback correctly - Update IDENTITY.md: Zhipu → Z.ai https://claude.ai/code/session_01MYemTMPtHrcgidWs8UdjcG --- pkg/config/config.go | 14 ++++++-------- pkg/providers/http_provider.go | 29 ++++++++++++++++++++++++++++- workspace/IDENTITY.md | 2 +- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index e88b30ff4..430d2c106 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -379,15 +379,13 @@ func LoadConfig(path string) (*Config, error) { return cfg, nil } -// migrateProviders merges deprecated Zhipu and Moonshot provider configs into Zai. -// If Zai is not configured, it falls back to Zhipu first, then Moonshot. +// migrateProviders merges deprecated Zhipu provider config into Zai. +// Zhipu AI rebranded to Z.ai in 2025 - same company, same API. +// Note: Moonshot (Kimi) is a separate service and is NOT migrated +// automatically, as Moonshot API keys are incompatible with Z.ai. func (c *Config) migrateProviders() { - if c.Providers.Zai.APIKey == "" { - if c.Providers.Zhipu.APIKey != "" { - c.Providers.Zai = c.Providers.Zhipu - } else if c.Providers.Moonshot.APIKey != "" { - c.Providers.Zai = c.Providers.Moonshot - } + if c.Providers.Zai.APIKey == "" && c.Providers.Zhipu.APIKey != "" { + c.Providers.Zai = c.Providers.Zhipu } } diff --git a/pkg/providers/http_provider.go b/pkg/providers/http_provider.go index 959169fb1..5b29de1aa 100644 --- a/pkg/providers/http_provider.go +++ b/pkg/providers/http_provider.go @@ -326,6 +326,8 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) { } } case "moonshot", "kimi": + // Moonshot/Kimi is deprecated. Prefer using "zai" provider instead. + // Falls back to legacy Moonshot config for backward compat. if cfg.Providers.Zai.APIKey != "" { apiKey = cfg.Providers.Zai.APIKey apiBase = cfg.Providers.Zai.APIBase @@ -333,6 +335,13 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) { if apiBase == "" { apiBase = "https://api.z.ai/api/paas/v4" } + } else if cfg.Providers.Moonshot.APIKey != "" { + apiKey = cfg.Providers.Moonshot.APIKey + apiBase = cfg.Providers.Moonshot.APIBase + proxy = cfg.Providers.Moonshot.Proxy + if apiBase == "" { + apiBase = "https://api.moonshot.cn/v1" + } } case "github_copilot", "copilot": if cfg.Providers.GitHubCopilot.APIBase != "" { @@ -349,7 +358,7 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) { // Fallback: detect provider from model name if apiKey == "" && apiBase == "" { switch { - case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/") || strings.Contains(lowerModel, "zai") || strings.HasPrefix(model, "zai/")) && cfg.Providers.Zai.APIKey != "": + case (strings.Contains(lowerModel, "zai") || strings.HasPrefix(model, "zai/")) && cfg.Providers.Zai.APIKey != "": apiKey = cfg.Providers.Zai.APIKey apiBase = cfg.Providers.Zai.APIBase proxy = cfg.Providers.Zai.Proxy @@ -357,6 +366,24 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) { apiBase = "https://api.z.ai/api/paas/v4" } + case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/")): + // Kimi/Moonshot models: prefer Zai, fallback to legacy Moonshot config + if cfg.Providers.Zai.APIKey != "" { + apiKey = cfg.Providers.Zai.APIKey + apiBase = cfg.Providers.Zai.APIBase + proxy = cfg.Providers.Zai.Proxy + if apiBase == "" { + apiBase = "https://api.z.ai/api/paas/v4" + } + } else if cfg.Providers.Moonshot.APIKey != "" { + apiKey = cfg.Providers.Moonshot.APIKey + apiBase = cfg.Providers.Moonshot.APIBase + proxy = cfg.Providers.Moonshot.Proxy + if apiBase == "" { + apiBase = "https://api.moonshot.cn/v1" + } + } + case strings.HasPrefix(model, "openrouter/") || strings.HasPrefix(model, "anthropic/") || strings.HasPrefix(model, "openai/") || strings.HasPrefix(model, "meta-llama/") || strings.HasPrefix(model, "deepseek/") || strings.HasPrefix(model, "google/"): apiKey = cfg.Providers.OpenRouter.APIKey proxy = cfg.Providers.OpenRouter.Proxy diff --git a/workspace/IDENTITY.md b/workspace/IDENTITY.md index dabb0e14b..edc034ac9 100644 --- a/workspace/IDENTITY.md +++ b/workspace/IDENTITY.md @@ -11,7 +11,7 @@ Ultra-lightweight personal AI assistant written in Go, inspired by nanobot. ## Purpose - Provide intelligent AI assistance with minimal resource usage -- Support multiple LLM providers (OpenAI, Anthropic, Zhipu, etc.) +- Support multiple LLM providers (OpenAI, Anthropic, Z.ai, etc.) - Enable easy customization through skills system - Run on minimal hardware ($10 boards, <10MB RAM)