- Project infrastructure: go.mod, Makefile, .gitignore, README - Configuration system with YAML parsing and env overrides - Structured logging with slog - AI provider interface with Ollama, OpenAI, Anthropic implementations - Provider manager with runtime switching - Agent orchestrator with ReAct loop (reason-act-observe) - Tool registry with JSON Schema descriptions - Terminal tool: shell command execution with safety controls - Filesystem tools: read, write, list with path access control - Conversation memory with session management - Web UI server with WebSocket streaming - Modern dark theme UI with glassmorphism, animations - Frontend: WebSocket client, markdown rendering, tool call display
83 lines
3 KiB
Go
83 lines
3 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/agent"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ai"
|
|
aiAnthropic "git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ai/anthropic"
|
|
aiOllama "git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ai/ollama"
|
|
aiOpenAI "git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ai/openai"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/config"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/tools"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/tools/filesystem"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/tools/terminal"
|
|
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ui"
|
|
)
|
|
|
|
// Run initializes all components and starts the application.
|
|
func Run(cfg *config.Config, log *slog.Logger) error {
|
|
// --- AI Providers ---
|
|
aiManager := ai.NewManager(log)
|
|
|
|
// Always register Ollama (local, no API key needed)
|
|
ollamaProvider := aiOllama.New(cfg.AI.Ollama, log)
|
|
aiManager.Register(ollamaProvider)
|
|
|
|
// Register cloud providers if API keys are configured
|
|
if cfg.AI.OpenAI.APIKey != "" {
|
|
openaiProvider := aiOpenAI.New(cfg.AI.OpenAI, log)
|
|
aiManager.Register(openaiProvider)
|
|
}
|
|
|
|
if cfg.AI.Anthropic.APIKey != "" {
|
|
anthropicProvider := aiAnthropic.New(cfg.AI.Anthropic, log)
|
|
aiManager.Register(anthropicProvider)
|
|
}
|
|
|
|
// Set active provider
|
|
if err := aiManager.SetActive(cfg.AI.DefaultProvider); err != nil {
|
|
// Fallback to ollama
|
|
log.Warn("default provider not available, falling back to ollama", "provider", cfg.AI.DefaultProvider, "error", err)
|
|
if err := aiManager.SetActive("ollama"); err != nil {
|
|
return fmt.Errorf("no AI providers available: %w", err)
|
|
}
|
|
}
|
|
|
|
// --- Tools ---
|
|
toolsRegistry := tools.NewRegistry(log)
|
|
|
|
terminal.RegisterTools(toolsRegistry, cfg.Tools.Terminal, log)
|
|
filesystem.RegisterTools(toolsRegistry, cfg.Tools.Filesystem, log)
|
|
|
|
log.Info("tools registered", "count", len(toolsRegistry.Names()), "tools", toolsRegistry.Names())
|
|
|
|
// --- Agent ---
|
|
activeProvider, err := aiManager.Active()
|
|
if err != nil {
|
|
return fmt.Errorf("getting active provider: %w", err)
|
|
}
|
|
|
|
ag := agent.New(activeProvider, toolsRegistry, cfg.Agent, log)
|
|
memory := agent.NewMemory()
|
|
|
|
// --- UI Server ---
|
|
server := ui.NewServer(cfg.Server, aiManager, ag, memory, log)
|
|
|
|
log.Info("ZovOS AI starting",
|
|
"provider", aiManager.ActiveName(),
|
|
"tools", toolsRegistry.Names(),
|
|
"address", fmt.Sprintf("http://%s:%d", cfg.Server.Host, cfg.Server.Port),
|
|
)
|
|
|
|
fmt.Printf("\n ╔══════════════════════════════════════════╗\n")
|
|
fmt.Printf(" ║ 🤖 ZovOS AI is running! ║\n")
|
|
fmt.Printf(" ║ ║\n")
|
|
fmt.Printf(" ║ Open: http://localhost:%d ║\n", cfg.Server.Port)
|
|
fmt.Printf(" ║ Provider: %-29s║\n", aiManager.ActiveName())
|
|
fmt.Printf(" ║ ║\n")
|
|
fmt.Printf(" ╚══════════════════════════════════════════╝\n\n")
|
|
|
|
return server.Start()
|
|
}
|