322 lines
9.4 KiB
Go
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"
|
|
}
|
|
|