iCloud Backup, better chatview exp. bugfixes++

This commit is contained in:
2026-02-27 14:05:11 +01:00
parent 3997f3feee
commit e9d0ad3c66
11 changed files with 634 additions and 30 deletions

View File

@@ -295,6 +295,9 @@ Don't narrate future actions ("Let me...") - just use the tools.
func sendMessage() {
guard !inputText.trimmingCharacters(in: .whitespaces).isEmpty else { return }
// If already generating, cancel first new message becomes a followup in context
if isGenerating { cancelGeneration() }
let trimmedInput = inputText.trimmingCharacters(in: .whitespaces)
// Handle slash escape: "//" becomes "/"
@@ -382,6 +385,11 @@ Don't narrate future actions ("Let me...") - just use the tools.
MCPService.shared.resetBashSessionApproval()
messages = loadedMessages
// Track identity so S can re-save under the same name
currentConversationId = conversation.id
currentConversationName = conversation.name
savedMessageCount = loadedMessages.filter { $0.role != .system }.count
// Rebuild session stats from loaded messages
for msg in loadedMessages {
sessionStats.addMessage(
@@ -1248,7 +1256,10 @@ Don't narrate future actions ("Let me...") - just use the tools.
var apiMessages: [[String: Any]] = [systemPrompt] + messagesToSend.map { msg in
let hasAttachments = msg.attachments?.contains(where: { $0.data != nil }) ?? false
if hasAttachments {
var contentArray: [[String: Any]] = [["type": "text", "text": msg.content]]
var contentArray: [[String: Any]] = []
if !msg.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
contentArray.append(["type": "text", "text": msg.content])
}
for attachment in msg.attachments ?? [] {
guard let data = attachment.data else { continue }
switch attachment.type {
@@ -1264,7 +1275,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
}
return ["role": msg.role.rawValue, "content": contentArray]
}
return ["role": msg.role.rawValue, "content": msg.content]
let content = msg.content.trimmingCharacters(in: .whitespacesAndNewlines)
return ["role": msg.role.rawValue, "content": content.isEmpty ? "[Image]" : content]
}
// If this is a silent auto-continue, inject the prompt into the API call only
@@ -1311,7 +1323,13 @@ Don't narrate future actions ("Let me...") - just use the tools.
// Show what tools the model is calling
let toolNames = toolCalls.map { $0.functionName }.joined(separator: ", ")
showSystemMessage("🔧 Calling: \(toolNames)")
let toolMsgId = showSystemMessage("🔧 Calling: \(toolNames)")
// Initialise detail entries with inputs (results fill in below)
var toolDetails: [ToolCallDetail] = toolCalls.map { tc in
ToolCallDetail(name: tc.functionName, input: tc.arguments, result: nil)
}
updateToolCallMessage(id: toolMsgId, details: toolDetails)
let usingTextCalls = !textCalls.isEmpty
@@ -1340,7 +1358,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
// Execute each tool and append results
var toolResultLines: [String] = []
for tc in toolCalls {
for (i, tc) in toolCalls.enumerated() {
if Task.isCancelled {
wasCancelled = true
break
@@ -1362,6 +1380,10 @@ Don't narrate future actions ("Let me...") - just use the tools.
resultJSON = "{\"error\": \"Failed to serialize result\"}"
}
// Update the detail entry with the result so the UI can show it
toolDetails[i].result = resultJSON
updateToolCallMessage(id: toolMsgId, details: toolDetails)
if usingTextCalls {
// Inject results as a user message for text-call models
toolResultLines.append("Tool result for \(tc.functionName):\n\(resultJSON)")
@@ -1462,7 +1484,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
}
}
private func showSystemMessage(_ text: String) {
@discardableResult
private func showSystemMessage(_ text: String) -> UUID {
let message = Message(
role: .system,
content: text,
@@ -1472,6 +1495,13 @@ Don't narrate future actions ("Let me...") - just use the tools.
attachments: nil
)
messages.append(message)
return message.id
}
private func updateToolCallMessage(id: UUID, details: [ToolCallDetail]) {
if let idx = messages.firstIndex(where: { $0.id == id }) {
messages[idx].toolCalls = details
}
}
// MARK: - Error Helpers