Fix: ask_user_choice Dauerschleife bei mehreren aufeinanderfolgenden Choice-Runden

Bug: Bei 2+ aufeinanderfolgenden ask_user_choice-Runden wurden ältere
Choice-Chains nur als Text geladen. Claude sah die früheren tool_use/
tool_result-Paare nicht → kein Kontext über bereits beantwortete Fragen
→ Agent stellte dieselben Fragen erneut (Dauerschleife).

Fix: fullChainStartIndex-Logik traversiert jetzt rückwärts durch alle
zusammenhängenden Choice-Chains (erkannt an tool_result mit Iteration 999).
Alle werden vollständig geladen, damit die gesamte Frage-Antwort-Historie
für Claude sichtbar bleibt.
This commit is contained in:
Meleki committed 2026-03-09 19:44:07 +01:00
1 parent fa947c82ed
commit 1e7b68fb09
3 files changed
+20 -11

No files matched your search

+18 -9
View File
@@ -222,18 +222,27 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop?
var isLastChain = false;
long? lastUserMsgId = null;
// Bestimme welche Chain als "vollständige letzte Chain" gilt.
// Wenn die letzte Chain leer oder nur tool_result enthält (z.B. nach ask_user_choice),
// dann muss die vorletzte Chain vollständig rekonstruiert werden.
// Bestimme ab welcher Chain vollständig geladen werden muss (mit Tool-Calls).
// Bei aufeinanderfolgenden ask_user_choice-Runden entstehen mehrere Chains,
// die alle vollständig geladen werden müssen (tool_use + tool_result Paare).
// Eine Chain braucht die vorherige vollständig, wenn sie:
// - leer ist (gerade erst erstellt für Choice-Antwort)
// - mit einem tool_result beginnt (Antwort auf ask_user_choice der vorherigen Chain)
int fullChainStartIndex = chainsList.Count - 1;
if (chainsList.Count >= 2)
for (int ci = chainsList.Count - 1; ci >= 1; ci--)
{
var lastChainMsgs = (await _db.GetChainMessages(chainsList[chainsList.Count - 1].ChainId)).ToList();
if (lastChainMsgs.Count == 0 ||
(lastChainMsgs.All(m => m.Type == "tool_result") && lastChainMsgs.Count <= 2))
var chainMsgs = (await _db.GetChainMessages(chainsList[ci].ChainId)).ToList();
bool needsPrevious = chainMsgs.Count == 0 ||
chainMsgs.Any(m => m.Type == "tool_result" && m.Iteration == 999);
if (needsPrevious)
{
// Vorletzte Chain hatte einen ask_user_choice → beide Chains vollständig laden
fullChainStartIndex = chainsList.Count - 2;
// Diese Chain enthält eine Choice-Antwort oder ist leer →
// vorherige Chain enthält den zugehörigen tool_use und muss vollständig geladen werden
fullChainStartIndex = ci - 1;
}
else
{
break;
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ Alle Dateipfade in Tool-Aufrufen müssen relativ zu diesem Workspace sein oder a
{
Icon = "fa-question-circle",
Label = "Agent · Rückfragen (AllowUserChoice)",
Content = "## Rückfragen\nWenn du dir bei einer Aufgabe unsicher bist oder es mehrere sinnvolle Wege gibt, nutze das `ask_user_choice`-Tool um dem User eine Auswahlliste zu präsentieren. Nutze es, wenn eine Entscheidung vom User getroffen werden soll."
Content = "## Rückfragen\nWenn du dir bei einer Aufgabe unsicher bist oder es mehrere sinnvolle Wege gibt, nutze das `ask_user_choice`-Tool um dem User eine Auswahlliste zu präsentieren. Nutze es immer, wenn eine Entscheidung vom User getroffen werden soll."
});
}
+1 -1
View File
@@ -71,7 +71,7 @@ public class ToolService
return new
{
name = AskUserChoiceToolName,
description = "Stellt dem User eine Frage mit Auswahlmöglichkeiten, wenn du unsicher bist oder es mehrere sinnvolle Wege gibt. Der User wählt eine Option und du arbeitest mit seiner Antwort weiter. Nutze dies sparsam – nur wenn die Entscheidung wirklich vom User getroffen werden sollte.",
description = "Stellt dem User eine Frage mit Auswahlmöglichkeiten, wenn du unsicher bist oder es mehrere sinnvolle Wege gibt. Der User wählt eine Option und du arbeitest mit seiner Antwort weiter.",
input_schema = new
{
type = "object",