mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 06:03:39 -06:00
d4fd9cc96a
* fix(ui): restore search media and native text * fix(native): unify visible chat text projection * fix(ui): search composed array schemas * fix(ui): keep config search off startup constraints * fix(ui): honor schema and media path boundaries
81 lines
2.7 KiB
Swift
81 lines
2.7 KiB
Swift
import OpenClawKit
|
|
|
|
public enum OpenClawChatEventText {
|
|
public static func assistantText(from event: OpenClawChatEventPayload) -> String? {
|
|
self.assistantText(fromMessage: event.message)
|
|
}
|
|
|
|
public static func assistantText(fromMessage message: AnyCodable?) -> String? {
|
|
guard let message else { return nil }
|
|
return self.assistantText(fromValue: message.value)
|
|
}
|
|
|
|
private static func assistantText(fromValue value: Any) -> String? {
|
|
if let text = value as? String {
|
|
return self.trimmed(text)
|
|
}
|
|
|
|
guard let object = self.dictionary(from: value) else { return nil }
|
|
if let role = self.stringValue(object["role"])?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
!role.isEmpty,
|
|
role.lowercased() != "assistant"
|
|
{
|
|
return nil
|
|
}
|
|
|
|
guard let content = object["content"] else { return nil }
|
|
return self.textContent(from: content)
|
|
}
|
|
|
|
private static func textContent(from value: Any) -> String? {
|
|
if let text = value as? String {
|
|
return self.trimmed(text)
|
|
}
|
|
|
|
let parts: [String] = if let array = value as? [AnyCodable] {
|
|
array.compactMap { self.textContentPart(from: $0.value) }
|
|
} else if let array = value as? [Any] {
|
|
array.compactMap { self.textContentPart(from: $0) }
|
|
} else {
|
|
self.textContentPart(from: value).map { [$0] } ?? []
|
|
}
|
|
|
|
return self.trimmed(parts.joined(separator: "\n"))
|
|
}
|
|
|
|
private static func textContentPart(from value: Any) -> String? {
|
|
if let text = value as? String {
|
|
return self.trimmed(text)
|
|
}
|
|
guard let object = self.dictionary(from: value) else { return nil }
|
|
guard ChatMessageVisibleText.isVisibleContentType(
|
|
self.stringValue(object["type"]),
|
|
role: "assistant")
|
|
else { return nil }
|
|
return self.trimmed(self.stringValue(object["text"]) ?? "")
|
|
}
|
|
|
|
private static func dictionary(from value: Any) -> [String: Any]? {
|
|
if let dict = value as? [String: AnyCodable] {
|
|
return dict.mapValues(\.value)
|
|
}
|
|
if let dict = value as? [String: Any] {
|
|
return dict
|
|
}
|
|
return nil
|
|
}
|
|
|
|
private static func stringValue(_ value: Any?) -> String? {
|
|
if let string = value as? String { return string }
|
|
if let wrapped = value as? AnyCodable {
|
|
return self.stringValue(wrapped.value)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
private static func trimmed(_ text: String) -> String? {
|
|
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
return trimmed.isEmpty ? nil : trimmed
|
|
}
|
|
}
|