Plan-Modus: System-Prompt-Blöcke kontextabhängig anpassen
- SystemPromptBuilder.BuildBlocks/Build bekommt planMode-Parameter - Im Plan-Modus: Tools-Block zeigt nur Read-only-Tools (read_file, list_files, glob, grep) - Im Plan-Modus: KRITISCH, Verhalten, Erinnerung und Git-Blöcke werden übersprungen - Im Plan-Modus: Skills als 'nicht ausführbar' markiert - Plan-Modus-Block zentral im SystemPromptBuilder statt doppelt in AnthropicService + SessionEndpoint - ChatService reicht planMode an SystemPromptBuilder durch - SessionEndpoint reicht planMode Query-Parameter an BuildBlocks durch - System-Prompt-Modal zeigt korrekte Blöcke je nach Plan-Modus-Status
This commit is contained in:
1 parent
6d95f9aec2
commit
8e0ae90dc6
6 files changed
+55
-32
No files matched your search
@@ -214,7 +214,8 @@ public static class SessionEndpoint
|
||||
var resolvedWorkspace = WorkspaceHelper.ResolveWorkspace(session, user);
|
||||
if (string.IsNullOrEmpty(resolvedWorkspace) && agentSkills.Any())
|
||||
resolvedWorkspace = "/tmp";
|
||||
var blocks = SystemPromptBuilder.BuildBlocks(agent, session, markedMessages, memoryService, agentMemoryDir, agentSkills, skillService, userPersona: user?.GetEffectivePersona(), resolvedWorkspace: resolvedWorkspace);
|
||||
var planMode = ctx.Request.Query.ContainsKey("planMode") && ctx.Request.Query["planMode"] == "true";
|
||||
var blocks = SystemPromptBuilder.BuildBlocks(agent, session, markedMessages, memoryService, agentMemoryDir, agentSkills, skillService, userPersona: user?.GetEffectivePersona(), resolvedWorkspace: resolvedWorkspace, planMode: planMode);
|
||||
|
||||
await ctx.Response.WriteAsJsonAsync(blocks.Select(b => new { b.Icon, b.Label, b.Content }));
|
||||
}
|
||||
|
||||
@@ -59,20 +59,6 @@ public class AnthropicService
|
||||
int reviewRound = 0;
|
||||
string lastStopReason = "";
|
||||
|
||||
// Plan-Modus: System-Prompt-Ergänzung
|
||||
if (planMode && systemPrompt != null)
|
||||
{
|
||||
systemPrompt.Add(new { type = "text", text = @"## Plan-Modus aktiv
|
||||
Der User hat den Plan-Modus aktiviert. Du DARFST KEINE Änderungen vornehmen:
|
||||
- KEINE Dateien erstellen, bearbeiten oder löschen
|
||||
- KEINE Shell-Befehle ausführen die Änderungen vornehmen (Commits, Installationen etc.)
|
||||
- NUR lesen, analysieren, suchen und planen
|
||||
- Nutze read_file, list_files, glob, grep und web_search um den Codebase zu verstehen
|
||||
- Nutze ask_user_choice um Rückfragen zu stellen und Anforderungen zu klären
|
||||
- Erstelle einen strukturierten Plan mit Aufgaben, Abhängigkeiten und Reihenfolge
|
||||
- Der User wird den Plan-Modus deaktivieren wenn du mit der Umsetzung beginnen sollst" });
|
||||
}
|
||||
|
||||
var chain = new ChainRecord
|
||||
{
|
||||
ChainId = chainId,
|
||||
|
||||
@@ -66,7 +66,7 @@ public class ChatService
|
||||
var systemPromptText = SystemPromptBuilder.Build(
|
||||
agent, session, markedMessages, _memoryService, agentMemoryDir,
|
||||
agentSkills, _skillService, userPersona: user?.GetEffectivePersona(),
|
||||
resolvedWorkspace: workspace);
|
||||
resolvedWorkspace: workspace, planMode: planMode);
|
||||
|
||||
var toolChoice = agent.ToolChoice ?? "any";
|
||||
var hasWorkspace = !string.IsNullOrEmpty(workspace);
|
||||
|
||||
@@ -13,7 +13,7 @@ public class PromptBlock
|
||||
|
||||
public static class SystemPromptBuilder
|
||||
{
|
||||
public static List<PromptBlock> BuildBlocks(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, IEnumerable<string> skillSlugs = null, SkillService skillService = null, string userPersona = null, string resolvedWorkspace = null)
|
||||
public static List<PromptBlock> BuildBlocks(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, IEnumerable<string> skillSlugs = null, SkillService skillService = null, string userPersona = null, string resolvedWorkspace = null, bool planMode = false)
|
||||
{
|
||||
var blocks = new List<PromptBlock>();
|
||||
|
||||
@@ -50,7 +50,7 @@ public static class SystemPromptBuilder
|
||||
var effectiveWorkspace = resolvedWorkspace ?? session.Workspace;
|
||||
if (!string.IsNullOrWhiteSpace(effectiveWorkspace))
|
||||
{
|
||||
if (toolAny)
|
||||
if (toolAny && !planMode)
|
||||
{
|
||||
blocks.Add(new PromptBlock
|
||||
{
|
||||
@@ -61,16 +61,32 @@ JEDE Datei-Operation und JEDER Shell-Befehl MUSS über einen Tool-Aufruf erfolge
|
||||
});
|
||||
}
|
||||
|
||||
blocks.Add(new PromptBlock
|
||||
if (planMode)
|
||||
{
|
||||
Icon = "fa-wrench",
|
||||
Label = "Session · Workspace",
|
||||
Content = @$"## Tools
|
||||
blocks.Add(new PromptBlock
|
||||
{
|
||||
Icon = "fa-wrench",
|
||||
Label = "Session · Workspace (Plan-Modus)",
|
||||
Content = @$"## Tools
|
||||
Du hast Read-only-Tools zur Verfügung (read_file, list_files, glob, grep). Benutze sie um den Code zu analysieren und zu verstehen.
|
||||
|
||||
Der Workspace-Pfad ist: `{effectiveWorkspace}`
|
||||
Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder absolute Pfade verwenden, die mit diesem Pfad beginnen."
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks.Add(new PromptBlock
|
||||
{
|
||||
Icon = "fa-wrench",
|
||||
Label = "Session · Workspace",
|
||||
Content = @$"## 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: `{effectiveWorkspace}`
|
||||
Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder absolute Pfade verwenden, die mit diesem Pfad beginnen."
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Rückfragen-Hinweis
|
||||
@@ -113,7 +129,10 @@ Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder a
|
||||
skillNames.Add(skill.Name ?? slug);
|
||||
}
|
||||
var skillLabel = "Agent · Skills: " + string.Join(", ", skillNames);
|
||||
var skillSection = "## Skills\nDu hast folgende Skills zur Verfügung. Nutze sie über das `execute`-Tool wenn der User etwas anfragt, das ein Skill abdeckt.\n\n"
|
||||
var skillIntro = planMode
|
||||
? "## Skills\nFolgende Skills sind verfügbar (im Plan-Modus nur zur Kenntnis – nicht ausführbar):\n\n"
|
||||
: "## Skills\nDu hast folgende Skills zur Verfügung. Nutze sie über das `execute`-Tool wenn der User etwas anfragt, das ein Skill abdeckt.\n\n";
|
||||
var skillSection = skillIntro
|
||||
+ string.Join("\n\n---\n\n", skillParts);
|
||||
blocks.Add(new PromptBlock { Icon = "fa-puzzle-piece", Label = skillLabel, Content = skillSection });
|
||||
}
|
||||
@@ -148,8 +167,8 @@ Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder a
|
||||
blocks.Add(new PromptBlock { Icon = "fa-database", Label = "Agent · Memory (UseMemory)", Content = string.Join("\n", memoryLines) });
|
||||
}
|
||||
|
||||
// Git-Commit-Verhalten: relevant sobald Workspace vorhanden (unabhängig von ToolChoice)
|
||||
if (!string.IsNullOrWhiteSpace(effectiveWorkspace))
|
||||
// Git-Commit-Verhalten: relevant sobald Workspace vorhanden (nicht im Plan-Modus)
|
||||
if (!string.IsNullOrWhiteSpace(effectiveWorkspace) && !planMode)
|
||||
{
|
||||
var autoCommit = (agent.AutoCommit ?? "").ToLowerInvariant();
|
||||
if (autoCommit == "mention")
|
||||
@@ -182,7 +201,7 @@ Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder a
|
||||
// autoCommit == "" → kein Block, Thema wird nicht erwähnt
|
||||
}
|
||||
|
||||
if (toolAny && !string.IsNullOrWhiteSpace(effectiveWorkspace))
|
||||
if (toolAny && !string.IsNullOrWhiteSpace(effectiveWorkspace) && !planMode)
|
||||
{
|
||||
blocks.Add(new PromptBlock
|
||||
{
|
||||
@@ -208,6 +227,22 @@ Diese Regel hat höchste Priorität und gilt für JEDE Antwort: Wenn eine Datei
|
||||
}
|
||||
// kein extra Erinnerungsblock ohne toolAny – Zeilenreferenz-Hinweise kommen direkt über die Nachricht
|
||||
|
||||
// Plan-Modus-Block
|
||||
if (planMode)
|
||||
{
|
||||
blocks.Add(new PromptBlock
|
||||
{
|
||||
Icon = "fa-map",
|
||||
Label = "Plan-Modus aktiv",
|
||||
Content = "## Plan-Modus\nDer User hat den Plan-Modus aktiviert. Du DARFST KEINE Änderungen vornehmen:\n" +
|
||||
"- KEINE Dateien schreiben, editieren oder löschen\n" +
|
||||
"- KEINE Shell-Befehle ausführen (außer read-only wie cat, ls, find, grep)\n" +
|
||||
"- KEINE Commits erstellen\n\n" +
|
||||
"Stattdessen: Analysiere, stelle Rückfragen und erstelle einen detaillierten Plan.\n" +
|
||||
"Der User wird den Plan-Modus deaktivieren wenn du mit der Umsetzung beginnen sollst."
|
||||
});
|
||||
}
|
||||
|
||||
var marked = markedMessages?.Where(m => !string.IsNullOrWhiteSpace(m.Content)).ToList();
|
||||
if (marked != null && marked.Count > 0)
|
||||
{
|
||||
@@ -223,9 +258,9 @@ Diese Regel hat höchste Priorität und gilt für JEDE Antwort: Wenn eine Datei
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public static string Build(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, IEnumerable<string> skillSlugs = null, SkillService skillService = null, string userPersona = null, string resolvedWorkspace = null)
|
||||
public static string Build(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, IEnumerable<string> skillSlugs = null, SkillService skillService = null, string userPersona = null, string resolvedWorkspace = null, bool planMode = false)
|
||||
{
|
||||
var blocks = BuildBlocks(agent, session, markedMessages, memoryService, agentMemoryDir, skillSlugs, skillService, userPersona, resolvedWorkspace);
|
||||
var blocks = BuildBlocks(agent, session, markedMessages, memoryService, agentMemoryDir, skillSlugs, skillService, userPersona, resolvedWorkspace, planMode);
|
||||
return string.Join("\n\n", blocks.Select(b => b.Content));
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -178,8 +178,9 @@ async function apiGetSystemPrompt(sessionId) {
|
||||
return resp.text();
|
||||
}
|
||||
|
||||
async function apiGetSystemPromptBlocks(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/system-prompt-blocks`);
|
||||
async function apiGetSystemPromptBlocks(sessionId, planMode) {
|
||||
const url = `/api/sessions/${sessionId}/system-prompt-blocks` + (planMode ? '?planMode=true' : '');
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) throw new Error('System-Prompt konnte nicht geladen werden');
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
+1
-1
@@ -1338,7 +1338,7 @@ async function showSystemPromptModal(sessionId) {
|
||||
|
||||
// Laden
|
||||
try {
|
||||
const blocks = await apiGetSystemPromptBlocks(sessionId);
|
||||
const blocks = await apiGetSystemPromptBlocks(sessionId, typeof _planModeActive !== 'undefined' && _planModeActive);
|
||||
body.innerHTML = '';
|
||||
_renderSystemPromptBlocks(body, blocks);
|
||||
} catch (e) {
|
||||
|
||||
Reference in new issue
Block a user