Files
llama-link/internal/config/config.go
T
darroyo 4c9ed3c24b Initial commit: LlamaLink Go rewrite
Complete rewrite from Python/FastAPI to Go/Gin:
- Go backend: auth (API keys + bcrypt), llama.cpp subprocess manager,
  hot-swap multi-model, rate limiting, quota system, webhooks
- Vue 3 SPA admin panel (src/) with Tailwind CSS
- Deployment: Docker multi-stage, docker-compose, nginx, systemd
- GORM/SQLite models: ApiKey, Model, UsageLog, Quota, Webhook
- REST API: /api/v1/admin/* (keys, models, chat, usage, health)
- Embedded frontend via go:embed (build output at web/dist/)

Removed legacy Python artifacts (app/, tests/, pyproject.toml, etc.)
2026-07-30 10:58:55 -04:00

138 lines
3.5 KiB
Go

package config
import (
"log/slog"
"os"
"strconv"
"time"
)
type Config struct {
// Server
LlamalinkEnv string
LlamalinkHost string
LlamalinkPort int
// Database
DatabaseURL string
DatabaseMaxOpenConns int
DatabaseMaxIdleConns int
DatabaseConnMaxLifetime int // seconds
// Llama server management
ManageLlamaServer bool
LlamaServerBin string
LlamaServerHost string
LlamaServerPort int
LlamaServerStartupTimeout int // seconds
LlamaServerStopTimeout int // seconds
ModelSwapCooldown int // seconds
// Rate limiting
RateLimitPerMinute int
RateLimitStorage string // "memory" or "redis"
// Auth
AdminToken string
// Logging
LogLevel string
LogFormat string // "json" or "text"
}
func Load() *Config {
c := &Config{
LlamalinkEnv: getEnv("LLAMALINK_ENV", "development"),
LlamalinkHost: getEnv("LLAMALINK_HOST", "0.0.0.0"),
LlamalinkPort: intEnv("LLAMALINK_PORT", 8000),
DatabaseURL: getEnv("DATABASE_URL", "sqlite:///./llamalink.db"),
DatabaseMaxOpenConns: intEnv("DATABASE_MAX_OPEN_CONNS", 25),
DatabaseMaxIdleConns: intEnv("DATABASE_MAX_IDLE_CONNS", 5),
DatabaseConnMaxLifetime: intEnv("DATABASE_CONN_MAX_LIFETIME", 300),
ManageLlamaServer: boolEnv("MANAGE_LLAMA_SERVER", true),
LlamaServerBin: getEnv("LLAMA_SERVER_BIN", "/usr/local/bin/llama-server"),
LlamaServerHost: getEnv("LLAMA_SERVER_HOST", "127.0.0.1"),
LlamaServerPort: intEnv("LLAMA_SERVER_PORT", 8080),
LlamaServerStartupTimeout: intEnv("LLAMA_SERVER_STARTUP_TIMEOUT", 120),
LlamaServerStopTimeout: intEnv("LLAMA_SERVER_STOP_TIMEOUT", 10),
ModelSwapCooldown: intEnv("MODEL_SWAP_COOLDOWN", 2),
RateLimitPerMinute: intEnv("RATE_LIMIT_PER_MINUTE", 60),
RateLimitStorage: getEnv("RATE_LIMIT_STORAGE", "memory"),
AdminToken: getEnv("ADMIN_TOKEN", "changeme"),
LogLevel: getEnv("LOG_LEVEL", "info"),
LogFormat: getEnv("LOG_FORMAT", "json"),
}
return c
}
func (c *Config) LlamaServerURL() string {
return "http://" + c.LlamaServerHost + ":" + strconv.Itoa(c.LlamaServerPort)
}
func (c *Config) LlamaServerStartupTimeoutDuration() time.Duration {
return time.Duration(c.LlamaServerStartupTimeout) * time.Second
}
func (c *Config) LlamaServerStopTimeoutDuration() time.Duration {
return time.Duration(c.LlamaServerStopTimeout) * time.Second
}
func (c *Config) ModelSwapCooldownDuration() time.Duration {
return time.Duration(c.ModelSwapCooldown) * time.Second
}
func (c *Config) Logger() *slog.Logger {
var level slog.Level
switch c.LogLevel {
case "debug":
level = slog.LevelDebug
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
default:
level = slog.LevelInfo
}
opts := &slog.HandlerOptions{
Level: level,
}
var handler slog.Handler
if c.LogFormat == "text" {
handler = slog.NewTextHandler(os.Stdout, opts)
} else {
handler = slog.NewJSONHandler(os.Stdout, opts)
}
return slog.New(handler)
}
func getEnv(key, defaultValue string) string {
if v := os.Getenv(key); v != "" {
return v
}
return defaultValue
}
func intEnv(key string, defaultValue int) int {
if v := os.Getenv(key); v != "" {
if i, err := strconv.Atoi(v); err == nil {
return i
}
}
return defaultValue
}
func boolEnv(key string, defaultValue bool) bool {
if v := os.Getenv(key); v != "" {
if v == "true" || v == "1" || v == "yes" {
return true
}
if v == "false" || v == "0" || v == "no" {
return false
}
}
return defaultValue
}