// Package config provides the configuration types for the Orca framework. // // Configuration is organized into logical groups: LLM (Ollama), sandbox, // and session management. Default values are provided for all settings. package config import ( "os" "strconv" "time" ) // Config is the top-level configuration for the Orca framework. type Config struct { Ollama OllamaConfig `json:"ollama"` Sandbox SandboxConfig `json:"sandbox"` Session SessionConfig `json:"session"` } // OllamaConfig holds configuration for the Ollama LLM backend. type OllamaConfig struct { // BaseURL is the Ollama API endpoint (e.g., "http://localhost:11434"). BaseURL string `json:"base_url"` // Model is the Ollama model name to use (e.g., "gemma4:e4b", "codellama"). Model string `json:"model"` // Timeout is the maximum duration to wait for an Ollama response. Timeout time.Duration `json:"timeout"` } // SandboxConfig holds configuration for the command execution sandbox. type SandboxConfig struct { // Timeout is the maximum duration for a sandboxed command. Timeout time.Duration `json:"timeout"` // MaxMemory is the maximum memory allocation for the sandbox (in bytes). MaxMemory int64 `json:"max_memory"` // WorkingDir is the default working directory for sandboxed commands. WorkingDir string `json:"working_dir"` } // SessionConfig holds configuration for session management. type SessionConfig struct { // StorageDir is the directory for session JSONL files. StorageDir string `json:"storage_dir"` // MaxHistory is the maximum number of messages to retain per session. MaxHistory int `json:"max_history"` } // DefaultConfig returns a Config with sensible defaults. func DefaultConfig() *Config { return &Config{ Ollama: OllamaConfig{ BaseURL: "http://localhost:11434", Model: "gemma4:e4b", Timeout: 120 * time.Second, }, Sandbox: SandboxConfig{ Timeout: 30 * time.Second, MaxMemory: 512 * 1024 * 1024, // 512 MB WorkingDir: "/tmp/orca/sandbox", }, Session: SessionConfig{ StorageDir: func() string { home, _ := os.UserHomeDir() return home + "/.orca/sessions" }(), MaxHistory: 100, }, } } // LoadConfigFromEnv reads configuration from environment variables, // overriding defaults where environment variables are set. func LoadConfigFromEnv() *Config { cfg := DefaultConfig() if v := os.Getenv("ORCA_OLLAMA_BASE_URL"); v != "" { cfg.Ollama.BaseURL = v } if v := os.Getenv("ORCA_OLLAMA_MODEL"); v != "" { cfg.Ollama.Model = v } if v := os.Getenv("ORCA_OLLAMA_TIMEOUT"); v != "" { if d, err := time.ParseDuration(v); err == nil { cfg.Ollama.Timeout = d } } if v := os.Getenv("ORCA_SANDBOX_TIMEOUT"); v != "" { if d, err := time.ParseDuration(v); err == nil { cfg.Sandbox.Timeout = d } } if v := os.Getenv("ORCA_SANDBOX_MAX_MEMORY"); v != "" { if n, err := strconv.ParseInt(v, 10, 64); err == nil { cfg.Sandbox.MaxMemory = n } } if v := os.Getenv("ORCA_SANDBOX_WORKING_DIR"); v != "" { cfg.Sandbox.WorkingDir = v } if v := os.Getenv("ORCA_SESSION_STORAGE_DIR"); v != "" { cfg.Session.StorageDir = v } if v := os.Getenv("ORCA_SESSION_MAX_HISTORY"); v != "" { if n, err := strconv.Atoi(v); err == nil { cfg.Session.MaxHistory = n } } return cfg } // IsValid checks whether the configuration has valid values. func (c *Config) IsValid() error { if c.Ollama.BaseURL == "" { return errConfig("ollama.base_url must not be empty") } if c.Ollama.Model == "" { return errConfig("ollama.model must not be empty") } if c.Ollama.Timeout <= 0 { return errConfig("ollama.timeout must be positive") } if c.Sandbox.Timeout <= 0 { return errConfig("sandbox.timeout must be positive") } if c.Sandbox.MaxMemory <= 0 { return errConfig("sandbox.max_memory must be positive") } if c.Session.MaxHistory <= 0 { return errConfig("session.max_history must be positive") } return nil } // errConfig creates a configuration error. func errConfig(msg string) error { return &ConfigError{Message: msg} } // ConfigError represents a configuration validation error. type ConfigError struct { Message string } func (e *ConfigError) Error() string { return "config: " + e.Message }