Files
openclaw/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageVisibleText.swift
Peter Steinberger 9dec7acc91 feat(macos): visible-markdown copy, full-message reader, and independent reasoning/tool toggles (#110276)
* feat(clients): copy visible markdown, full-message reader for truncated messages, and independent reasoning/tool toggles

* chore(i18n): translate new reader and trace strings and regenerate catalogs

* test(ios): adopt reader display-options API in render smoke tests
2026-07-18 04:05:50 +01:00

41 lines
1.7 KiB
Swift

import Foundation
/// Plain-text projection of a transcript message: exactly what the reader sees
/// in the bubble, with tool traces and non-text blocks removed. Shared by the
/// transcript exporter and the Listen action so exported and spoken text
/// always match the visible transcript.
enum ChatMessageVisibleText {
static func copyText(in message: OpenClawChatMessage) -> String {
let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
return role == "assistant" ? self.visibleText(in: message) : self.primaryText(in: message)
}
static func visibleText(in message: OpenClawChatMessage) -> String {
let text = self.primaryText(in: message)
let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
guard role != "user" else { return text }
return AssistantTextParser.visibleSegments(from: text)
.map(\.text)
.joined(separator: "\n\n")
}
static func hasVisibleText(in message: OpenClawChatMessage) -> Bool {
!self.visibleText(in: message)
.trimmingCharacters(in: .whitespacesAndNewlines)
.isEmpty
}
private static func primaryText(in message: OpenClawChatMessage) -> String {
let parts = message.content.compactMap { content -> String? in
let kind = (content.type ?? "text").lowercased()
guard kind == "text" || kind.isEmpty else { return nil }
return content.text
}
return OpenClawChatMessage.displayText(
contentText: parts.joined(separator: "\n"),
role: message.role,
stopReason: message.stopReason,
errorMessage: message.errorMessage)
}
}