feat(deeplink): forward agent links via bridge

This commit is contained in:
Peter Steinberger
2025-12-13 01:18:48 +00:00
parent a56daa6c06
commit 378e5acd23
6 changed files with 177 additions and 65 deletions

View File

@@ -145,6 +145,31 @@ actor BridgeServer {
deliver: false,
to: nil,
channel: "last")
case "agent.request":
guard let json = evt.payloadJSON, let data = json.data(using: .utf8) else {
return
}
guard let link = try? JSONDecoder().decode(AgentDeepLink.self, from: data) else {
return
}
let message = link.message.trimmingCharacters(in: .whitespacesAndNewlines)
guard !message.isEmpty else { return }
guard message.count <= 20000 else { return }
let sessionKey = link.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty
?? "node-\(nodeId)"
let thinking = link.thinking?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty
let to = link.to?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty
let channel = link.channel?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty
_ = await AgentRPC.shared.send(
text: message,
thinking: thinking,
sessionKey: sessionKey,
deliver: link.deliver,
to: to,
channel: channel ?? "last")
default:
break
}

View File

@@ -1,59 +1,11 @@
import AppKit
import ClawdisNodeKit
import Foundation
import OSLog
import Security
private let deepLinkLogger = Logger(subsystem: "com.steipete.clawdis", category: "DeepLink")
enum DeepLinkRoute: Sendable, Equatable {
case agent(AgentDeepLink)
}
struct AgentDeepLink: Sendable, Equatable {
let message: String
let sessionKey: String?
let thinking: String?
let deliver: Bool
let to: String?
let channel: String?
let timeoutSeconds: Int?
let key: String?
}
enum DeepLinkParser {
static func parse(_ url: URL) -> DeepLinkRoute? {
guard url.scheme?.lowercased() == "clawdis" else { return nil }
guard let host = url.host?.lowercased(), !host.isEmpty else { return nil }
guard let comps = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return nil }
let query = (comps.queryItems ?? []).reduce(into: [String: String]()) { dict, item in
guard let value = item.value else { return }
dict[item.name] = value
}
switch host {
case "agent":
guard let message = query["message"], !message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
return nil
}
let deliver = (query["deliver"] as NSString?)?.boolValue ?? false
let timeoutSeconds = query["timeoutSeconds"].flatMap { Int($0) }.flatMap { $0 >= 0 ? $0 : nil }
return .agent(
.init(
message: message,
sessionKey: query["sessionKey"],
thinking: query["thinking"],
deliver: deliver,
to: query["to"],
channel: query["channel"],
timeoutSeconds: timeoutSeconds,
key: query["key"]))
default:
return nil
}
}
}
@MainActor
final class DeepLinkHandler {
static let shared = DeepLinkHandler()
@@ -128,7 +80,7 @@ final class DeepLinkHandler {
// MARK: - Auth
static func currentKey() -> String {
Self.expectedKey()
self.expectedKey()
}
private static func expectedKey() -> String {