diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..49c4407e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module chat-agent-system + +go 1.27.1 diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 00000000..fd9447fa --- /dev/null +++ b/internal/config/config.go @@ -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 +} diff --git a/internal/config/config_test.go b/internal/config/config_test.go new file mode 100644 index 00000000..bf369f19 --- /dev/null +++ b/internal/config/config_test.go @@ -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) + } +}