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);
|
var resolvedWorkspace = WorkspaceHelper.ResolveWorkspace(session, user);
|
||||||
if (string.IsNullOrEmpty(resolvedWorkspace) && agentSkills.Any())
|
if (string.IsNullOrEmpty(resolvedWorkspace) && agentSkills.Any())
|
||||||
resolvedWorkspace = "/tmp";
|
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 }));
|
await ctx.Response.WriteAsJsonAsync(blocks.Select(b => new { b.Icon, b.Label, b.Content }));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,20 +59,6 @@ public class AnthropicService
|
|||||||
int reviewRound = 0;
|
int reviewRound = 0;
|
||||||
string lastStopReason = "";
|
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
|
var chain = new ChainRecord
|
||||||
{
|
{
|
||||||
ChainId = chainId,
|
ChainId = chainId,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class ChatService
|
|||||||
var systemPromptText = SystemPromptBuilder.Build(
|
var systemPromptText = SystemPromptBuilder.Build(
|
||||||
agent, session, markedMessages, _memoryService, agentMemoryDir,
|
agent, session, markedMessages, _memoryService, agentMemoryDir,
|
||||||
agentSkills, _skillService, userPersona: user?.GetEffectivePersona(),
|
agentSkills, _skillService, userPersona: user?.GetEffectivePersona(),
|
||||||
resolvedWorkspace: workspace);
|
resolvedWorkspace: workspace, planMode: planMode);
|
||||||
|
|
||||||
var toolChoice = agent.ToolChoice ?? "any";
|
var toolChoice = agent.ToolChoice ?? "any";
|
||||||
var hasWorkspace = !string.IsNullOrEmpty(workspace);
|
var hasWorkspace = !string.IsNullOrEmpty(workspace);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PromptBlock
|
|||||||
|
|
||||||
public static class SystemPromptBuilder
|
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>();
|
var blocks = new List<PromptBlock>();
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public static class SystemPromptBuilder
|
|||||||
var effectiveWorkspace = resolvedWorkspace ?? session.Workspace;
|
var effectiveWorkspace = resolvedWorkspace ?? session.Workspace;
|
||||||
if (!string.IsNullOrWhiteSpace(effectiveWorkspace))
|
if (!string.IsNullOrWhiteSpace(effectiveWorkspace))
|
||||||
{
|
{
|
||||||
if (toolAny)
|
if (toolAny && !planMode)
|
||||||
{
|
{
|
||||||
blocks.Add(new PromptBlock
|
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",
|
blocks.Add(new PromptBlock
|
||||||
Label = "Session · Workspace",
|
{
|
||||||
Content = @$"## Tools
|
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.
|
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}`
|
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."
|
Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder absolute Pfade verwenden, die mit diesem Pfad beginnen."
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rückfragen-Hinweis
|
// 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);
|
skillNames.Add(skill.Name ?? slug);
|
||||||
}
|
}
|
||||||
var skillLabel = "Agent · Skills: " + string.Join(", ", skillNames);
|
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);
|
+ string.Join("\n\n---\n\n", skillParts);
|
||||||
blocks.Add(new PromptBlock { Icon = "fa-puzzle-piece", Label = skillLabel, Content = skillSection });
|
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) });
|
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)
|
// Git-Commit-Verhalten: relevant sobald Workspace vorhanden (nicht im Plan-Modus)
|
||||||
if (!string.IsNullOrWhiteSpace(effectiveWorkspace))
|
if (!string.IsNullOrWhiteSpace(effectiveWorkspace) && !planMode)
|
||||||
{
|
{
|
||||||
var autoCommit = (agent.AutoCommit ?? "").ToLowerInvariant();
|
var autoCommit = (agent.AutoCommit ?? "").ToLowerInvariant();
|
||||||
if (autoCommit == "mention")
|
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
|
// autoCommit == "" → kein Block, Thema wird nicht erwähnt
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toolAny && !string.IsNullOrWhiteSpace(effectiveWorkspace))
|
if (toolAny && !string.IsNullOrWhiteSpace(effectiveWorkspace) && !planMode)
|
||||||
{
|
{
|
||||||
blocks.Add(new PromptBlock
|
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
|
// 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();
|
var marked = markedMessages?.Where(m => !string.IsNullOrWhiteSpace(m.Content)).ToList();
|
||||||
if (marked != null && marked.Count > 0)
|
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;
|
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));
|
return string.Join("\n\n", blocks.Select(b => b.Content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-2
@@ -178,8 +178,9 @@ async function apiGetSystemPrompt(sessionId) {
|
|||||||
return resp.text();
|
return resp.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function apiGetSystemPromptBlocks(sessionId) {
|
async function apiGetSystemPromptBlocks(sessionId, planMode) {
|
||||||
const resp = await fetch(`/api/sessions/${sessionId}/system-prompt-blocks`);
|
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');
|
if (!resp.ok) throw new Error('System-Prompt konnte nicht geladen werden');
|
||||||
return resp.json();
|
return resp.json();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1338,7 +1338,7 @@ async function showSystemPromptModal(sessionId) {
|
|||||||
|
|
||||||
// Laden
|
// Laden
|
||||||
try {
|
try {
|
||||||
const blocks = await apiGetSystemPromptBlocks(sessionId);
|
const blocks = await apiGetSystemPromptBlocks(sessionId, typeof _planModeActive !== 'undefined' && _planModeActive);
|
||||||
body.innerHTML = '';
|
body.innerHTML = '';
|
||||||
_renderSystemPromptBlocks(body, blocks);
|
_renderSystemPromptBlocks(body, blocks);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in new issue
Block a user