From 701e146c0645b6622ba03f7e5af52316f0a493a0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 10 Jan 2026 16:23:03 +0000 Subject: [PATCH] refactor(shared): default ToolDisplay config --- .../Sources/Clawdbot/WorkActivityStore.swift | 45 ----------- .../Sources/ClawdbotKit/ToolDisplay.swift | 79 ++++++++++++++++++- 2 files changed, 75 insertions(+), 49 deletions(-) diff --git a/apps/macos/Sources/Clawdbot/WorkActivityStore.swift b/apps/macos/Sources/Clawdbot/WorkActivityStore.swift index cb89a8953..8ee9aeda9 100644 --- a/apps/macos/Sources/Clawdbot/WorkActivityStore.swift +++ b/apps/macos/Sources/Clawdbot/WorkActivityStore.swift @@ -220,51 +220,6 @@ final class WorkActivityStore { return "\(display.label): \(detail)" } - // Fallback: If the shared tool display config isn't available in this runtime, - // still show a helpful one-liner for the most common tools. - if let args { - func stringArg(_ key: String) -> String? { - let raw = (args[key]?.value as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return raw.isEmpty ? nil : raw - } - - func shortenHome(_ value: String) -> String { - let home = NSHomeDirectory() - guard !home.isEmpty else { return value } - return value.replacingOccurrences(of: home, with: "~") - } - - let toolKey = (name ?? "tool").trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - - if toolKey == "bash" || toolKey == "shell" { - if let cmd = stringArg("command") { - let firstLine = cmd.split(whereSeparator: \.isNewline).first.map(String.init) ?? cmd - let trimmed = firstLine.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { - return "\(display.label): \(trimmed)" - } - } - } - - if toolKey == "read" { - if let path = stringArg("path") { - let offset = args["offset"]?.value as? Double ?? (args["offset"]?.value as? Int).map(Double.init) - let limit = args["limit"]?.value as? Double ?? (args["limit"]?.value as? Int).map(Double.init) - if let offset, let limit { - let end = offset + limit - return "\(display.label): \(shortenHome(path)):\(Int(offset))-\(Int(end))" - } - return "\(display.label): \(shortenHome(path))" - } - } - - if toolKey == "write" || toolKey == "edit" || toolKey == "attach" { - if let path = stringArg("path") { - return "\(display.label): \(shortenHome(path))" - } - } - } - return display.label } diff --git a/apps/shared/ClawdbotKit/Sources/ClawdbotKit/ToolDisplay.swift b/apps/shared/ClawdbotKit/Sources/ClawdbotKit/ToolDisplay.swift index 1f7a88147..c48ef5be8 100644 --- a/apps/shared/ClawdbotKit/Sources/ClawdbotKit/ToolDisplay.swift +++ b/apps/shared/ClawdbotKit/Sources/ClawdbotKit/ToolDisplay.swift @@ -91,16 +91,85 @@ public enum ToolDisplayRegistry { private static func loadConfig() -> ToolDisplayConfig { guard let url = ClawdbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json") else { - return ToolDisplayConfig(version: nil, fallback: nil, tools: nil) + return self.defaultConfig() } do { let data = try Data(contentsOf: url) return try JSONDecoder().decode(ToolDisplayConfig.self, from: data) } catch { - return ToolDisplayConfig(version: nil, fallback: nil, tools: nil) + return self.defaultConfig() } } + private static func defaultConfig() -> ToolDisplayConfig { + ToolDisplayConfig( + version: 1, + fallback: ToolDisplaySpec( + emoji: "🧩", + title: nil, + label: nil, + detailKeys: [ + "command", + "path", + "url", + "targetUrl", + "targetId", + "ref", + "element", + "node", + "nodeId", + "id", + "requestId", + "to", + "channelId", + "guildId", + "userId", + "name", + "query", + "pattern", + "messageId", + ], + actions: nil), + tools: [ + "bash": ToolDisplaySpec( + emoji: "🛠️", + title: "Bash", + label: nil, + detailKeys: ["command"], + actions: nil), + "read": ToolDisplaySpec( + emoji: "📖", + title: "Read", + label: nil, + detailKeys: ["path"], + actions: nil), + "write": ToolDisplaySpec( + emoji: "✍️", + title: "Write", + label: nil, + detailKeys: ["path"], + actions: nil), + "edit": ToolDisplaySpec( + emoji: "📝", + title: "Edit", + label: nil, + detailKeys: ["path"], + actions: nil), + "attach": ToolDisplaySpec( + emoji: "📎", + title: "Attach", + label: nil, + detailKeys: ["path", "url", "fileName"], + actions: nil), + "process": ToolDisplaySpec( + emoji: "🧰", + title: "Process", + label: nil, + detailKeys: ["sessionId"], + actions: nil), + ]) + } + private static func titleFromName(_ name: String) -> String { let cleaned = name.replacingOccurrences(of: "_", with: " ").trimmingCharacters(in: .whitespaces) guard !cleaned.isEmpty else { return "Tool" } @@ -122,8 +191,10 @@ public enum ToolDisplayRegistry { private static func readDetail(_ args: AnyCodable?) -> String? { guard let path = valueForKeyPath(args, path: "path") as? String else { return nil } - let offset = self.valueForKeyPath(args, path: "offset") as? Double - let limit = self.valueForKeyPath(args, path: "limit") as? Double + let offsetAny = self.valueForKeyPath(args, path: "offset") + let limitAny = self.valueForKeyPath(args, path: "limit") + let offset = (offsetAny as? Double) ?? (offsetAny as? Int).map(Double.init) + let limit = (limitAny as? Double) ?? (limitAny as? Int).map(Double.init) if let offset, let limit { let end = offset + limit return "\(path):\(Int(offset))-\(Int(end))"