chore(config): initialize go module and configuration loader

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WeiCHEN
2026-09-13 02:50:18 +00:00
committed by weichen
co-authored by Cursor
parent 0832d7caa9
commit 68d58df38f
3 changed files with 162 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
module chat-agent-system
go 1.27.1
+114
View File
@@ -0,0 +1,114 @@
package config
import (
"bufio"
"os"
"strconv"
"strings"
"time"
)
type Config struct {
Env string `json:"env"`
DataDir string `json:"data_dir"`
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"`
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"`
}
func Load(path string) (*Config, error) {
cfg := &Config{
Env: "dev",
DataDir: "./data/dev",
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: "anthropic",
PiAgentModel: "claude-3-7-sonnet",
KbDbHost: "127.0.0.1",
KbDbPort: 55432,
KbDbUser: "regkb",
KbDbPassword: "shared_kb_secret_pass",
KbDbName: "regulations",
}
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 "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 "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
}
}
}
return cfg, nil
}
+45
View File
@@ -0,0 +1,45 @@
package config_test
import (
"os"
"path/filepath"
"testing"
"time"
"chat-agent-system/internal/config"
)
func TestConfigLoadDefaultsAndFile(t *testing.T) {
tmpDir := t.TempDir()
envPath := filepath.Join(tmpDir, ".env")
envContent := `ENV=dev
DATA_DIR=./data/test_data
AGENT_BACKEND=pi-agent
AGENT_TIMEOUT=15m
KB_DB_PORT=55432
`
if err := os.WriteFile(envPath, []byte(envContent), 0o644); err != nil {
t.Fatalf("failed to write test env: %v", err)
}
cfg, err := config.Load(envPath)
if err != nil {
t.Fatalf("unexpected error loading config: %v", err)
}
if cfg.Env != "dev" {
t.Errorf("expected Env 'dev', got %q", cfg.Env)
}
if cfg.DataDir != "./data/test_data" {
t.Errorf("expected DataDir './data/test_data', got %q", cfg.DataDir)
}
if cfg.AgentBackend != "pi-agent" {
t.Errorf("expected AgentBackend 'pi-agent', got %q", cfg.AgentBackend)
}
if cfg.AgentTimeout != 15*time.Minute {
t.Errorf("expected AgentTimeout 15m, got %v", cfg.AgentTimeout)
}
if cfg.KbDbPort != 55432 {
t.Errorf("expected KbDbPort 55432, got %d", cfg.KbDbPort)
}
}