fix: don't migrate Moonshot API keys to Z.ai (incompatible APIs)

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
This commit is contained in:
Claude 2026-02-18 18:57:37 +00:00
parent 09a03c4ed5
commit 47a626fb61
No known key found for this signature in database
3 changed files with 35 additions and 10 deletions

View file

@ -379,15 +379,13 @@ func LoadConfig(path string) (*Config, error) {
return cfg, nil return cfg, nil
} }
// migrateProviders merges deprecated Zhipu and Moonshot provider configs into Zai. // migrateProviders merges deprecated Zhipu provider config into Zai.
// If Zai is not configured, it falls back to Zhipu first, then Moonshot. // 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() { func (c *Config) migrateProviders() {
if c.Providers.Zai.APIKey == "" { if c.Providers.Zai.APIKey == "" && c.Providers.Zhipu.APIKey != "" {
if c.Providers.Zhipu.APIKey != "" {
c.Providers.Zai = c.Providers.Zhipu c.Providers.Zai = c.Providers.Zhipu
} else if c.Providers.Moonshot.APIKey != "" {
c.Providers.Zai = c.Providers.Moonshot
}
} }
} }

View file

@ -326,6 +326,8 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
} }
} }
case "moonshot", "kimi": 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 != "" { if cfg.Providers.Zai.APIKey != "" {
apiKey = cfg.Providers.Zai.APIKey apiKey = cfg.Providers.Zai.APIKey
apiBase = cfg.Providers.Zai.APIBase apiBase = cfg.Providers.Zai.APIBase
@ -333,6 +335,13 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
if apiBase == "" { if apiBase == "" {
apiBase = "https://api.z.ai/api/paas/v4" 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": case "github_copilot", "copilot":
if cfg.Providers.GitHubCopilot.APIBase != "" { if cfg.Providers.GitHubCopilot.APIBase != "" {
@ -349,7 +358,7 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
// Fallback: detect provider from model name // Fallback: detect provider from model name
if apiKey == "" && apiBase == "" { if apiKey == "" && apiBase == "" {
switch { 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 apiKey = cfg.Providers.Zai.APIKey
apiBase = cfg.Providers.Zai.APIBase apiBase = cfg.Providers.Zai.APIBase
proxy = cfg.Providers.Zai.Proxy proxy = cfg.Providers.Zai.Proxy
@ -357,6 +366,24 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
apiBase = "https://api.z.ai/api/paas/v4" 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/"): 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 apiKey = cfg.Providers.OpenRouter.APIKey
proxy = cfg.Providers.OpenRouter.Proxy proxy = cfg.Providers.OpenRouter.Proxy

View file

@ -11,7 +11,7 @@ Ultra-lightweight personal AI assistant written in Go, inspired by nanobot.
## Purpose ## Purpose
- Provide intelligent AI assistance with minimal resource usage - 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 - Enable easy customization through skills system
- Run on minimal hardware ($10 boards, <10MB RAM) - Run on minimal hardware ($10 boards, <10MB RAM)