feat: add system.which bin probe
This commit is contained in:
@@ -164,6 +164,7 @@ final class MacNodeModeCoordinator {
|
||||
]
|
||||
|
||||
if SystemRunPolicy.load() != .never {
|
||||
commands.append(ClawdbotSystemCommand.which.rawValue)
|
||||
commands.append(ClawdbotSystemCommand.run.rawValue)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ actor MacNodeRuntime {
|
||||
return try await self.handleScreenRecordInvoke(req)
|
||||
case ClawdbotSystemCommand.run.rawValue:
|
||||
return try await self.handleSystemRun(req)
|
||||
case ClawdbotSystemCommand.which.rawValue:
|
||||
return try await self.handleSystemWhich(req)
|
||||
case ClawdbotSystemCommand.notify.rawValue:
|
||||
return try await self.handleSystemNotify(req)
|
||||
default:
|
||||
@@ -494,6 +496,33 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
}
|
||||
|
||||
private func handleSystemWhich(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let params = try Self.decodeParams(ClawdbotSystemWhichParams.self, from: req.paramsJSON)
|
||||
let bins = params.bins
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
guard !bins.isEmpty else {
|
||||
return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: bins required")
|
||||
}
|
||||
|
||||
let searchPaths = CommandResolver.preferredPaths()
|
||||
var matches: [String] = []
|
||||
var paths: [String: String] = [:]
|
||||
for bin in bins {
|
||||
if let path = CommandResolver.findExecutable(named: bin, searchPaths: searchPaths) {
|
||||
matches.append(bin)
|
||||
paths[bin] = path
|
||||
}
|
||||
}
|
||||
|
||||
struct WhichPayload: Encodable {
|
||||
let bins: [String]
|
||||
let paths: [String: String]
|
||||
}
|
||||
let payload = try Self.encodePayload(WhichPayload(bins: matches, paths: paths))
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
}
|
||||
|
||||
private func handleSystemNotify(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let params = try Self.decodeParams(ClawdbotSystemNotifyParams.self, from: req.paramsJSON)
|
||||
let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
@@ -21,6 +21,15 @@ struct MacNodeRuntimeTests {
|
||||
#expect(response.ok == false)
|
||||
}
|
||||
|
||||
@Test func handleInvokeRejectsEmptySystemWhich() async throws {
|
||||
let runtime = MacNodeRuntime()
|
||||
let params = ClawdbotSystemWhichParams(bins: [])
|
||||
let json = try String(data: JSONEncoder().encode(params), encoding: .utf8)
|
||||
let response = await runtime.handleInvoke(
|
||||
BridgeInvokeRequest(id: "req-2b", command: ClawdbotSystemCommand.which.rawValue, paramsJSON: json))
|
||||
#expect(response.ok == false)
|
||||
}
|
||||
|
||||
@Test func handleInvokeRejectsEmptyNotification() async throws {
|
||||
let runtime = MacNodeRuntime()
|
||||
let params = ClawdbotSystemNotifyParams(title: "", body: "")
|
||||
|
||||
@@ -2,6 +2,7 @@ import Foundation
|
||||
|
||||
public enum ClawdbotSystemCommand: String, Codable, Sendable {
|
||||
case run = "system.run"
|
||||
case which = "system.which"
|
||||
case notify = "system.notify"
|
||||
}
|
||||
|
||||
@@ -39,6 +40,14 @@ public struct ClawdbotSystemRunParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotSystemWhichParams: Codable, Sendable, Equatable {
|
||||
public var bins: [String]
|
||||
|
||||
public init(bins: [String]) {
|
||||
self.bins = bins
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotSystemNotifyParams: Codable, Sendable, Equatable {
|
||||
public var title: String
|
||||
public var body: String
|
||||
|
||||
Reference in New Issue
Block a user