配置 (Config) 包提供了 YAML 配置文件加载、环境变量展开、配置合并和验证功能。
import "github.com/astercloud/aster/pkg/config"
配置加载器。
创建配置加载器。
func NewLoader(opts ...LoaderOption) *Loader
参数:
opts - 加载器选项返回:
*Loader - 加载器实例示例:
loader := config.NewLoader()
// 带选项
loader := config.NewLoader(
config.WithEnvPrefix("APP_"),
config.WithVariables(map[string]string{
"VERSION": "1.0.0",
}),
)
加载 Agent 配置文件。
func (l *Loader) LoadAgentConfig(path string) (*types.AgentConfig, error)
参数:
path - 配置文件路径返回:
*types.AgentConfig - Agent 配置error - 错误信息示例:
config, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
return err
}
加载模型配置文件。
func (l *Loader) LoadModelConfig(path string) (*types.ModelConfig, error)
参数:
path - 配置文件路径返回:
*types.ModelConfig - 模型配置error - 错误信息示例:
modelConfig, err := loader.LoadModelConfig("model.yaml")
if err != nil {
return err
}
从字符串加载配置。
func (l *Loader) LoadFromString(content string, target any) error
参数:
content - YAML 内容target - 目标结构体指针返回:
error - 错误信息示例:
yamlContent := `
template_id: "test-agent"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
`
var config types.AgentConfig
err := loader.LoadFromString(yamlContent, &config)
启用或禁用环境变量展开。
func WithEnvExpansion(enabled bool) LoaderOption
参数:
enabled - 是否启用(默认为 true)示例:
loader := config.NewLoader(
config.WithEnvExpansion(false), // 禁用环境变量展开
)
设置环境变量前缀。
func WithEnvPrefix(prefix string) LoaderOption
参数:
prefix - 环境变量前缀示例:
loader := config.NewLoader(
config.WithEnvPrefix("APP_"),
)
// 配置文件中 ${API_KEY} 会查找 APP_API_KEY 环境变量
提供自定义变量。
func WithVariables(vars map[string]string) LoaderOption
参数:
vars - 变量映射示例:
loader := config.NewLoader(
config.WithVariables(map[string]string{
"ENVIRONMENT": "production",
"VERSION": "1.0.0",
"REGION": "us-west-2",
}),
)
合并多个配置。
func MergeConfigs(base *types.AgentConfig, overlays ...*types.AgentConfig) *types.AgentConfig
参数:
base - 基础配置overlays - 要合并的配置列表返回:
*types.AgentConfig - 合并后的配置说明:
示例:
baseConfig, _ := loader.LoadAgentConfig("base.yaml")
prodConfig, _ := loader.LoadAgentConfig("production.yaml")
// 合并配置
finalConfig := config.MergeConfigs(baseConfig, prodConfig)
// 多层合并
finalConfig := config.MergeConfigs(
baseConfig,
envConfig,
userConfig,
)
获取配置目录。
func ConfigDir() string
返回:
string - 配置目录路径(~/.config/aster/)示例:
configDir := config.ConfigDir()
// 返回: /Users/username/.config/aster/
获取数据目录。
func DataDir() string
返回:
string - 数据目录路径(~/.local/share/aster/)获取日志目录。
func LogDir() string
返回:
string - 日志目录路径(~/.local/share/aster/logs/)获取缓存目录。
func CacheDir() string
返回:
string - 缓存目录路径(~/.cache/aster/)获取数据库文件路径。
func DatabaseFile() string
返回:
string - 数据库文件路径获取项目配置文件路径。
func ProjectConfigFile() string
返回:
string - 项目配置文件路径(./.aster/config.yaml)解析配置文件路径。
func ResolveConfigFile(filename string) string
参数:
filename - 配置文件名返回:
string - 解析后的完整路径说明: 按以下顺序查找文件:
示例:
configPath := config.ResolveConfigFile("agent.yaml")
// 查找顺序:
// 1. ./agent.yaml
// 2. ./.aster/agent.yaml
// 3. ~/.config/aster/agent.yaml
确保目录存在。
func EnsureDir(dir string) error
参数:
dir - 目录路径返回:
error - 错误信息示例:
err := config.EnsureDir(config.DataDir())
if err != nil {
return err
}
配置文件中支持以下环境变量语法:
# ${VAR} 语法
api_key: "${API_KEY}"
# $VAR 语法
api_key: "$API_KEY"
# 如果变量不存在,使用默认值
api_key: "${API_KEY:-default-key}"
model: "${MODEL_NAME:-claude-3-5-sonnet-20241022}"
# 如果变量不存在,报错
api_key: "${API_KEY:?API key is required}"
database_url: "${DATABASE_URL:?Database URL must be set}"
# 在字符串中使用变量
base_url: "https://${API_HOST:-api.example.com}/v1"
connection_string: "postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
配置加载时会自动验证以下内容:
template_id 必需model_config:
provider 必需model 必需multitenancy:
org_id 或 tenant_idprovider 必需model 必需package main
import (
"log"
"github.com/astercloud/aster/pkg/agent"
"github.com/astercloud/aster/pkg/config"
)
func main() {
// 创建加载器
loader := config.NewLoader()
// 加载配置
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
log.Fatalf("加载配置失败: %v", err)
}
// 创建 Agent
agent, err := agent.NewAgent(agentConfig)
if err != nil {
log.Fatalf("创建 Agent 失败: %v", err)
}
// 使用 Agent
// ...
}
package main
import (
"log"
"os"
"github.com/astercloud/aster/pkg/config"
)
func main() {
loader := config.NewLoader()
// 加载基础配置
baseConfig, err := loader.LoadAgentConfig("config/base.yaml")
if err != nil {
log.Fatalf("加载基础配置失败: %v", err)
}
// 根据环境加载对应配置
env := os.Getenv("ENVIRONMENT")
if env == "" {
env = "development"
}
envConfigPath := fmt.Sprintf("config/%s.yaml", env)
envConfig, err := loader.LoadAgentConfig(envConfigPath)
if err != nil {
log.Fatalf("加载环境配置失败: %v", err)
}
// 合并配置
finalConfig := config.MergeConfigs(baseConfig, envConfig)
// 创建 Agent
agent, err := agent.NewAgent(finalConfig)
if err != nil {
log.Fatalf("创建 Agent 失败: %v", err)
}
}
package main
import (
"log"
"github.com/astercloud/aster/pkg/config"
)
func main() {
// 创建带自定义变量的加载器
loader := config.NewLoader(
config.WithEnvPrefix("APP_"),
config.WithVariables(map[string]string{
"VERSION": "1.0.0",
"ENVIRONMENT": "production",
"REGION": "us-west-2",
}),
)
// 加载配置
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
log.Fatalf("加载配置失败: %v", err)
}
log.Printf("加载配置成功: %s", agentConfig.TemplateID)
}
package main
import (
"log"
"github.com/astercloud/aster/pkg/config"
"github.com/astercloud/aster/pkg/types"
)
func main() {
loader := config.NewLoader()
configYAML := `
template_id: "dynamic-agent"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
api_key: "${ANTHROPIC_API_KEY}"
tools:
- "read_file"
- "write_file"
`
var agentConfig types.AgentConfig
err := loader.LoadFromString(configYAML, &agentConfig)
if err != nil {
log.Fatalf("加载配置失败: %v", err)
}
log.Printf("模板 ID: %s", agentConfig.TemplateID)
log.Printf("工具数量: %d", len(agentConfig.Tools))
}
package main
import (
"log"
"github.com/astercloud/aster/pkg/config"
)
func main() {
loader := config.NewLoader()
// 加载配置
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
// 检查不同类型的错误
if os.IsNotExist(err) {
log.Fatal("配置文件不存在")
}
if strings.Contains(err.Error(), "yaml") {
log.Fatal("YAML 语法错误:", err)
}
if strings.Contains(err.Error(), "validate") {
log.Fatal("配置验证失败:", err)
}
log.Fatalf("加载配置失败: %v", err)
}
log.Println("配置验证通过")
}
# base.yaml
template_id: "general-assistant"
template_version: "1.0.0"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
tools:
- "read_file"
- "write_file"
metadata:
version: "1.0.0"
# production.yaml
model_config:
api_key: "${ANTHROPIC_API_KEY:?API key is required}"
base_url: "${API_BASE_URL:-https://api.anthropic.com}"
execution_mode: "streaming"
middlewares:
- "logging"
- "rate_limit"
- "auth"
middleware_config:
rate_limit:
requests_per_minute: 60
logging:
level: "info"
format: "json"
metadata:
environment: "production"
region: "${AWS_REGION:-us-west-2}"
# development.yaml
model_config:
api_key: "${ANTHROPIC_API_KEY}"
tools:
- "read_file"
- "write_file"
- "bash"
- "debug_tool"
middlewares:
- "logging"
middleware_config:
logging:
level: "debug"
format: "text"
metadata:
environment: "development"
debug: true
// 文件不存在
config, err := loader.LoadAgentConfig("nonexistent.yaml")
// err: open nonexistent.yaml: no such file or directory
// YAML 语法错误
// err: yaml: line 5: mapping values are not allowed in this context
// 验证错误
// err: validate config: template_id is required
// 环境变量未设置
// err: required environment variable API_KEY is not set
config, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
switch {
case os.IsNotExist(err):
log.Fatal("配置文件不存在")
case strings.Contains(err.Error(), "yaml"):
log.Fatal("YAML 语法错误:", err)
case strings.Contains(err.Error(), "validate"):
log.Fatal("配置验证失败:", err)
case strings.Contains(err.Error(), "required"):
log.Fatal("缺少必需的环境变量:", err)
default:
log.Fatal("加载配置失败:", err)
}
}