Files
picoclaw/pkg/config/config_old.go
T
Cytown 667fc85d54 refactor(config): make config.Channel to multiple instance support
add new field type to Channel struct
config.channels refactor to channel_list
update config version to 3
update the docs
2026-04-13 22:21:21 +08:00

624 lines
16 KiB
Go

// PicoClaw - Ultra-lightweight personal AI agent
// License: MIT
//
// Copyright (c) 2026 PicoClaw contributors
package config
import "strings"
// isProvidersMapEmpty checks if a providers map has any non-empty provider configurations.
func isProvidersMapEmpty(providers map[string]any) bool {
for _, prov := range providers {
if provMap, ok := prov.(map[string]any); ok {
if apiKey, ok := provMap["api_key"]; ok && apiKey != "" {
return false
}
if apiBase, ok := provMap["api_base"]; ok && apiBase != "" {
return false
}
if connectMode, ok := provMap["connect_mode"]; ok && connectMode != "" {
return false
}
if authMethod, ok := provMap["auth_method"]; ok && authMethod != "" {
return false
}
}
}
return true
}
// v0ProvidersMapToModelList converts a V0 providers map to a model_list slice.
func v0ProvidersMapToModelList(providers map[string]any, userProvider, userModel string) []any {
// providerMigration defines migration rules for a provider
type providerMigration struct {
jsonKeys []string
protocol string
defModel string
extractFn func(prov map[string]any) map[string]any
}
migrations := []providerMigration{
{
jsonKeys: []string{"openai", "gpt"},
protocol: "openai",
defModel: "openai/gpt-5.4",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
if v, ok := prov["auth_method"]; ok && v != "" {
entry["auth_method"] = v
}
if v, ok := prov["web_search"]; ok && v != false {
entry["web_search"] = v
}
return entry
},
},
{
jsonKeys: []string{"anthropic", "claude"},
protocol: "anthropic",
defModel: "anthropic/claude-sonnet-4.6",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
if v, ok := prov["auth_method"]; ok && v != "" {
entry["auth_method"] = v
}
return entry
},
},
{
jsonKeys: []string{"litellm"},
protocol: "litellm",
defModel: "litellm/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"openrouter"},
protocol: "openrouter",
defModel: "openrouter/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"groq"},
protocol: "groq",
defModel: "groq/llama-3.1-70b-versatile",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"zhipu", "glm"},
protocol: "zhipu",
defModel: "zhipu/glm-4",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"vllm"},
protocol: "vllm",
defModel: "vllm/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"gemini", "google"},
protocol: "gemini",
defModel: "gemini/gemini-pro",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"nvidia"},
protocol: "nvidia",
defModel: "nvidia/meta/llama-3.1-8b-instruct",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"ollama"},
protocol: "ollama",
defModel: "ollama/llama3",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"moonshot", "kimi"},
protocol: "moonshot",
defModel: "moonshot/kimi",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"shengsuanyun"},
protocol: "shengsuanyun",
defModel: "shengsuanyun/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"deepseek"},
protocol: "deepseek",
defModel: "deepseek/deepseek-chat",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"cerebras"},
protocol: "cerebras",
defModel: "cerebras/llama-3.3-70b",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"vivgrid"},
protocol: "vivgrid",
defModel: "vivgrid/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"volcengine", "doubao"},
protocol: "volcengine",
defModel: "volcengine/doubao-pro",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"github_copilot", "copilot"},
protocol: "github-copilot",
defModel: "github-copilot/gpt-5.4",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["connect_mode"]; ok && v != "" {
entry["connect_mode"] = v
}
return entry
},
},
{
jsonKeys: []string{"antigravity"},
protocol: "antigravity",
defModel: "antigravity/gemini-2.0-flash",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["auth_method"]; ok && v != "" {
entry["auth_method"] = v
}
return entry
},
},
{
jsonKeys: []string{"qwen", "tongyi"},
protocol: "qwen",
defModel: "qwen/qwen-max",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"mistral"},
protocol: "mistral",
defModel: "mistral/mistral-small-latest",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"avian"},
protocol: "avian",
defModel: "avian/deepseek/deepseek-v3.2",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"minimax"},
protocol: "minimax",
defModel: "minimax/minimax",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"longcat"},
protocol: "longcat",
defModel: "longcat/LongCat-Flash-Thinking",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"modelscope"},
protocol: "modelscope",
defModel: "modelscope/Qwen/Qwen3-235B-A22B-Instruct-2507",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
{
jsonKeys: []string{"novita"},
protocol: "novita",
defModel: "novita/auto",
extractFn: func(prov map[string]any) map[string]any {
entry := make(map[string]any)
if v, ok := prov["api_key"]; ok && v != "" {
entry["api_key"] = v
}
if v, ok := prov["api_base"]; ok && v != "" {
entry["api_base"] = v
}
if v, ok := prov["proxy"]; ok && v != "" {
entry["proxy"] = v
}
if v, ok := prov["request_timeout"]; ok && v != nil {
entry["request_timeout"] = v
}
return entry
},
},
}
// We need access to agents.defaults for user provider/model, but we only have providers map
// This function is called with just the providers map, so we can't access agents.defaults
// The caller (migrateV0ToV1) would need to pass this information if needed
// For now, we skip the user provider/model matching
var result []any
for _, migration := range migrations {
// Find the provider in the providers map
var provData map[string]any
found := false
for _, key := range migration.jsonKeys {
if v, ok := providers[key]; ok {
if provMap, ok := v.(map[string]any); ok {
provData = provMap
found = true
break
}
}
}
if !found {
continue
}
// Extract fields using the extraction function
entry := migration.extractFn(provData)
if len(entry) == 0 {
continue
}
// Add model_name and model
entry["model_name"] = migration.jsonKeys[0]
// Use the user's model if the provider matches, otherwise use the default
modelToUse := migration.defModel
if userProvider != "" && userModel != "" {
for _, key := range migration.jsonKeys {
if userProvider == key {
// Build the model string with protocol prefix if needed
if !strings.Contains(userModel, "/") {
modelToUse = migration.protocol + "/" + userModel
} else {
modelToUse = userModel
}
break
}
}
}
entry["model"] = modelToUse
result = append(result, entry)
}
return result
}