File size: 5,696 Bytes
fc93158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import Foundation

enum ToolResultTextFormatter {
    static func format(text: String, toolName: String?) -> String {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else { return "" }

        guard self.looksLikeJSON(trimmed),
              let data = trimmed.data(using: .utf8),
              let json = try? JSONSerialization.jsonObject(with: data)
        else {
            return trimmed
        }

        let normalizedTool = toolName?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
        return self.renderJSON(json, toolName: normalizedTool)
    }

    private static func looksLikeJSON(_ value: String) -> Bool {
        guard let first = value.first else { return false }
        return first == "{" || first == "["
    }

    private static func renderJSON(_ json: Any, toolName: String?) -> String {
        if let dict = json as? [String: Any] {
            return self.renderDictionary(dict, toolName: toolName)
        }
        if let array = json as? [Any] {
            if array.isEmpty { return "No items." }
            return "\(array.count) item\(array.count == 1 ? "" : "s")."
        }
        return ""
    }

    private static func renderDictionary(_ dict: [String: Any], toolName: String?) -> String {
        let status = (dict["status"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines)
        let errorText = self.firstString(in: dict, keys: ["error", "reason"])
        let messageText = self.firstString(in: dict, keys: ["message", "result", "detail"])

        if status?.lowercased() == "error" || errorText != nil {
            if let errorText {
                return "Error: \(self.sanitizeError(errorText))"
            }
            if let messageText {
                return "Error: \(self.sanitizeError(messageText))"
            }
            return "Error"
        }

        if toolName == "nodes", let summary = self.renderNodesSummary(dict) {
            return summary
        }

        if let message = messageText {
            return message
        }

        if let status, !status.isEmpty {
            return "Status: \(status)"
        }

        return ""
    }

    private static func renderNodesSummary(_ dict: [String: Any]) -> String? {
        if let nodes = dict["nodes"] as? [[String: Any]] {
            if nodes.isEmpty { return "No nodes found." }
            var lines: [String] = []
            lines.append("\(nodes.count) node\(nodes.count == 1 ? "" : "s") found.")

            for node in nodes.prefix(3) {
                let label = self.firstString(in: node, keys: ["displayName", "name", "nodeId"]) ?? "Node"
                var details: [String] = []

                if let connected = node["connected"] as? Bool {
                    details.append(connected ? "connected" : "offline")
                }
                if let platform = self.firstString(in: node, keys: ["platform"]) {
                    details.append(platform)
                }
                if let version = self.firstString(in: node, keys: ["osVersion", "appVersion", "version"]) {
                    details.append(version)
                }
                if let pairing = self.pairingDetail(node) {
                    details.append(pairing)
                }

                if details.isEmpty {
                    lines.append("• \(label)")
                } else {
                    lines.append("• \(label) - \(details.joined(separator: ", "))")
                }
            }

            let extra = nodes.count - 3
            if extra > 0 {
                lines.append("... +\(extra) more")
            }
            return lines.joined(separator: "\n")
        }

        if let pending = dict["pending"] as? [Any], let paired = dict["paired"] as? [Any] {
            return "Pairing requests: \(pending.count) pending, \(paired.count) paired."
        }

        if let pending = dict["pending"] as? [Any] {
            if pending.isEmpty { return "No pending pairing requests." }
            return "\(pending.count) pending pairing request\(pending.count == 1 ? "" : "s")."
        }

        return nil
    }

    private static func pairingDetail(_ node: [String: Any]) -> String? {
        if let paired = node["paired"] as? Bool, !paired {
            return "pairing required"
        }

        for key in ["status", "state", "deviceStatus"] {
            if let raw = node[key] as? String, raw.lowercased().contains("pairing required") {
                return "pairing required"
            }
        }
        return nil
    }

    private static func firstString(in dict: [String: Any], keys: [String]) -> String? {
        for key in keys {
            if let value = dict[key] as? String {
                let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
                if !trimmed.isEmpty {
                    return trimmed
                }
            }
        }
        return nil
    }

    private static func sanitizeError(_ raw: String) -> String {
        var cleaned = raw.trimmingCharacters(in: .whitespacesAndNewlines)
        if cleaned.contains("agent="),
           cleaned.contains("action="),
           let marker = cleaned.range(of: ": ")
        {
            cleaned = String(cleaned[marker.upperBound...]).trimmingCharacters(in: .whitespacesAndNewlines)
        }

        if let firstLine = cleaned.split(separator: "\n").first {
            cleaned = String(firstLine).trimmingCharacters(in: .whitespacesAndNewlines)
        }

        if cleaned.count > 220 {
            cleaned = String(cleaned.prefix(217)) + "..."
        }
        return cleaned
    }
}