From 5037c7d24e781a045f0d838eac1098e230060f5f Mon Sep 17 00:00:00 2001 From: Meleki Date: Sun, 1 Mar 2026 01:46:04 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Auto-Commit=20Flag=20f=C3=BCr=20Agents?= =?UTF-8?q?=20-=20neues=20Property=20AgentRecord.AutoCommit=20(bool)=20-?= =?UTF-8?q?=20DB-Migration:=20agents.auto=5Fcommit=20INTEGER=20NOT=20NULL?= =?UTF-8?q?=20DEFAULT=200=20-=20Agent=20Create/Update=20um=20autoCommit=20?= =?UTF-8?q?erweitert=20-=20SystemPromptBuilder:=20bedingte=20Commit-Regel?= =?UTF-8?q?=20im=20Verhalten-Abschnitt=20-=20AutoCommit=3Dtrue:=20Agent=20?= =?UTF-8?q?MUSS=20nach=20=C3=84nderungen=20committen=20-=20AutoCommit=3Dfa?= =?UTF-8?q?lse:=20Agent=20darf=20NIE=20eigenst=C3=A4ndig=20committen=20-?= =?UTF-8?q?=20Frontend:=20Checkbox=20'Auto-Commit=20erlauben'=20in=20Agent?= =?UTF-8?q?-Settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Endpoints/AgentEndpoint.cs | 4 +++- Models/AgentRecord.cs | 1 + Services/DatabaseService.cs | 7 ++++--- Services/SystemPromptBuilder.cs | 26 ++++++++++++++++++++------ wwwroot/index.html | 4 ++++ wwwroot/js/pages/agent-page.js | 3 +++ 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Endpoints/AgentEndpoint.cs b/Endpoints/AgentEndpoint.cs index ab2b904..1a4e959 100644 --- a/Endpoints/AgentEndpoint.cs +++ b/Endpoints/AgentEndpoint.cs @@ -55,7 +55,8 @@ public static class AgentEndpoint Persona = body.TryGetProperty("persona", out var p) ? p.GetString() : null, Instructions = body.TryGetProperty("instructions", out var i) ? i.GetString() : null, ToolChoice = body.TryGetProperty("toolChoice", out var tc) ? tc.GetString() ?? "any" : "any", - CustomCommands = customCommands + CustomCommands = customCommands, + AutoCommit = body.TryGetProperty("autoCommit", out var ac) && ac.GetBoolean() }; agent = await db.CreateAgent(agent); @@ -81,6 +82,7 @@ public static class AgentEndpoint if (body.TryGetProperty("toolChoice", out var tc)) agent.ToolChoice = tc.GetString(); if (body.TryGetProperty("customCommands", out var cc)) agent.CustomCommands = cc.ValueKind == JsonValueKind.Null ? null : cc.GetRawText(); + if (body.TryGetProperty("autoCommit", out var ac)) agent.AutoCommit = ac.GetBoolean(); await db.UpdateAgent(agent); agent = await db.GetAgent(agentId); diff --git a/Models/AgentRecord.cs b/Models/AgentRecord.cs index 0f10068..b2e7f28 100644 --- a/Models/AgentRecord.cs +++ b/Models/AgentRecord.cs @@ -12,6 +12,7 @@ public class AgentRecord public string Instructions { get; set; } public string ToolChoice { get; set; } // "any" oder "auto" public string CustomCommands { get; set; } + public bool AutoCommit { get; set; } public bool IsDeleted { get; set; } public string CreatedAt { get; set; } public string UpdatedAt { get; set; } diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index 2085ece..d00fe69 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -129,6 +129,7 @@ public class DatabaseService TryAddColumn(conn, "agents", "tool_choice", "TEXT DEFAULT 'any'"); TryAddColumn(conn, "agents", "custom_commands", "TEXT"); TryAddColumn(conn, "messages", "is_marked", "INTEGER NOT NULL DEFAULT 0"); + TryAddColumn(conn, "agents", "auto_commit", "INTEGER NOT NULL DEFAULT 0"); } private void TryAddColumn(SqliteConnection conn, string table, string column, string type) @@ -147,8 +148,8 @@ public class DatabaseService agent.CreatedAt = now; agent.UpdatedAt = now; await conn.ExecuteAsync(@" - INSERT INTO agents (agent_id, name, avatar, description, model, persona, instructions, tool_choice, custom_commands, is_deleted, created_at, updated_at) - VALUES (@AgentId, @Name, @Avatar, @Description, @Model, @Persona, @Instructions, @ToolChoice, @CustomCommands, 0, @CreatedAt, @UpdatedAt) + INSERT INTO agents (agent_id, name, avatar, description, model, persona, instructions, tool_choice, custom_commands, auto_commit, is_deleted, created_at, updated_at) + VALUES (@AgentId, @Name, @Avatar, @Description, @Model, @Persona, @Instructions, @ToolChoice, @CustomCommands, @AutoCommit, 0, @CreatedAt, @UpdatedAt) ", agent); return agent; } @@ -174,7 +175,7 @@ public class DatabaseService await conn.ExecuteAsync(@" UPDATE agents SET name = @Name, avatar = @Avatar, description = @Description, model = @Model, persona = @Persona, instructions = @Instructions, tool_choice = @ToolChoice, - custom_commands = @CustomCommands, updated_at = @UpdatedAt + custom_commands = @CustomCommands, auto_commit = @AutoCommit, updated_at = @UpdatedAt WHERE agent_id = @AgentId ", agent); } diff --git a/Services/SystemPromptBuilder.cs b/Services/SystemPromptBuilder.cs index 51bdcb8..d00b107 100644 --- a/Services/SystemPromptBuilder.cs +++ b/Services/SystemPromptBuilder.cs @@ -41,13 +41,27 @@ Wenn der User auf eine bestimmte Zeile in einer Datei verweist (z.B. `[Datei: fo if (toolAny) { - parts.Add(@"## 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. + 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." + }; -## ERINNERUNG + 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."); } diff --git a/wwwroot/index.html b/wwwroot/index.html index fad370d..1a3fcee 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -131,6 +131,10 @@ Tool-Nutzung erzwingen (tool_choice: any) +
diff --git a/wwwroot/js/pages/agent-page.js b/wwwroot/js/pages/agent-page.js index 4c96720..e09a2a8 100644 --- a/wwwroot/js/pages/agent-page.js +++ b/wwwroot/js/pages/agent-page.js @@ -21,6 +21,7 @@ registerPage('agent', { const personaEl = document.getElementById('agentPersona'); const instructionsEl = document.getElementById('agentInstructions'); const toolChoiceEl = document.getElementById('agentToolChoice'); + const autoCommitEl = document.getElementById('agentAutoCommit'); const avatarPreview = document.getElementById('avatarPreview'); const avatarInput = document.getElementById('avatarInput'); const avatarBtn = document.getElementById('avatarBtn'); @@ -41,6 +42,7 @@ registerPage('agent', { personaEl.value = agent.persona || ''; instructionsEl.value = agent.instructions || ''; toolChoiceEl.checked = (agent.toolChoice || 'any') === 'any'; + autoCommitEl.checked = !!agent.autoCommit; _agentAvatarData = agent.avatar || null; deleteBtn.hidden = false; @@ -103,6 +105,7 @@ registerPage('agent', { persona: personaEl.value, instructions: instructionsEl.value, toolChoice: toolChoiceEl.checked ? 'any' : 'auto', + autoCommit: autoCommitEl.checked, avatar: _agentAvatarData, customCommands: getCommandsFromUI(commandsList) };