package main import ( "bufio" "context" "flag" "fmt" "log" "os" "path/filepath" "strconv" "strings" "github.com/openai/openai-go" oaioption "github.com/openai/openai-go/option" "llm-agent/agent" ) const baseURL = "http://127.0.0.1:12434/v1" func resolvePath(base, rel string) string { if filepath.IsAbs(rel) { return rel // absoluter Pfad → direkt nutzen } return filepath.Join(base, rel) } func selectModel(client *openai.Client) string { modelsPage, err := client.Models.List(context.Background()) if err != nil { log.Fatalf("Fehler beim Abrufen der Modelle: %v", err) } models := modelsPage.Data if len(models) == 0 { log.Fatal("Keine Modelle verfügbar!") } fmt.Println("\n📦 Verfügbare Modelle:") fmt.Println(strings.Repeat("─", 50)) for i, m := range models { fmt.Printf(" [%d] %s\n", i+1, m.ID) } fmt.Println(strings.Repeat("─", 50)) scanner := bufio.NewScanner(os.Stdin) for { fmt.Printf("Wähle ein Modell (1-%d): ", len(models)) if !scanner.Scan() { log.Fatal("Eingabe fehlgeschlagen") } choice, err := strconv.Atoi(strings.TrimSpace(scanner.Text())) if err != nil || choice < 1 || choice > len(models) { fmt.Printf("❌ Ungültige Eingabe.\n") continue } selected := models[choice-1].ID fmt.Printf("✅ Modell gewählt: %s\n", selected) return selected } } func main() { // Verzeichnis der ausführbaren Binary ermitteln execPath, err := os.Executable() if err != nil { log.Fatalf("Konnte Executable-Pfad nicht ermitteln: %v", err) } execDir := filepath.Dir(execPath) // Flags definieren verbose := flag.Bool("verbose", false, "Zeigt alle Chat-Nachrichten vollständig an") workDir := flag.String("workdir", "workspace", "Arbeitsverzeichnis (relativ zur Binary oder absolut)") prdFile := flag.String("prd", "PRD.md", "PRD-Datei (relativ zum Arbeitsverzeichnis oder absolut)") flag.Parse() // Pfade auflösen resolvedWorkDir := resolvePath(execDir, *workDir) resolvedPRD := resolvePath(resolvedWorkDir, *prdFile) // Arbeitsverzeichnis anlegen falls nicht vorhanden if err := os.MkdirAll(resolvedWorkDir, 0755); err != nil { log.Fatalf("Konnte Arbeitsverzeichnis nicht anlegen: %v", err) } fmt.Println("🤖 LLM Agent") fmt.Printf("📁 Arbeitsverzeichnis : %s\n", resolvedWorkDir) fmt.Printf("📋 PRD-Datei : %s\n", resolvedPRD) if *verbose { fmt.Println("🔍 Verbose-Modus aktiv") } client := openai.NewClient( oaioption.WithBaseURL(baseURL), oaioption.WithAPIKey("ollama"), ) model := selectModel(&client) loop := agent.NewAgentLoop(model, resolvedWorkDir, resolvedPRD, *verbose) if err := loop.Run(); err != nil { log.Fatalf("Agent fehlgeschlagen: %v", err) } }