130 lines
3.8 KiB
Go
130 lines
3.8 KiB
Go
package config
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Config holds all runtime configuration for the GoClaw Gateway.
|
|
//
|
|
// LLM Provider selection (via LLM_BASE_URL env):
|
|
//
|
|
// Cloud (default): https://ollama.com/v1 — Ollama Cloud API (requires OLLAMA_API_KEY)
|
|
// OpenAI-compat: https://api.openai.com/v1 — OpenAI or any OpenAI-compatible endpoint
|
|
// Local GPU node: http://localhost:11434/v1 — Local Ollama (only on machines with GPU)
|
|
//
|
|
// To use a local Ollama instance on a GPU-equipped agent node, set:
|
|
//
|
|
// LLM_BASE_URL=http://<gpu-node-ip>:11434/v1
|
|
// LLM_API_KEY= # (empty for local Ollama)
|
|
type Config struct {
|
|
// Server
|
|
Port string
|
|
|
|
// LLM / Ollama Cloud
|
|
// LLM_BASE_URL — OpenAI-compatible base URL (without trailing slash, /v1 suffix included).
|
|
// Default: https://ollama.com/v1 (Ollama Cloud).
|
|
// For local GPU agents set LLM_BASE_URL=http://<host>:11434/v1
|
|
LLMBaseURL string
|
|
LLMAPIKey string
|
|
|
|
// Deprecated aliases kept for backward-compat (mapped to LLMBaseURL / LLMAPIKey)
|
|
OllamaBaseURL string
|
|
OllamaAPIKey string
|
|
|
|
// Database (MySQL/TiDB)
|
|
DatabaseURL string
|
|
|
|
// Project root (for file tools)
|
|
ProjectRoot string
|
|
|
|
// Gateway defaults
|
|
DefaultModel string
|
|
MaxToolIterations int
|
|
RequestTimeoutSecs int
|
|
}
|
|
|
|
func Load() *Config {
|
|
// Try to load .env from parent directory (project root) or current dir
|
|
_ = godotenv.Load("../.env")
|
|
_ = godotenv.Load(".env")
|
|
|
|
maxIter, _ := strconv.Atoi(getEnv("GATEWAY_MAX_TOOL_ITERATIONS", "10"))
|
|
timeout, _ := strconv.Atoi(getEnv("GATEWAY_REQUEST_TIMEOUT_SECS", "120"))
|
|
|
|
// Resolve LLM base URL — priority: LLM_BASE_URL > OLLAMA_BASE_URL > default cloud
|
|
rawLLMURL := getEnvFirst(
|
|
"LLM_BASE_URL", // preferred new name
|
|
"OLLAMA_BASE_URL", // legacy alias
|
|
)
|
|
if rawLLMURL == "" {
|
|
// Default: Ollama Cloud (OpenAI-compatible, requires OLLAMA_API_KEY)
|
|
rawLLMURL = "https://ollama.com/v1"
|
|
}
|
|
// Normalise: strip trailing slash, ensure /v1 suffix for bare Ollama hosts
|
|
llmBaseURL := normaliseLLMURL(rawLLMURL)
|
|
|
|
// Resolve API key — priority: LLM_API_KEY > OLLAMA_API_KEY
|
|
llmAPIKey := getEnvFirst("LLM_API_KEY", "OLLAMA_API_KEY")
|
|
|
|
cfg := &Config{
|
|
Port: getEnv("GATEWAY_PORT", "18789"),
|
|
LLMBaseURL: llmBaseURL,
|
|
LLMAPIKey: llmAPIKey,
|
|
OllamaBaseURL: llmBaseURL, // backward-compat alias
|
|
OllamaAPIKey: llmAPIKey, // backward-compat alias
|
|
DatabaseURL: getEnv("DATABASE_URL", ""),
|
|
ProjectRoot: getEnv("PROJECT_ROOT", "/home/ubuntu/goclaw-control-center"),
|
|
DefaultModel: getEnv("DEFAULT_MODEL", "qwen2.5:7b"),
|
|
MaxToolIterations: maxIter,
|
|
RequestTimeoutSecs: timeout,
|
|
}
|
|
|
|
if cfg.LLMAPIKey == "" {
|
|
log.Println("[Config] WARNING: LLM_API_KEY / OLLAMA_API_KEY is not set — cloud API calls will fail")
|
|
}
|
|
if cfg.DatabaseURL == "" {
|
|
log.Println("[Config] WARNING: DATABASE_URL is not set — agent config will use defaults")
|
|
}
|
|
|
|
log.Printf("[Config] LLM endpoint: %s", cfg.LLMBaseURL)
|
|
|
|
return cfg
|
|
}
|
|
|
|
// normaliseLLMURL ensures the URL has a /v1 suffix for bare Ollama hosts.
|
|
// Examples:
|
|
//
|
|
// "http://localhost:11434" → "http://localhost:11434/v1"
|
|
// "http://localhost:11434/" → "http://localhost:11434/v1"
|
|
// "https://ollama.com/v1" → "https://ollama.com/v1" (unchanged)
|
|
// "https://api.openai.com/v1" → unchanged
|
|
func normaliseLLMURL(raw string) string {
|
|
u := strings.TrimRight(raw, "/")
|
|
if !strings.HasSuffix(u, "/v1") {
|
|
u += "/v1"
|
|
}
|
|
return u
|
|
}
|
|
|
|
// getEnvFirst returns the value of the first non-empty env variable from the list.
|
|
func getEnvFirst(keys ...string) string {
|
|
for _, k := range keys {
|
|
if v := os.Getenv(k); v != "" {
|
|
return v
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|