Files
clawgo/pkg/config/config.go

289 lines
7.4 KiB
Go

package config
import (
"encoding/json"
"os"
"path/filepath"
"sync"
"github.com/caarlos0/env/v11"
)
type Config struct {
Agents AgentsConfig `json:"agents"`
Channels ChannelsConfig `json:"channels"`
Providers ProvidersConfig `json:"providers"`
Gateway GatewayConfig `json:"gateway"`
Tools ToolsConfig `json:"tools"`
mu sync.RWMutex
}
type AgentsConfig struct {
Defaults AgentDefaults `json:"defaults"`
}
type AgentDefaults struct {
Workspace string `json:"workspace" env:"CLAWGO_AGENTS_DEFAULTS_WORKSPACE"`
Model string `json:"model" env:"CLAWGO_AGENTS_DEFAULTS_MODEL"`
MaxTokens int `json:"max_tokens" env:"CLAWGO_AGENTS_DEFAULTS_MAX_TOKENS"`
Temperature float64 `json:"temperature" env:"CLAWGO_AGENTS_DEFAULTS_TEMPERATURE"`
MaxToolIterations int `json:"max_tool_iterations" env:"CLAWGO_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
}
type ChannelsConfig struct {
WhatsApp WhatsAppConfig `json:"whatsapp"`
Telegram TelegramConfig `json:"telegram"`
Feishu FeishuConfig `json:"feishu"`
Discord DiscordConfig `json:"discord"`
MaixCam MaixCamConfig `json:"maixcam"`
QQ QQConfig `json:"qq"`
DingTalk DingTalkConfig `json:"dingtalk"`
}
type WhatsAppConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_WHATSAPP_ENABLED"`
BridgeURL string `json:"bridge_url" env:"CLAWGO_CHANNELS_WHATSAPP_BRIDGE_URL"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_WHATSAPP_ALLOW_FROM"`
}
type TelegramConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_TELEGRAM_ENABLED"`
Token string `json:"token" env:"CLAWGO_CHANNELS_TELEGRAM_TOKEN"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_TELEGRAM_ALLOW_FROM"`
}
type FeishuConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_FEISHU_ENABLED"`
AppID string `json:"app_id" env:"CLAWGO_CHANNELS_FEISHU_APP_ID"`
AppSecret string `json:"app_secret" env:"CLAWGO_CHANNELS_FEISHU_APP_SECRET"`
EncryptKey string `json:"encrypt_key" env:"CLAWGO_CHANNELS_FEISHU_ENCRYPT_KEY"`
VerificationToken string `json:"verification_token" env:"CLAWGO_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_FEISHU_ALLOW_FROM"`
}
type DiscordConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_DISCORD_ENABLED"`
Token string `json:"token" env:"CLAWGO_CHANNELS_DISCORD_TOKEN"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_DISCORD_ALLOW_FROM"`
}
type MaixCamConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_MAIXCAM_ENABLED"`
Host string `json:"host" env:"CLAWGO_CHANNELS_MAIXCAM_HOST"`
Port int `json:"port" env:"CLAWGO_CHANNELS_MAIXCAM_PORT"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_MAIXCAM_ALLOW_FROM"`
}
type QQConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_QQ_ENABLED"`
AppID string `json:"app_id" env:"CLAWGO_CHANNELS_QQ_APP_ID"`
AppSecret string `json:"app_secret" env:"CLAWGO_CHANNELS_QQ_APP_SECRET"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_QQ_ALLOW_FROM"`
}
type DingTalkConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_DINGTALK_ENABLED"`
ClientID string `json:"client_id" env:"CLAWGO_CHANNELS_DINGTALK_CLIENT_ID"`
ClientSecret string `json:"client_secret" env:"CLAWGO_CHANNELS_DINGTALK_CLIENT_SECRET"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_DINGTALK_ALLOW_FROM"`
}
type ProvidersConfig struct {
Proxy ProviderConfig `json:"proxy"`
}
type ProviderConfig struct {
APIKey string `json:"api_key" env:"CLAWGO_PROVIDERS_{{.Name}}_API_KEY"`
APIBase string `json:"api_base" env:"CLAWGO_PROVIDERS_{{.Name}}_API_BASE"`
Auth string `json:"auth" env:"CLAWGO_PROVIDERS_{{.Name}}_AUTH"`
}
type GatewayConfig struct {
Host string `json:"host" env:"CLAWGO_GATEWAY_HOST"`
Port int `json:"port" env:"CLAWGO_GATEWAY_PORT"`
}
type WebSearchConfig struct {
APIKey string `json:"api_key" env:"CLAWGO_TOOLS_WEB_SEARCH_API_KEY"`
MaxResults int `json:"max_results" env:"CLAWGO_TOOLS_WEB_SEARCH_MAX_RESULTS"`
}
type WebToolsConfig struct {
Search WebSearchConfig `json:"search"`
}
type ToolsConfig struct {
Web WebToolsConfig `json:"web"`
}
var (
isDebug bool
muDebug sync.RWMutex
)
func SetDebugMode(debug bool) {
muDebug.Lock()
defer muDebug.Unlock()
isDebug = debug
}
func IsDebugMode() bool {
muDebug.RLock()
defer muDebug.RUnlock()
return isDebug
}
func GetConfigDir() string {
if IsDebugMode() {
return ".clawgo"
}
home, _ := os.UserHomeDir()
return filepath.Join(home, ".clawgo")
}
func DefaultConfig() *Config {
configDir := GetConfigDir()
return &Config{
Agents: AgentsConfig{
Defaults: AgentDefaults{
Workspace: filepath.Join(configDir, "workspace"),
Model: "glm-4.7",
MaxTokens: 8192,
Temperature: 0.7,
MaxToolIterations: 20,
},
},
Channels: ChannelsConfig{
WhatsApp: WhatsAppConfig{
Enabled: false,
BridgeURL: "ws://localhost:3001",
AllowFrom: []string{},
},
Telegram: TelegramConfig{
Enabled: false,
Token: "",
AllowFrom: []string{},
},
Feishu: FeishuConfig{
Enabled: false,
AppID: "",
AppSecret: "",
EncryptKey: "",
VerificationToken: "",
AllowFrom: []string{},
},
Discord: DiscordConfig{
Enabled: false,
Token: "",
AllowFrom: []string{},
},
MaixCam: MaixCamConfig{
Enabled: false,
Host: "0.0.0.0",
Port: 18790,
AllowFrom: []string{},
},
QQ: QQConfig{
Enabled: false,
AppID: "",
AppSecret: "",
AllowFrom: []string{},
},
DingTalk: DingTalkConfig{
Enabled: false,
ClientID: "",
ClientSecret: "",
AllowFrom: []string{},
},
},
Providers: ProvidersConfig{
Proxy: ProviderConfig{
APIBase: "http://localhost:8080/v1",
},
},
Gateway: GatewayConfig{
Host: "0.0.0.0",
Port: 18790,
},
Tools: ToolsConfig{
Web: WebToolsConfig{
Search: WebSearchConfig{
APIKey: "",
MaxResults: 5,
},
},
},
}
}
func LoadConfig(path string) (*Config, error) {
cfg := DefaultConfig()
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return cfg, nil
}
return nil, err
}
if err := json.Unmarshal(data, cfg); err != nil {
return nil, err
}
if err := env.Parse(cfg); err != nil {
return nil, err
}
return cfg, nil
}
func SaveConfig(path string, cfg *Config) error {
cfg.mu.RLock()
defer cfg.mu.RUnlock()
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
func (c *Config) WorkspacePath() string {
c.mu.RLock()
defer c.mu.RUnlock()
return expandHome(c.Agents.Defaults.Workspace)
}
func (c *Config) GetAPIKey() string {
c.mu.RLock()
defer c.mu.RUnlock()
return c.Providers.Proxy.APIKey
}
func (c *Config) GetAPIBase() string {
c.mu.RLock()
defer c.mu.RUnlock()
return c.Providers.Proxy.APIBase
}
func expandHome(path string) string {
if path == "" {
return path
}
if path[0] == '~' {
home, _ := os.UserHomeDir()
if len(path) > 1 && path[1] == '/' {
return home + path[1:]
}
return home
}
return path
}