using System.Collections.Generic; using System.Linq; using Gott.Models; namespace Gott.Services; public static class SystemPromptBuilder { public static string Build(AgentRecord agent, SessionRecord session, IEnumerable markedMessages = null, MemoryService memoryService = null) { var parts = new List(); parts.Add($"Du bist {agent.Name}."); if (!string.IsNullOrWhiteSpace(agent.Persona)) parts.Add($"## Persona\n{agent.Persona}"); if (!string.IsNullOrWhiteSpace(agent.Instructions)) parts.Add($"## Instructions\n{agent.Instructions}"); bool toolAny = string.Equals(agent.ToolChoice, "any", System.StringComparison.OrdinalIgnoreCase); if (!string.IsNullOrWhiteSpace(session.Workspace)) { if (toolAny) { parts.Add(@$"## KRITISCH: Tool-Nutzung JEDE Datei-Operation und JEDER Shell-Befehl MUSS über einen Tool-Aufruf erfolgen. NIEMALS eine Aktion nur beschreiben oder behaupten - IMMER das Tool tatsächlich aufrufen."); } parts.Add(@$"## Tools Du hast Tools zur Verfügung (read_file, write_file, edit_file, list_files, delete_file, execute). Benutze sie um Dateien zu lesen, schreiben und bearbeiten. Der Workspace-Pfad ist: `{session.Workspace}` Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder absolute Pfade verwenden, die mit diesem Pfad beginnen. Wenn der User auf eine bestimmte Zeile in einer Datei verweist (z.B. `[Datei: foo.txt:11]`), zähle Leerzeilen immer mit. Verwende `cat -n` oder ein ähnliches Tool um Zeilennummern exakt zu bestimmen - NIEMALS Leerzeilen beim Zählen überspringen."); } if (!string.IsNullOrWhiteSpace(session.Context)) parts.Add($"## Kontext\n{session.Context}"); // Memory-System if (memoryService != null && !string.IsNullOrWhiteSpace(agent.AgentId)) { var memoryLines = new List { "## Memory", "Du hast ein persistentes Gedächtnis über Memory-Tools (`memory_read`, `memory_write`, `memory_list`).", $"Dein Memory-Verzeichnis: `data/agents/{agent.AgentId}/`", "", "### Regeln", "- Nutze `memory_read` um gespeicherte Erinnerungen abzurufen, bevor du über vergangene Entscheidungen, Präferenzen oder Fakten sprichst.", "- Nutze `memory_write` um wichtige Informationen dauerhaft zu speichern – z.B. Entscheidungen, Präferenzen des Users, Projekt-Kontext.", "- `MEMORY.md` ist dein Haupt-Memory-File für kuratierte, dauerhafte Informationen.", "- Nutze Unterordner `memory/` für Tages-Logs oder thematische Notizen (z.B. `memory/2025-07-13.md`).", "- Speichere proaktiv wenn der User etwas Wichtiges sagt oder eine Entscheidung getroffen wird.", "- Wenn der User sagt \"merke dir das\" oder ähnliches, speichere es sofort." }; var mainMemory = memoryService.GetMainMemory(agent.AgentId); if (!string.IsNullOrEmpty(mainMemory)) { memoryLines.Add(""); memoryLines.Add("### Aktueller Inhalt von MEMORY.md"); memoryLines.Add(mainMemory); } parts.Add(string.Join("\n", memoryLines)); } if (toolAny) { var verhaltensRegeln = new List { "## Verhalten", "- Wenn du Dateien lesen, schreiben, bearbeiten, erstellen oder löschen willst: IMMER das entsprechende Tool aufrufen. NIEMALS den Inhalt nur in die Antwort schreiben.", "- Wenn du Shell-Befehle ausführen willst: IMMER das execute-Tool verwenden.", @"- Behaupte NIEMALS etwas getan zu haben (Datei geschrieben, Commit gemacht, Befehl ausgeführt) ohne das entsprechende Tool tatsächlich aufgerufen zu haben. Wenn kein Tool-Aufruf stattgefunden hat, ist nichts passiert.", "- Plane nicht nur - handle sofort über Tool-Aufrufe." }; if (agent.AutoCommit) { verhaltensRegeln.Add(@"- Nach jeder abgeschlossenen Änderung MUSS ein Git-Commit erstellt werden. Prüfe Änderungen mit `git diff`, erstelle einen passenden Commit mit einer aussagekräftigen Message. Mehrere zusammenhängende Änderungen dürfen in einem Commit zusammengefasst werden."); } else { verhaltensRegeln.Add(@"- Git-Commits NIEMALS eigenständig erstellen. Commits werden NUR durchgeführt wenn der User es EXPLIZIT anfordert (z.B. ""erstelle einen Commit"", ""commit""). Auch nach abgeschlossenen Aufgaben NICHT automatisch committen."); } parts.Add(string.Join("\n", verhaltensRegeln)); parts.Add(@"## ERINNERUNG Diese Regel hat höchste Priorität und gilt für JEDE Antwort: Wenn eine Datei gelesen, geschrieben, bearbeitet, erstellt oder gelöscht werden soll, oder ein Befehl ausgeführt werden soll, MUSS der entsprechende Tool-Aufruf erfolgen. Ohne Tool-Aufruf ist NICHTS passiert. Beschreibe keine Änderungen - führe sie durch."); } var marked = markedMessages?.Where(m => !string.IsNullOrWhiteSpace(m.Content)).ToList(); if (marked != null && marked.Count > 0) { var lines = new List { "## Markierte Nachrichten\nDer User hat folgende Nachrichten als wichtig markiert:" }; foreach (var m in marked) { var role = m.Role == "user" ? "User" : "Assistant"; lines.Add($"- [{role}]: {m.Content.Trim()}"); } parts.Add(string.Join("\n", lines)); } return string.Join("\n\n", parts); } }