picoclaw/pkg/providers/builtin_resolvers.go

343 lines
11 KiB
Go

package providers
import (
"github.com/sipeed/picoclaw/pkg/config"
)
func init() {
RegisterProvider("groq", groqResolver)
RegisterProvider("openai", openaiResolver)
RegisterProvider("gpt", openaiResolver)
RegisterProvider("anthropic", anthropicResolver)
RegisterProvider("claude", anthropicResolver)
RegisterProvider("openrouter", openrouterResolver)
RegisterProvider("litellm", litellmResolver)
RegisterProvider("zhipu", zhipuResolver)
RegisterProvider("glm", zhipuResolver)
RegisterProvider("gemini", geminiResolver)
RegisterProvider("google", geminiResolver)
RegisterProvider("vllm", vllmResolver)
RegisterProvider("shengsuanyun", shengsuanyunResolver)
RegisterProvider("nvidia", nvidiaResolver)
RegisterProvider("vivgrid", vivgridResolver)
RegisterProvider("deepseek", deepseekResolver)
RegisterProvider("avian", avianResolver)
RegisterProvider("mistral", mistralResolver)
RegisterProvider("minimax", minimaxResolver)
RegisterProvider("claude-cli", claudeCLIResolver)
RegisterProvider("claude-code", claudeCLIResolver)
RegisterProvider("claudecode", claudeCLIResolver)
RegisterProvider("codex-cli", codexCLIResolver)
RegisterProvider("codex-code", codexCLIResolver)
RegisterProvider("github_copilot", copilotResolver)
RegisterProvider("copilot", copilotResolver)
}
func groqResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Groq.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Groq.APIKey,
apiBase: cfg.Providers.Groq.APIBase,
proxy: cfg.Providers.Groq.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.groq.com/openai/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func openaiResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
enableWebSearch: cfg.Providers.OpenAI.WebSearch,
}
if cfg.Providers.OpenAI.AuthMethod == "codex-cli" {
sel.providerType = providerTypeCodexCLIToken
return sel, true, nil
}
if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" {
sel.providerType = providerTypeCodexAuth
return sel, true, nil
}
sel.apiKey = cfg.Providers.OpenAI.APIKey
sel.apiBase = cfg.Providers.OpenAI.APIBase
sel.proxy = cfg.Providers.OpenAI.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.openai.com/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func anthropicResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
}
if cfg.Providers.Anthropic.AuthMethod == "oauth" || cfg.Providers.Anthropic.AuthMethod == "token" {
sel.apiBase = cfg.Providers.Anthropic.APIBase
if sel.apiBase == "" {
sel.apiBase = defaultAnthropicAPIBase
}
sel.providerType = providerTypeClaudeAuth
return sel, true, nil
}
sel.apiKey = cfg.Providers.Anthropic.APIKey
sel.apiBase = cfg.Providers.Anthropic.APIBase
sel.proxy = cfg.Providers.Anthropic.Proxy
if sel.apiBase == "" {
sel.apiBase = defaultAnthropicAPIBase
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func openrouterResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.OpenRouter.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.OpenRouter.APIKey,
proxy: cfg.Providers.OpenRouter.Proxy,
apiBase: cfg.Providers.OpenRouter.APIBase,
}
if sel.apiBase == "" {
sel.apiBase = "https://openrouter.ai/api/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func litellmResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.LiteLLM.APIKey != "" || cfg.Providers.LiteLLM.APIBase != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.LiteLLM.APIKey,
apiBase: cfg.Providers.LiteLLM.APIBase,
proxy: cfg.Providers.LiteLLM.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "http://localhost:4000/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func zhipuResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Zhipu.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Zhipu.APIKey,
apiBase: cfg.Providers.Zhipu.APIBase,
proxy: cfg.Providers.Zhipu.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://open.bigmodel.cn/api/paas/v4"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func geminiResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Gemini.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Gemini.APIKey,
apiBase: cfg.Providers.Gemini.APIBase,
proxy: cfg.Providers.Gemini.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://generativelanguage.googleapis.com/v1beta"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func vllmResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.VLLM.APIBase != "" {
return providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.VLLM.APIKey,
apiBase: cfg.Providers.VLLM.APIBase,
proxy: cfg.Providers.VLLM.Proxy,
}, true, nil
}
return providerSelection{}, false, nil
}
func shengsuanyunResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.ShengSuanYun.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.ShengSuanYun.APIKey,
apiBase: cfg.Providers.ShengSuanYun.APIBase,
proxy: cfg.Providers.ShengSuanYun.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://router.shengsuanyun.com/api/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func nvidiaResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Nvidia.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Nvidia.APIKey,
apiBase: cfg.Providers.Nvidia.APIBase,
proxy: cfg.Providers.Nvidia.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://integrate.api.nvidia.com/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func vivgridResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Vivgrid.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Vivgrid.APIKey,
apiBase: cfg.Providers.Vivgrid.APIBase,
proxy: cfg.Providers.Vivgrid.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.vivgrid.com/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func claudeCLIResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
workspace := cfg.WorkspacePath()
if workspace == "" {
workspace = "."
}
return providerSelection{
providerType: providerTypeClaudeCLI,
model: model,
workspace: workspace,
}, true, nil
}
func codexCLIResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
workspace := cfg.WorkspacePath()
if workspace == "" {
workspace = "."
}
return providerSelection{
providerType: providerTypeCodexCLI,
model: model,
workspace: workspace,
}, true, nil
}
func deepseekResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.DeepSeek.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.DeepSeek.APIKey,
apiBase: cfg.Providers.DeepSeek.APIBase,
proxy: cfg.Providers.DeepSeek.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.deepseek.com/v1"
}
if model != "deepseek-chat" && model != "deepseek-reasoner" {
sel.model = "deepseek-chat"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func avianResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Avian.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Avian.APIKey,
apiBase: cfg.Providers.Avian.APIBase,
proxy: cfg.Providers.Avian.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.avian.io/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func mistralResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Mistral.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Mistral.APIKey,
apiBase: cfg.Providers.Mistral.APIBase,
proxy: cfg.Providers.Mistral.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.mistral.ai/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func minimaxResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
if cfg.Providers.Minimax.APIKey != "" {
sel := providerSelection{
providerType: providerTypeHTTPCompat,
model: model,
apiKey: cfg.Providers.Minimax.APIKey,
apiBase: cfg.Providers.Minimax.APIBase,
proxy: cfg.Providers.Minimax.Proxy,
}
if sel.apiBase == "" {
sel.apiBase = "https://api.minimaxi.com/v1"
}
return sel, true, nil
}
return providerSelection{}, false, nil
}
func copilotResolver(cfg *config.Config, name, model string) (providerSelection, bool, error) {
sel := providerSelection{
providerType: providerTypeGitHubCopilot,
model: model,
connectMode: cfg.Providers.GitHubCopilot.ConnectMode,
}
if cfg.Providers.GitHubCopilot.APIBase != "" {
sel.apiBase = cfg.Providers.GitHubCopilot.APIBase
} else {
sel.apiBase = "localhost:4321"
}
return sel, true, nil
}