Silence placeholder/continuing messages in the tool-call auto-retry path

The tool loop's max-iterations and empty-response fallbacks were showing
placeholder assistant bubbles ("[Tool loop reached maximum iterations]",
"[No response from the model — retrying]") followed by a "↩ Continuing…"
system message before silently re-running. None of that added anything
for the user, so the auto-continue now happens without any visible
message when there's no real content to show; genuine partial content
is still displayed as before, and usage/cost tracking is unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 08:05:07 +02:00
parent e6f965ff19
commit 7119cd1d06
+20 -8
View File
@@ -360,7 +360,6 @@ Don't narrate future actions ("Let me...") - just use the tools.
}
func startAutoContinue() {
showSystemMessage("↩ Continuing…")
silentContinuePrompt = "Please continue from where you left off."
Task { @MainActor in
generateAIResponse(to: "", attachments: nil)
@@ -1475,9 +1474,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
if finalContent.isEmpty {
// Some models (observed with Qwen via OpenRouter) stop calling tools
// after a long tool-call chain but return no summarizing text at all.
// Surface a placeholder and nudge a follow-up turn instead of a silent blank bubble.
// Silently nudge a follow-up turn instead of showing a placeholder bubble.
finishedWithEmptyContent = true
finalContent = "[No response from the model — retrying]"
}
break
}
@@ -1566,9 +1564,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
// If this was the last iteration, note it
if iteration == maxIterations - 1 {
hitIterationLimit = true // We're exiting with pending tool calls
finalContent = response.content.isEmpty
? "[Tool loop reached maximum iterations]"
: response.content
finalContent = response.content
}
}
@@ -1577,8 +1573,24 @@ Don't narrate future actions ("Let me...") - just use the tools.
wasCancelled = true
}
// If we hit the iteration limit or the model returned no text at all, silently
// nudge a follow-up turn instead of showing a placeholder/blank bubble.
let willAutoContinue = (hitIterationLimit || finishedWithEmptyContent) && !wasCancelled
// Display the final response as an assistant message
let responseTime = Date().timeIntervalSince(startTime)
if willAutoContinue && finalContent.isEmpty {
// Nothing worth showing yet still record usage/cost for this turn.
if let usage = totalUsage, let model = selectedModel {
let hasPricing = model.pricing.prompt > 0 || model.pricing.completion > 0
let cost: Double? = hasPricing ? calculateCost(usage: usage, pricing: model.pricing) : nil
sessionStats.addMessage(
inputTokens: usage.promptTokens,
outputTokens: usage.completionTokens,
cost: cost
)
}
} else {
let assistantMessage = Message(
role: .assistant,
content: finalContent,
@@ -1606,12 +1618,12 @@ Don't narrate future actions ("Let me...") - just use the tools.
cost: cost
)
}
}
isGenerating = false
streamingTask = nil
// If we hit the iteration limit, or the model returned no text at all, nudge a follow-up turn
if (hitIterationLimit || finishedWithEmptyContent) && !wasCancelled {
if willAutoContinue {
startAutoContinue()
}