fix(macos): restore gateway launch agent build

This commit is contained in:
Peter Steinberger
2026-01-12 04:07:28 +00:00
parent 986ff8c59f
commit d26518687a
2 changed files with 39 additions and 37 deletions

View File

@@ -39,7 +39,6 @@ final class CLIInstallPrompter {
guard !self.isPrompting else { return false }
guard AppStateStore.shared.onboardingSeen else { return false }
guard AppStateStore.shared.connectionMode == .local else { return false }
guard !AppStateStore.shared.attachExistingGatewayOnly else { return false }
guard CLIInstaller.installedLocation() == nil else { return false }
guard let version = Self.appVersion() else { return false }
let lastPrompt = UserDefaults.standard.string(forKey: cliInstallPromptedVersionKey)
@@ -47,11 +46,11 @@ final class CLIInstallPrompter {
}
private func installCLI() async {
var lastStatus: String?
let status = StatusBox()
await CLIInstaller.install { message in
lastStatus = message
await status.set(message)
}
if let message = lastStatus {
if let message = await status.get() {
let alert = NSAlert()
alert.messageText = "CLI install finished"
alert.informativeText = message
@@ -71,3 +70,15 @@ final class CLIInstallPrompter {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}
}
private actor StatusBox {
private var value: String?
func set(_ value: String) {
self.value = value
}
func get() -> String? {
self.value
}
}

View File

@@ -7,16 +7,15 @@ enum GatewayLaunchAgentManager {
private static let disableLaunchAgentMarker = ".clawdbot/disable-launchagent"
private enum GatewayProgramArgumentsError: LocalizedError {
case cliNotFound
case message(String)
var errorDescription: String? {
switch self {
case .cliNotFound:
"clawdbot CLI not found in PATH; install the CLI."
case let .message(message):
return message
}
}
}
private static var plistURL: URL {
FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist")
@@ -29,10 +28,10 @@ enum GatewayLaunchAgentManager {
private static func gatewayProgramArguments(
port: Int,
bind: String) -> Result<[String], GatewayProgramArgumentsError>
{
#if DEBUG
bind: String,
) -> Result<[String], GatewayProgramArgumentsError> {
let projectRoot = CommandResolver.projectRoot()
#if DEBUG
if let localBin = CommandResolver.projectClawdbotExecutable(projectRoot: projectRoot) {
return .success([localBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
}
@@ -55,22 +54,18 @@ enum GatewayLaunchAgentManager {
return .success([gatewayBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
}
let fallbackProjectRoot = CommandResolver.projectRoot()
if let entry = CommandResolver.gatewayEntrypoint(in: fallbackProjectRoot) {
switch CommandResolver.runtimeResolution(searchPaths: searchPaths) {
case let .success(runtime):
let cmd = CommandResolver.makeRuntimeCommand(
runtime: runtime,
entrypoint: entry,
subcommand: "gateway-daemon",
extraArgs: ["--port", "\(port)", "--bind", bind])
return .success(cmd)
case .failure:
break
}
if let entry = CommandResolver.gatewayEntrypoint(in: projectRoot),
case let .success(runtime) = CommandResolver.runtimeResolution(searchPaths: searchPaths)
{
let cmd = CommandResolver.makeRuntimeCommand(
runtime: runtime,
entrypoint: entry,
subcommand: "gateway-daemon",
extraArgs: ["--port", "\(port)", "--bind", bind])
return .success(cmd)
}
return .failure(.cliNotFound)
return .failure(.message("clawdbot CLI not found in PATH; install the CLI."))
}
static func isLoaded() async -> Bool {
@@ -82,7 +77,7 @@ enum GatewayLaunchAgentManager {
static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? {
_ = bundlePath
if enabled, self.isLaunchAgentWriteDisabled() {
self.logger.info("launchd enable skipped (attach-only or disable marker set)")
self.logger.info("launchd enable skipped (disable marker set)")
return nil
}
if enabled {
@@ -98,14 +93,13 @@ enum GatewayLaunchAgentManager {
token: desiredToken,
password: desiredPassword)
let programArgumentsResult = self.gatewayProgramArguments(port: port, bind: desiredBind)
let programArguments: [String]
switch programArgumentsResult {
case let .success(args):
programArguments = args
case let .failure(error):
let message = error.errorDescription ?? "Failed to resolve gateway CLI"
self.logger.error("launchd enable failed: \(message)")
return message
guard case let .success(programArguments) = programArgumentsResult else {
if case let .failure(error) = programArgumentsResult {
let message = error.localizedDescription
self.logger.error("launchd enable failed: \(message)")
return message
}
return "Failed to resolve gateway command."
}
// If launchd already loaded the job (common on login), avoid `bootout` unless we must
@@ -336,9 +330,6 @@ enum GatewayLaunchAgentManager {
extension GatewayLaunchAgentManager {
private static func isLaunchAgentWriteDisabled() -> Bool {
if UserDefaults.standard.bool(forKey: attachExistingGatewayOnlyKey) {
return true
}
let marker = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent(self.disableLaunchAgentMarker)
return FileManager.default.fileExists(atPath: marker.path)