feat: add Kimi/Moonshot and Opencode provider support
- Add "kimi", "kimi-code", "moonshot" provider cases in factory.go with default API base https://api.kimi.com/coding/v1 - Add Kimi Code API User-Agent header (KimiCLI/0.77) for api.kimi.com - Add "opencode" provider with default API base https://opencode.ai/zen/v1 - Add "opencode" to recognized HTTP-compatible protocols in factory_provider - Add Opencode field to ProvidersConfig, IsEmpty, HasProvidersConfig - Add opencode migration entry in ConvertProvidersToModelList - Update moonshot fallback API base from api.moonshot.cn to api.kimi.com
This commit is contained in:
parent
9c9524f934
commit
ec540312da
5 changed files with 48 additions and 4 deletions
|
|
@ -401,6 +401,7 @@ type ProvidersConfig struct {
|
||||||
Antigravity ProviderConfig `json:"antigravity"`
|
Antigravity ProviderConfig `json:"antigravity"`
|
||||||
Qwen ProviderConfig `json:"qwen"`
|
Qwen ProviderConfig `json:"qwen"`
|
||||||
Mistral ProviderConfig `json:"mistral"`
|
Mistral ProviderConfig `json:"mistral"`
|
||||||
|
Opencode ProviderConfig `json:"opencode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty checks if all provider configs are empty (no API keys or API bases set)
|
// IsEmpty checks if all provider configs are empty (no API keys or API bases set)
|
||||||
|
|
@ -423,7 +424,8 @@ func (p ProvidersConfig) IsEmpty() bool {
|
||||||
p.GitHubCopilot.APIKey == "" && p.GitHubCopilot.APIBase == "" &&
|
p.GitHubCopilot.APIKey == "" && p.GitHubCopilot.APIBase == "" &&
|
||||||
p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" &&
|
p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" &&
|
||||||
p.Qwen.APIKey == "" && p.Qwen.APIBase == "" &&
|
p.Qwen.APIKey == "" && p.Qwen.APIBase == "" &&
|
||||||
p.Mistral.APIKey == "" && p.Mistral.APIBase == ""
|
p.Mistral.APIKey == "" && p.Mistral.APIBase == "" &&
|
||||||
|
p.Opencode.APIKey == "" && p.Opencode.APIBase == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements custom JSON marshaling for ProvidersConfig
|
// MarshalJSON implements custom JSON marshaling for ProvidersConfig
|
||||||
|
|
@ -760,7 +762,8 @@ func (c *Config) HasProvidersConfig() bool {
|
||||||
v.GitHubCopilot.APIKey != "" || v.GitHubCopilot.APIBase != "" ||
|
v.GitHubCopilot.APIKey != "" || v.GitHubCopilot.APIBase != "" ||
|
||||||
v.Antigravity.APIKey != "" || v.Antigravity.APIBase != "" ||
|
v.Antigravity.APIKey != "" || v.Antigravity.APIBase != "" ||
|
||||||
v.Qwen.APIKey != "" || v.Qwen.APIBase != "" ||
|
v.Qwen.APIKey != "" || v.Qwen.APIBase != "" ||
|
||||||
v.Mistral.APIKey != "" || v.Mistral.APIBase != ""
|
v.Mistral.APIKey != "" || v.Mistral.APIBase != "" ||
|
||||||
|
v.Opencode.APIKey != "" || v.Opencode.APIBase != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateModelList validates all ModelConfig entries in the model_list.
|
// ValidateModelList validates all ModelConfig entries in the model_list.
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,23 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig {
|
||||||
}, true
|
}, true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
providerNames: []string{"opencode"},
|
||||||
|
protocol: "opencode",
|
||||||
|
buildConfig: func(p ProvidersConfig) (ModelConfig, bool) {
|
||||||
|
if p.Opencode.APIKey == "" && p.Opencode.APIBase == "" {
|
||||||
|
return ModelConfig{}, false
|
||||||
|
}
|
||||||
|
return ModelConfig{
|
||||||
|
ModelName: "opencode",
|
||||||
|
Model: "opencode/auto",
|
||||||
|
APIKey: p.Opencode.APIKey,
|
||||||
|
APIBase: p.Opencode.APIBase,
|
||||||
|
Proxy: p.Opencode.Proxy,
|
||||||
|
RequestTimeout: p.Opencode.RequestTimeout,
|
||||||
|
}, true
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each provider migration
|
// Process each provider migration
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,24 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
|
||||||
sel.apiBase = "https://api.mistral.ai/v1"
|
sel.apiBase = "https://api.mistral.ai/v1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "opencode":
|
||||||
|
if cfg.Providers.Opencode.APIKey != "" {
|
||||||
|
sel.apiKey = cfg.Providers.Opencode.APIKey
|
||||||
|
sel.apiBase = cfg.Providers.Opencode.APIBase
|
||||||
|
sel.proxy = cfg.Providers.Opencode.Proxy
|
||||||
|
if sel.apiBase == "" {
|
||||||
|
sel.apiBase = "https://opencode.ai/zen/v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "kimi", "kimi-code", "moonshot":
|
||||||
|
if cfg.Providers.Moonshot.APIKey != "" {
|
||||||
|
sel.apiKey = cfg.Providers.Moonshot.APIKey
|
||||||
|
sel.apiBase = cfg.Providers.Moonshot.APIBase
|
||||||
|
sel.proxy = cfg.Providers.Moonshot.Proxy
|
||||||
|
if sel.apiBase == "" {
|
||||||
|
sel.apiBase = "https://api.kimi.com/coding/v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
case "github_copilot", "copilot":
|
case "github_copilot", "copilot":
|
||||||
sel.providerType = providerTypeGitHubCopilot
|
sel.providerType = providerTypeGitHubCopilot
|
||||||
if cfg.Providers.GitHubCopilot.APIBase != "" {
|
if cfg.Providers.GitHubCopilot.APIBase != "" {
|
||||||
|
|
@ -201,7 +219,7 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
|
||||||
sel.apiBase = cfg.Providers.Moonshot.APIBase
|
sel.apiBase = cfg.Providers.Moonshot.APIBase
|
||||||
sel.proxy = cfg.Providers.Moonshot.Proxy
|
sel.proxy = cfg.Providers.Moonshot.Proxy
|
||||||
if sel.apiBase == "" {
|
if sel.apiBase == "" {
|
||||||
sel.apiBase = "https://api.moonshot.cn/v1"
|
sel.apiBase = "https://api.kimi.com/coding/v1"
|
||||||
}
|
}
|
||||||
case strings.HasPrefix(model, "openrouter/") ||
|
case strings.HasPrefix(model, "openrouter/") ||
|
||||||
strings.HasPrefix(model, "anthropic/") ||
|
strings.HasPrefix(model, "anthropic/") ||
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
|
||||||
|
|
||||||
case "openrouter", "groq", "zhipu", "gemini", "nvidia",
|
case "openrouter", "groq", "zhipu", "gemini", "nvidia",
|
||||||
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
|
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
|
||||||
"volcengine", "vllm", "qwen", "mistral":
|
"volcengine", "vllm", "qwen", "mistral", "opencode":
|
||||||
// All other OpenAI-compatible HTTP providers
|
// All other OpenAI-compatible HTTP providers
|
||||||
if cfg.APIKey == "" && cfg.APIBase == "" {
|
if cfg.APIKey == "" && cfg.APIBase == "" {
|
||||||
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
|
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
|
||||||
|
|
@ -206,6 +206,8 @@ func getDefaultAPIBase(protocol string) string {
|
||||||
return "http://localhost:8000/v1"
|
return "http://localhost:8000/v1"
|
||||||
case "mistral":
|
case "mistral":
|
||||||
return "https://api.mistral.ai/v1"
|
return "https://api.mistral.ai/v1"
|
||||||
|
case "opencode":
|
||||||
|
return "https://opencode.ai/zen/v1"
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,10 @@ func (p *Provider) Chat(
|
||||||
if p.apiKey != "" {
|
if p.apiKey != "" {
|
||||||
req.Header.Set("Authorization", "Bearer "+p.apiKey)
|
req.Header.Set("Authorization", "Bearer "+p.apiKey)
|
||||||
}
|
}
|
||||||
|
// Kimi Code API requires a coding agent User-Agent
|
||||||
|
if strings.Contains(p.apiBase, "api.kimi.com") {
|
||||||
|
req.Header.Set("User-Agent", "KimiCLI/0.77")
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := p.httpClient.Do(req)
|
resp, err := p.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue