From 754b2aa3e3c6793eaf6c1963387ebbcc02068e90 Mon Sep 17 00:00:00 2001 From: Meleki Date: Mon, 2 Mar 2026 07:59:29 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20Krea-Tags=20in=20Code-Bl=C3=B6cken=20nic?= =?UTF-8?q?ht=20parsen,=20Git-Verhalten=20unabh=C3=A4ngig=20von=20ToolChoi?= =?UTF-8?q?ce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - renderMarkdown: Code-Blöcke (
, ) vor Krea-Regex schützen
  via Platzhalter-Swap, danach wiederherstellen
- SystemPromptBuilder: Git-Commit-Regeln nur an Workspace gebunden,
  nicht mehr an ToolChoice:any – eigener PromptBlock mit Label
- CSS: modal-width Variable, Krea-Modal width:max-content, minor tweaks
- TODO.md aktualisiert
---
 Services/SystemPromptBuilder.cs | 43 +++++++++++++++++++++++----------
 TODO.md                         |  7 ++++--
 wwwroot/css/chat.css            |  9 ++++---
 wwwroot/css/file-explorer.css   |  2 +-
 wwwroot/css/theme.css           |  3 ++-
 wwwroot/js/ui.js                | 10 ++++++++
 6 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/Services/SystemPromptBuilder.cs b/Services/SystemPromptBuilder.cs
index 6d3e735..5b67546 100644
--- a/Services/SystemPromptBuilder.cs
+++ b/Services/SystemPromptBuilder.cs
@@ -147,27 +147,44 @@ Wenn der User auf eine bestimmte Zeile in einer Datei verweist (z.B. `[Datei: fo
             blocks.Add(new PromptBlock { Icon = "fa-database", Label = "Agent · Memory (UseMemory)", Content = string.Join("\n", memoryLines) });
         }
 
-        if (toolAny && !string.IsNullOrWhiteSpace(session.Workspace))
+        // Git-Commit-Verhalten: relevant sobald Workspace vorhanden (unabhängig von ToolChoice)
+        if (!string.IsNullOrWhiteSpace(session.Workspace))
         {
-            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.");
+                blocks.Add(new PromptBlock
+                {
+                    Icon = "fa-code-branch",
+                    Label = "Agent · Git-Verhalten (Workspace + AutoCommit)",
+                    Content = "## Git-Commits\n- 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.");
+                blocks.Add(new PromptBlock
+                {
+                    Icon = "fa-code-branch",
+                    Label = "Agent · Git-Verhalten (Workspace)",
+                    Content = "## Git-Commits\n- 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."
+                });
             }
+        }
 
-            blocks.Add(new PromptBlock { Icon = "fa-cog", Label = "Agent · Verhalten (Workspace + ToolChoice: any" + (agent.AutoCommit ? ", AutoCommit" : "") + ")", Content = string.Join("\n", verhaltensRegeln) });
+        if (toolAny && !string.IsNullOrWhiteSpace(session.Workspace))
+        {
+            blocks.Add(new PromptBlock
+            {
+                Icon = "fa-cog",
+                Label = "Agent · Verhalten (Workspace + ToolChoice: any)",
+                Content = string.Join("\n", new[]
+                {
+                    "## 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."
+                })
+            });
 
             blocks.Add(new PromptBlock
             {
diff --git a/TODO.md b/TODO.md
index 16fb6b7..0ad0047 100644
--- a/TODO.md
+++ b/TODO.md
@@ -9,7 +9,9 @@
 - [ ] User-Management: Tabelle in Datenbank mit username / password. Wenn kein User vorhanden: dann admin mit password "admin" anlegen
 - [ ] Neuer Message-Tag: `[canvas::<height (optional)>]...[/canvas]`
 - [ ] Websearch Tool?
-- [ ] Anfrage/Stream abbrechen
+- [x] Anfrage/Stream abbrechen
+- [ ] Telegram Intergration
+- [ ] Refactoring: Agent/Session-Einstellungen, die den System-Prompt bzw. das Tool Use bearbeiten
 
 ## Bugs
 - [x] Wenn gerade gestreamt wird und man refreshed die Seite, dann verliert das Frontend den Status "Streaming..." und ich kann eine Nachricht schreiben, obwohl das nicht möglich sein sollte
@@ -20,10 +22,11 @@
 
 ## Frontend
 - [x] Chat: Es scrollt beim Laden nicht ganz nach unten, ich denke weil im DOM noch etwas nachgeladen wird (ich denke es ist die Schriftart), und die Höhe sich beim Laden nochmal verändert
-- [x] Chat: User-Nachrichten mit dem Tag [Datei: pfat/zur/datei.xyz:1-10] wird nicht als HTML geparsed
+- [x] Chat: User-Nachrichten mit dem Tag [Datei: pfad/zur/datei.xyz:1-10] wird nicht als HTML geparsed
 - [x] Chat: Wird zwar erkannt und ist klickbar, aber es öffnet sich einfach nur der File Explorer, ohne dass sich die Datei öffnet und die Darstellung in Monospace ist auch nicht schön
 - [x] Chat: Es werden momentan alle Tool-Calls angezeigt - die Anzeige soll individuell in den Einstellungen gemacht werden können. Auswahl aus drei Stufen: "Alle anzeigen" / "Nur Modifikationen" (file änderungen, memory änderungen, etc.) / "Verstecken"
 - [ ] Browser: "Zurück"-Taste soll auf den vorherigen location.hash wechseln
+- [ ] File Explorer: CodeMirror lässt sich horizontal nicht scroll
 
 ## Ideas / Backlog
 - [ ] Memory: Embedding-Modell für semantische Suche über Memory-Dateien (Vektor-basiert + BM25 Hybrid Search)
diff --git a/wwwroot/css/chat.css b/wwwroot/css/chat.css
index 8eef8e8..f294a6a 100644
--- a/wwwroot/css/chat.css
+++ b/wwwroot/css/chat.css
@@ -534,7 +534,7 @@
   border-radius: var(--border-radius);
   overflow: hidden;
   width: 90vw;
-  max-width: 700px;
+  max-width: var(--modal-width);
   max-height: 80vh;
   display: flex;
   flex-direction: column;
@@ -592,7 +592,7 @@
 /* Command Output Modal */
 
 .cmd-output-modal {
-  max-width: 800px;
+  max-width: var(--modal-width);
 }
 
 .cmd-output-meta {
@@ -671,15 +671,16 @@
 /* Krea Image Modal */
 
 .krea-modal {
+  width: max-content;
   max-width: 90vw;
-  max-height: 90vh;
+  max-height: unset;
 }
 
 .krea-modal-body {
   display: flex;
   align-items: center;
   justify-content: center;
-  padding: var(--box-spacing);
+  padding: var(--badge-spacing);
 }
 
 .krea-modal-image {
diff --git a/wwwroot/css/file-explorer.css b/wwwroot/css/file-explorer.css
index a0706c0..244e5f9 100644
--- a/wwwroot/css/file-explorer.css
+++ b/wwwroot/css/file-explorer.css
@@ -16,7 +16,6 @@
   border-radius: var(--border-radius);
   overflow: hidden;
   width: 90vw;
-  max-width: 1100px;
   height: 80vh;
   display: flex;
   flex-direction: column;
@@ -60,6 +59,7 @@
   overflow-y: auto;
   background: var(--f1-bg);
   flex-shrink: 0;
+  padding-block: var(--box-spacing);
 }
 
 .fe-sidebar-full {
diff --git a/wwwroot/css/theme.css b/wwwroot/css/theme.css
index f0ec73c..079b3fd 100644
--- a/wwwroot/css/theme.css
+++ b/wwwroot/css/theme.css
@@ -24,11 +24,12 @@
   --box-padding: .75em 1em;
   --box-spacing: 1.5em;
   --input-padding: .45em .7em;
-  --button-padding: .45em .8em;
+  --button-padding: .5em .9em;
   --badge-padding: .2em .6em;
   --badge-spacing: .5em;
   --menu-item-padding: .5em .75em;
   --page-width: 900px;
   --hover-filter: contrast(.9);
   --transition-duration: .15s;
+  --modal-width: 700px;
 }
diff --git a/wwwroot/js/ui.js b/wwwroot/js/ui.js
index 83e0192..5181daf 100644
--- a/wwwroot/js/ui.js
+++ b/wwwroot/js/ui.js
@@ -11,6 +11,12 @@ marked.setOptions({ breaks: true, gfm: true });
 function renderMarkdown(text) {
   if (!text) return '';
   var html = marked.parse(text.trim());
+  // Code-Blöcke (<pre>...<code>...</code>...</pre> und inline <code>...</code>) schützen
+  var codeBlocks = [];
+  html = html.replace(/<pre[\s>][\s\S]*?<\/pre>|<code[\s>][\s\S]*?<\/code>/gi, function(m) {
+    codeBlocks.push(m);
+    return '%%CODE' + (codeBlocks.length - 1) + '%%';
+  });
   // [Krea: dateiname.png] → Inline-Thumbnail mit Klick für Vollbild
   html = html.replace(/\[Krea:\s*([^\]]+)\]/g, function(match, filename) {
     var fn = filename.trim();
@@ -21,6 +27,10 @@ function renderMarkdown(text) {
       + '<img class="krea-thumb" src="' + thumbUrl + '" alt="' + safeFn + '" loading="lazy">'
       + '</span>';
   });
+  // Code-Blöcke wiederherstellen
+  html = html.replace(/%%CODE(\d+)%%/g, function(m, idx) {
+    return codeBlocks[parseInt(idx)];
+  });
   return html;
 }