feat: add exec host approvals flow

This commit is contained in:
Peter Steinberger
2026-01-18 04:27:33 +00:00
parent fa1079214b
commit efdb33c975
30 changed files with 2344 additions and 855 deletions

View File

@@ -1,21 +1,7 @@
import AppKit
import ClawdbotKit
import CoreLocation
import Foundation
enum SystemRunDecision: Sendable {
case allowOnce
case allowAlways
case deny
}
struct SystemRunPromptContext: Sendable {
let command: String
let cwd: String?
let agentId: String?
let executablePath: String?
}
@MainActor
protocol MacNodeRuntimeMainActorServices: Sendable {
func recordScreen(
@@ -31,8 +17,6 @@ protocol MacNodeRuntimeMainActorServices: Sendable {
desiredAccuracy: ClawdbotLocationAccuracy,
maxAgeMs: Int?,
timeoutMs: Int?) async throws -> CLLocation
func confirmSystemRun(context: SystemRunPromptContext) async -> SystemRunDecision
}
@MainActor
@@ -74,38 +58,4 @@ final class LiveMacNodeRuntimeMainActorServices: MacNodeRuntimeMainActorServices
timeoutMs: timeoutMs)
}
func confirmSystemRun(context: SystemRunPromptContext) async -> SystemRunDecision {
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = "Allow this command?"
var details = "Clawdbot wants to run:\n\n\(context.command)"
let trimmedCwd = context.cwd?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !trimmedCwd.isEmpty {
details += "\n\nWorking directory:\n\(trimmedCwd)"
}
let trimmedAgent = context.agentId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !trimmedAgent.isEmpty {
details += "\n\nAgent:\n\(trimmedAgent)"
}
let trimmedPath = context.executablePath?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !trimmedPath.isEmpty {
details += "\n\nExecutable:\n\(trimmedPath)"
}
details += "\n\nThis runs on this Mac via node mode."
alert.informativeText = details
alert.addButton(withTitle: "Allow Once")
alert.addButton(withTitle: "Always Allow")
alert.addButton(withTitle: "Don't Allow")
switch alert.runModal() {
case .alertFirstButtonReturn:
return .allowOnce
case .alertSecondButtonReturn:
return .allowAlways
default:
return .deny
}
}
}