- Implement 'Show Problems Only' toggle combining degraded status, high CPU/memory alerts, and needs backup filters - Add 'Investigate with AI' button to filter bar for problematic guests - Fix dashboard column sizing inconsistencies between bars and sparklines view modes - Fix PBS backups display and polling - Refine AI prompt for general-purpose usage - Fix frontend flickering and reload loops during initial load - Integrate persistent SQLite metrics store with Monitor - Fortify AI command routing with improved validation and logging - Fix CSRF token handling for note deletion - Debug and fix AI command execution issues - Various AI reliability improvements and command safety enhancements
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package config
|
|
|
|
// AIConfig holds AI feature configuration
|
|
// This is stored in ai.enc (encrypted) in the config directory
|
|
type AIConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
Provider string `json:"provider"` // "anthropic", "openai", "ollama", "deepseek"
|
|
APIKey string `json:"api_key"` // encrypted at rest (not needed for ollama)
|
|
Model string `json:"model"` // e.g., "claude-opus-4-5-20250514", "gpt-4o", "llama3"
|
|
BaseURL string `json:"base_url"` // custom endpoint (required for ollama, optional for openai)
|
|
AutonomousMode bool `json:"autonomous_mode"` // when true, AI executes commands without approval
|
|
CustomContext string `json:"custom_context"` // user-provided context about their infrastructure
|
|
}
|
|
|
|
// AIProvider constants
|
|
const (
|
|
AIProviderAnthropic = "anthropic"
|
|
AIProviderOpenAI = "openai"
|
|
AIProviderOllama = "ollama"
|
|
AIProviderDeepSeek = "deepseek"
|
|
)
|
|
|
|
// Default models per provider
|
|
const (
|
|
DefaultAIModelAnthropic = "claude-opus-4-5-20251101"
|
|
DefaultAIModelOpenAI = "gpt-4o"
|
|
DefaultAIModelOllama = "llama3"
|
|
DefaultAIModelDeepSeek = "deepseek-reasoner"
|
|
DefaultOllamaBaseURL = "http://localhost:11434"
|
|
DefaultDeepSeekBaseURL = "https://api.deepseek.com/chat/completions"
|
|
)
|
|
|
|
// NewDefaultAIConfig returns an AIConfig with sensible defaults
|
|
func NewDefaultAIConfig() *AIConfig {
|
|
return &AIConfig{
|
|
Enabled: false,
|
|
Provider: AIProviderAnthropic,
|
|
Model: DefaultAIModelAnthropic,
|
|
}
|
|
}
|
|
|
|
// IsConfigured returns true if the AI config has enough info to make API calls
|
|
func (c *AIConfig) IsConfigured() bool {
|
|
if !c.Enabled {
|
|
return false
|
|
}
|
|
|
|
switch c.Provider {
|
|
case AIProviderAnthropic, AIProviderOpenAI, AIProviderDeepSeek:
|
|
return c.APIKey != ""
|
|
case AIProviderOllama:
|
|
// Ollama doesn't need an API key
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// GetBaseURL returns the base URL, using defaults where appropriate
|
|
func (c *AIConfig) GetBaseURL() string {
|
|
if c.BaseURL != "" {
|
|
return c.BaseURL
|
|
}
|
|
switch c.Provider {
|
|
case AIProviderOllama:
|
|
return DefaultOllamaBaseURL
|
|
case AIProviderDeepSeek:
|
|
return DefaultDeepSeekBaseURL
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetModel returns the model, using defaults where appropriate
|
|
func (c *AIConfig) GetModel() string {
|
|
if c.Model != "" {
|
|
return c.Model
|
|
}
|
|
switch c.Provider {
|
|
case AIProviderAnthropic:
|
|
return DefaultAIModelAnthropic
|
|
case AIProviderOpenAI:
|
|
return DefaultAIModelOpenAI
|
|
case AIProviderOllama:
|
|
return DefaultAIModelOllama
|
|
case AIProviderDeepSeek:
|
|
return DefaultAIModelDeepSeek
|
|
default:
|
|
return ""
|
|
}
|
|
}
|