Bugfix: Lingering error in image generation from image gen. models

This commit is contained in:
2026-03-04 11:52:18 +01:00
parent 49f842f119
commit 305abfa85d
6 changed files with 137 additions and 43 deletions

View File

@@ -1265,6 +1265,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
private func generateAIResponseWithTools(provider: AIProvider, modelId: String) {
let mcp = MCPService.shared
Log.ui.info("generateAIResponseWithTools: model=\(modelId)")
isGenerating = true
streamingTask?.cancel()
@@ -1351,6 +1352,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
let maxIterations = 10 // Increased from 5 to reduce hitting client-side limit
var finalContent = ""
var finalImages: [Data] = []
var didContinueAfterImages = false // Only inject temp-file continuation once
var totalUsage: ChatResponse.Usage?
var hitIterationLimit = false // Track if we exited due to hitting the limit
@@ -1379,9 +1382,32 @@ Don't narrate future actions ("Let me...") - just use the tools.
let toolCalls = structuredCalls.isEmpty ? textCalls : structuredCalls
guard !toolCalls.isEmpty else {
// No tool calls this is the final text response
// Strip any unparseable tool call text from display
// No tool calls this is the final response
finalContent = response.content
if let images = response.generatedImages { finalImages = images }
Log.ui.debug("Tools final response: content='\(response.content.prefix(80))', images=\(response.generatedImages?.count ?? 0)")
// If images were generated and tools are available, save to temp files
// and continue the loop so the model can save them to the requested path.
if !finalImages.isEmpty && !didContinueAfterImages && iteration < maxIterations - 1 {
didContinueAfterImages = true
let timestamp = Int(Date().timeIntervalSince1970)
let tempPaths: [String] = finalImages.enumerated().compactMap { i, imgData in
let path = "/tmp/oai_generated_\(timestamp)_\(i).png"
let ok = FileManager.default.createFile(atPath: path, contents: imgData)
Log.ui.debug("Saved generated image to temp: \(path) ok=\(ok)")
return ok ? path : nil
}
if !tempPaths.isEmpty {
let pathList = tempPaths.joined(separator: ", ")
let assistantContent = response.content.isEmpty ? "[Image generated]" : response.content
apiMessages.append(["role": "assistant", "content": assistantContent])
apiMessages.append(["role": "user", "content": "The image(s) have been generated and temporarily saved to: \(pathList). Please save them to the requested destination(s) using the available tools (bash or MCP write)."])
finalImages = []
finalContent = ""
continue
}
}
break
}
@@ -1491,7 +1517,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
attachments: nil,
responseTime: responseTime,
wasInterrupted: wasCancelled,
modelId: modelId
modelId: modelId,
generatedImages: finalImages.isEmpty ? nil : finalImages
)
messages.append(assistantMessage)
@@ -1935,12 +1962,11 @@ Don't narrate future actions ("Let me...") - just use the tools.
func detectGoodbyePhrase(in text: String) -> Bool {
let lowercased = text.lowercased()
let goodbyePhrases = [
"bye", "goodbye", "bye bye",
"thanks", "thank you", "thx", "ty",
"bye", "goodbye", "bye bye", "good bye",
"that's all", "thats all", "that'll be all",
"done", "i'm done", "we're done",
"i'm done", "we're done",
"see you", "see ya", "catch you later",
"have a good", "have a nice"
"have a good day", "have a nice day"
]
return goodbyePhrases.contains { phrase in