// Orca is a Go-based Agent framework with a microkernel architecture. // // It supports multi-agent collaboration, persistent session memory, // skill-based automation, sandboxed execution, custom tool registration, // and local LLM integration via Ollama. package main import ( "bufio" "fmt" "log" "os" "os/signal" "strings" "syscall" "time" "github.com/orca/orca/internal/config" "github.com/orca/orca/pkg/kernel" ) func main() { // Load configuration from environment variables cfg := config.LoadConfigFromEnv() if v := os.Getenv("OLLAMA_BASE_URL"); v != "" { cfg.Ollama.BaseURL = v } if v := os.Getenv("OLLAMA_MODEL"); v != "" { cfg.Ollama.Model = v } if v := os.Getenv("OLLAMA_TIMEOUT"); v != "" { if d, err := time.ParseDuration(v); err == nil { cfg.Ollama.Timeout = d } } if v := os.Getenv("DEEPSEEK_BASE_URL"); v != "" { cfg.DeepSeek.BaseURL = v } if v := os.Getenv("DEEPSEEK_MODEL"); v != "" { cfg.DeepSeek.Model = v } if v := os.Getenv("DEEPSEEK_API_KEY"); v != "" { cfg.DeepSeek.APIKey = v } if v := os.Getenv("DEEPSEEK_TIMEOUT"); v != "" { if d, err := time.ParseDuration(v); err == nil { cfg.DeepSeek.Timeout = d } } // Create and start kernel k := kernel.NewWithConfig(cfg) if err := k.Start(); err != nil { log.Fatalf("Failed to start kernel: %v", err) } if err := k.InitPlugins(); err != nil { log.Printf("Warning: failed to load skills: %v", err) } k.SetStreamWriter(os.Stdout) fmt.Println("Orca Agent Framework") fmt.Println("Kernel started successfully") if cfg.Provider == config.ProviderDeepSeek { fmt.Printf(" Provider: DeepSeek\n") fmt.Printf(" LLM Model: %s\n", cfg.DeepSeek.Model) } else { fmt.Printf(" Provider: Ollama\n") fmt.Printf(" LLM Model: %s\n", cfg.Ollama.Model) fmt.Printf(" Ollama URL: %s\n", cfg.Ollama.BaseURL) } fmt.Println("Type your message or /help for commands.") fmt.Println() // Handle graceful shutdown sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) // REPL loop in a goroutine so we can catch signals done := make(chan struct{}) go func() { scanner := bufio.NewScanner(os.Stdin) for { fmt.Print("> ") if !scanner.Scan() { break } input := strings.TrimSpace(scanner.Text()) if input == "" { continue } // Handle commands if strings.HasPrefix(input, "/") { handleCommand(input, k) continue } // Send message to LLM agent via kernel _, err := k.SendMessage("user", "llm", input) if err != nil { fmt.Printf("Error: %v\n", err) continue } fmt.Println() } if err := scanner.Err(); err != nil { fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err) } close(done) }() // Wait for either SIGINT or REPL exit select { case <-sig: fmt.Println("\nShutting down Orca kernel...") case <-done: fmt.Println("\nInput closed. Shutting down Orca kernel...") } if err := k.Stop(); err != nil { log.Fatalf("Failed to stop kernel: %v", err) } fmt.Println("Orca kernel shut down gracefully.") } // handleCommand processes REPL commands. func handleCommand(cmd string, k *kernel.Kernel) { switch cmd { case "/help": fmt.Println("Available commands:") fmt.Println(" /help - Show this help message") fmt.Println(" /exit - Exit the program") fmt.Println(" /quit - Exit the program") fmt.Println(" /plugins - List registered plugins") fmt.Println(" /agents - List active agents") fmt.Println(" /tools - List registered tools") fmt.Println(" /skills - List loaded skills") fmt.Println(" /status - Show kernel status") fmt.Println() fmt.Println("Any other input is sent to the LLM agent for processing.") case "/exit", "/quit": fmt.Println("Goodbye!") os.Exit(0) case "/plugins": plugins := k.ListPlugins() if len(plugins) == 0 { fmt.Println("No plugins registered.") } else { fmt.Println("Registered plugins:") for _, p := range plugins { fmt.Printf(" - %s (%s)\n", p.Name(), p.Version()) } } case "/agents": as := k.ActorSystem() if as == nil { fmt.Println("Actor system not initialized.") return } infos := as.AgentInfos() if len(infos) == 0 { fmt.Println("No agents running.") } else { fmt.Println("Active agents:") for _, info := range infos { fmt.Printf(" - %s [%s] (status: %s)\n", info.ID, info.Role, info.Status) } } case "/tools": tm := k.ToolManager() if tm == nil { fmt.Println("Tool manager not initialized.") return } tools := tm.List() if len(tools) == 0 { fmt.Println("No tools registered.") } else { fmt.Println("Registered tools:") for _, t := range tools { fmt.Printf(" - %s: %s\n", t.Name(), t.Description()) } } case "/skills": sm := k.SkillManager() if sm == nil { fmt.Println("Skill manager not initialized.") return } skills := sm.ListSkills() if len(skills) == 0 { fmt.Println("No skills loaded.") } else { fmt.Println("Loaded skills:") for _, s := range skills { fmt.Printf(" - %s: %s\n", s.Name, s.Description) } } case "/status": fmt.Printf("Kernel running: %v\n", k.IsRunning()) if tm := k.ToolManager(); tm != nil { fmt.Printf("Tools registered: %d\n", tm.Count()) } if as := k.ActorSystem(); as != nil { fmt.Printf("Agents active: %d\n", as.AgentCount()) } if sm := k.SkillManager(); sm != nil { fmt.Printf("Skills loaded: %d\n", len(sm.ListSkills())) } default: fmt.Printf("Unknown command: %s\n", cmd) fmt.Println("Type /help for available commands.") } }