Files
Agent-System/internal/config/config.go
T

322 lines
9.4 KiB
Go

package config
import (
"bufio"
"os"
"strconv"
"strings"
"time"
)
type Config struct {
Env string `json:"env"`
DataDir string `json:"data_dir"`
HTTPHost string `json:"http_host"`
HTTPPort int `json:"http_port"`
AgentBackend string `json:"agent_backend"`
AgentTimeout time.Duration `json:"agent_timeout"`
CursorAPIKey string `json:"cursor_api_key"`
CursorModel string `json:"cursor_model"`
CursorBin string `json:"cursor_bin"`
CursorBridgeBin string `json:"cursor_bridge_bin"`
PiAgentBin string `json:"pi_agent_bin"`
PiAgentBridgeBin string `json:"pi_agent_bridge_bin"`
PiAgentProvider string `json:"pi_agent_provider"`
PiAgentModel string `json:"pi_agent_model"`
PiAgentRunnerURL string `json:"pi_agent_runner_url"`
KbDbHost string `json:"kb_db_host"`
KbDbPort int `json:"kb_db_port"`
KbDbUser string `json:"kb_db_user"`
KbDbPassword string `json:"kb_db_password"`
KbDbName string `json:"kb_db_name"`
// 专属记忆与多级上下文数据库配置
ContextDbHost string `json:"context_db_host"`
ContextDbPort int `json:"context_db_port"`
ContextDbUser string `json:"context_db_user"`
ContextDbPassword string `json:"context_db_password"`
ContextDbName string `json:"context_db_name"`
// 向量化 Embedding 服务配置
EmbeddingEndpointURL string `json:"embedding_endpoint_url"`
EmbeddingProvider string `json:"embedding_provider"`
EmbeddingModel string `json:"embedding_model"`
EmbeddingAPIKey string `json:"embedding_api_key"`
// 语义重排 Reranker 服务配置
RerankerEndpointURL string `json:"reranker_endpoint_url"`
RerankerProvider string `json:"reranker_provider"`
RerankerModel string `json:"reranker_model"`
RerankerAPIKey string `json:"reranker_api_key"`
// 系统管理员与准入认证配置
AdminUsername string `json:"admin_username"`
AdminPassword string `json:"admin_password"`
AuthRegistrationEnabled bool `json:"auth_registration_enabled"`
AuthRequireApproval bool `json:"auth_require_approval"`
}
func Load(path string) (*Config, error) {
cfg := &Config{
Env: "dev",
DataDir: "./data/dev",
HTTPHost: "127.0.0.1",
HTTPPort: 8080,
AgentBackend: "pi-agent",
AgentTimeout: 30 * time.Minute,
CursorModel: "auto",
CursorBin: "/usr/local/bin/cursor",
CursorBridgeBin: "tools/cursor-bridge/index.mjs",
PiAgentBin: "/opt/homebrew/bin/pi",
PiAgentBridgeBin: "tools/pi-bridge/index.mjs",
PiAgentProvider: "cc-switch-kimi-for-coding",
PiAgentModel: "kimi-for-coding",
KbDbHost: "127.0.0.1",
KbDbPort: 5432,
KbDbUser: "regkb",
KbDbPassword: "shared_kb_secret_pass",
KbDbName: "regulations",
ContextDbHost: "127.0.0.1",
ContextDbPort: 5433,
ContextDbUser: "app",
ContextDbPassword: "dev_secret_db_pass",
ContextDbName: "agent_system_dev",
EmbeddingEndpointURL: "https://www.dmxapi.cn/v1/embeddings",
EmbeddingProvider: "openai_compatible",
EmbeddingModel: "bge-m3",
EmbeddingAPIKey: "",
RerankerEndpointURL: "https://www.dmxapi.cn/v1/rerank",
RerankerProvider: "openai_compatible",
RerankerModel: "bge-reranker-v2-m3-free",
RerankerAPIKey: "",
AdminUsername: "admin",
AdminPassword: "admin-secret-password-123",
AuthRegistrationEnabled: true,
AuthRequireApproval: false,
}
if path == "" {
if _, err := os.Stat("configs/.env.dev"); err == nil {
path = "configs/.env.dev"
} else if _, err := os.Stat(".env"); err == nil {
path = ".env"
}
}
f, err := os.Open(path)
if err == nil {
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
val := strings.TrimSpace(parts[1])
if commentIdx := strings.Index(val, " #"); commentIdx != -1 {
val = strings.TrimSpace(val[:commentIdx])
}
switch key {
case "ENV":
cfg.Env = val
case "DATA_DIR":
cfg.DataDir = val
case "APP_PUBLISH_HOST", "HTTP_HOST":
cfg.HTTPHost = val
case "HTTP_PORT":
if p, err := strconv.Atoi(val); err == nil {
cfg.HTTPPort = p
}
case "AGENT_BACKEND":
cfg.AgentBackend = val
case "AGENT_TIMEOUT":
if d, err := time.ParseDuration(val); err == nil {
cfg.AgentTimeout = d
}
case "CURSOR_API_KEY":
cfg.CursorAPIKey = val
case "CURSOR_MODEL":
cfg.CursorModel = val
case "CURSOR_BIN":
cfg.CursorBin = val
case "CURSOR_BRIDGE_BIN":
cfg.CursorBridgeBin = val
case "PI_AGENT_BIN":
cfg.PiAgentBin = val
case "PI_AGENT_BRIDGE_BIN":
cfg.PiAgentBridgeBin = val
case "PI_AGENT_PROVIDER":
cfg.PiAgentProvider = val
case "PI_AGENT_MODEL":
cfg.PiAgentModel = val
case "PI_AGENT_RUNNER_URL":
cfg.PiAgentRunnerURL = val
case "KB_DB_HOST":
cfg.KbDbHost = val
case "KB_DB_PORT":
if p, err := strconv.Atoi(val); err == nil {
cfg.KbDbPort = p
}
case "KB_DB_USER":
cfg.KbDbUser = val
case "KB_DB_PASSWORD":
cfg.KbDbPassword = val
case "KB_DB_NAME":
cfg.KbDbName = val
case "CONTEXT_DB_HOST":
cfg.ContextDbHost = val
case "CONTEXT_DB_PORT":
if p, err := strconv.Atoi(val); err == nil {
cfg.ContextDbPort = p
}
case "CONTEXT_DB_USER":
cfg.ContextDbUser = val
case "CONTEXT_DB_PASSWORD":
cfg.ContextDbPassword = val
case "CONTEXT_DB_NAME":
cfg.ContextDbName = val
case "EMBEDDING_ENDPOINT_URL":
cfg.EmbeddingEndpointURL = val
case "EMBEDDING_PROVIDER":
cfg.EmbeddingProvider = val
case "EMBEDDING_MODEL":
cfg.EmbeddingModel = val
case "EMBEDDING_API_KEY":
cfg.EmbeddingAPIKey = val
case "RERANKER_ENDPOINT_URL":
cfg.RerankerEndpointURL = val
case "RERANKER_PROVIDER":
cfg.RerankerProvider = val
case "RERANKER_MODEL":
cfg.RerankerModel = val
case "RERANKER_API_KEY":
cfg.RerankerAPIKey = val
case "ADMIN_USERNAME":
cfg.AdminUsername = val
case "ADMIN_PASSWORD":
cfg.AdminPassword = val
case "AUTH_REGISTRATION_ENABLED":
cfg.AuthRegistrationEnabled = val == "true" || val == "1"
case "AUTH_REQUIRE_APPROVAL":
cfg.AuthRequireApproval = val == "true" || val == "1"
}
}
}
// 允许系统环境变量覆盖
if v := os.Getenv("ENV"); v != "" {
cfg.Env = v
}
if v := os.Getenv("DATA_DIR"); v != "" {
cfg.DataDir = v
}
if v := os.Getenv("HTTP_HOST"); v != "" {
cfg.HTTPHost = v
} else if v := os.Getenv("APP_PUBLISH_HOST"); v != "" {
cfg.HTTPHost = v
}
if v := os.Getenv("HTTP_PORT"); v != "" {
if p, err := strconv.Atoi(v); err == nil {
cfg.HTTPPort = p
}
}
if v := os.Getenv("AGENT_BACKEND"); v != "" {
cfg.AgentBackend = v
}
if v := os.Getenv("PI_AGENT_BIN"); v != "" {
cfg.PiAgentBin = v
}
if v := os.Getenv("PI_AGENT_PROVIDER"); v != "" {
cfg.PiAgentProvider = v
}
if v := os.Getenv("PI_AGENT_MODEL"); v != "" {
cfg.PiAgentModel = v
}
if v := os.Getenv("KB_DB_HOST"); v != "" {
cfg.KbDbHost = v
}
if v := os.Getenv("KB_DB_PORT"); v != "" {
if p, err := strconv.Atoi(v); err == nil {
cfg.KbDbPort = p
}
}
if v := os.Getenv("KB_DB_USER"); v != "" {
cfg.KbDbUser = v
}
if v := os.Getenv("KB_DB_PASSWORD"); v != "" {
cfg.KbDbPassword = v
}
if v := os.Getenv("KB_DB_NAME"); v != "" {
cfg.KbDbName = v
}
if v := os.Getenv("CONTEXT_DB_HOST"); v != "" {
cfg.ContextDbHost = v
}
if v := os.Getenv("CONTEXT_DB_PORT"); v != "" {
if p, err := strconv.Atoi(v); err == nil {
cfg.ContextDbPort = p
}
}
if v := os.Getenv("CONTEXT_DB_USER"); v != "" {
cfg.ContextDbUser = v
}
if v := os.Getenv("CONTEXT_DB_PASSWORD"); v != "" {
cfg.ContextDbPassword = v
}
if v := os.Getenv("CONTEXT_DB_NAME"); v != "" {
cfg.ContextDbName = v
}
if v := os.Getenv("EMBEDDING_ENDPOINT_URL"); v != "" {
cfg.EmbeddingEndpointURL = v
}
if v := os.Getenv("EMBEDDING_API_KEY"); v != "" {
cfg.EmbeddingAPIKey = v
}
if v := os.Getenv("EMBEDDING_MODEL"); v != "" {
cfg.EmbeddingModel = v
}
if v := os.Getenv("RERANKER_ENDPOINT_URL"); v != "" {
cfg.RerankerEndpointURL = v
}
if v := os.Getenv("RERANKER_API_KEY"); v != "" {
cfg.RerankerAPIKey = v
}
if v := os.Getenv("RERANKER_MODEL"); v != "" {
cfg.RerankerModel = v
}
if v := os.Getenv("ADMIN_USERNAME"); v != "" {
cfg.AdminUsername = v
}
if v := os.Getenv("ADMIN_PASSWORD"); v != "" {
cfg.AdminPassword = v
}
if v := os.Getenv("AUTH_REGISTRATION_ENABLED"); v != "" {
cfg.AuthRegistrationEnabled = v == "true" || v == "1"
}
if v := os.Getenv("AUTH_REQUIRE_APPROVAL"); v != "" {
cfg.AuthRequireApproval = v == "true" || v == "1"
}
return cfg, nil
}
// KbDSN 返回 PostgreSQL 连接字符串
func (c *Config) KbDSN() string {
return "postgres://" + c.KbDbUser + ":" + c.KbDbPassword + "@" + c.KbDbHost + ":" + strconv.Itoa(c.KbDbPort) + "/" + c.KbDbName + "?sslmode=disable"
}
// ContextDSN 返回专属记忆与多级上下文 PostgreSQL 连接字符串
func (c *Config) ContextDSN() string {
return "postgres://" + c.ContextDbUser + ":" + c.ContextDbPassword + "@" + c.ContextDbHost + ":" + strconv.Itoa(c.ContextDbPort) + "/" + c.ContextDbName + "?sslmode=disable"
}