refactor(shared): default ToolDisplay config

This commit is contained in:
Peter Steinberger
2026-01-10 16:23:03 +00:00
parent 8bc9209094
commit 701e146c06
2 changed files with 75 additions and 49 deletions

View File

@@ -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
}

View File

@@ -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))"