fix(macos): restore gateway launch agent build
This commit is contained in:
@@ -39,7 +39,6 @@ final class CLIInstallPrompter {
|
|||||||
guard !self.isPrompting else { return false }
|
guard !self.isPrompting else { return false }
|
||||||
guard AppStateStore.shared.onboardingSeen else { return false }
|
guard AppStateStore.shared.onboardingSeen else { return false }
|
||||||
guard AppStateStore.shared.connectionMode == .local 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 CLIInstaller.installedLocation() == nil else { return false }
|
||||||
guard let version = Self.appVersion() else { return false }
|
guard let version = Self.appVersion() else { return false }
|
||||||
let lastPrompt = UserDefaults.standard.string(forKey: cliInstallPromptedVersionKey)
|
let lastPrompt = UserDefaults.standard.string(forKey: cliInstallPromptedVersionKey)
|
||||||
@@ -47,11 +46,11 @@ final class CLIInstallPrompter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func installCLI() async {
|
private func installCLI() async {
|
||||||
var lastStatus: String?
|
let status = StatusBox()
|
||||||
await CLIInstaller.install { message in
|
await CLIInstaller.install { message in
|
||||||
lastStatus = message
|
await status.set(message)
|
||||||
}
|
}
|
||||||
if let message = lastStatus {
|
if let message = await status.get() {
|
||||||
let alert = NSAlert()
|
let alert = NSAlert()
|
||||||
alert.messageText = "CLI install finished"
|
alert.messageText = "CLI install finished"
|
||||||
alert.informativeText = message
|
alert.informativeText = message
|
||||||
@@ -71,3 +70,15 @@ final class CLIInstallPrompter {
|
|||||||
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ enum GatewayLaunchAgentManager {
|
|||||||
private static let disableLaunchAgentMarker = ".clawdbot/disable-launchagent"
|
private static let disableLaunchAgentMarker = ".clawdbot/disable-launchagent"
|
||||||
|
|
||||||
private enum GatewayProgramArgumentsError: LocalizedError {
|
private enum GatewayProgramArgumentsError: LocalizedError {
|
||||||
case cliNotFound
|
case message(String)
|
||||||
|
|
||||||
var errorDescription: String? {
|
var errorDescription: String? {
|
||||||
switch self {
|
switch self {
|
||||||
case .cliNotFound:
|
case let .message(message):
|
||||||
"clawdbot CLI not found in PATH; install the CLI."
|
return message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static var plistURL: URL {
|
private static var plistURL: URL {
|
||||||
FileManager.default.homeDirectoryForCurrentUser
|
FileManager.default.homeDirectoryForCurrentUser
|
||||||
.appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist")
|
.appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist")
|
||||||
@@ -29,10 +28,10 @@ enum GatewayLaunchAgentManager {
|
|||||||
|
|
||||||
private static func gatewayProgramArguments(
|
private static func gatewayProgramArguments(
|
||||||
port: Int,
|
port: Int,
|
||||||
bind: String) -> Result<[String], GatewayProgramArgumentsError>
|
bind: String,
|
||||||
{
|
) -> Result<[String], GatewayProgramArgumentsError> {
|
||||||
#if DEBUG
|
|
||||||
let projectRoot = CommandResolver.projectRoot()
|
let projectRoot = CommandResolver.projectRoot()
|
||||||
|
#if DEBUG
|
||||||
if let localBin = CommandResolver.projectClawdbotExecutable(projectRoot: projectRoot) {
|
if let localBin = CommandResolver.projectClawdbotExecutable(projectRoot: projectRoot) {
|
||||||
return .success([localBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
|
return .success([localBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
|
||||||
}
|
}
|
||||||
@@ -55,22 +54,18 @@ enum GatewayLaunchAgentManager {
|
|||||||
return .success([gatewayBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
|
return .success([gatewayBin, "gateway-daemon", "--port", "\(port)", "--bind", bind])
|
||||||
}
|
}
|
||||||
|
|
||||||
let fallbackProjectRoot = CommandResolver.projectRoot()
|
if let entry = CommandResolver.gatewayEntrypoint(in: projectRoot),
|
||||||
if let entry = CommandResolver.gatewayEntrypoint(in: fallbackProjectRoot) {
|
case let .success(runtime) = CommandResolver.runtimeResolution(searchPaths: searchPaths)
|
||||||
switch CommandResolver.runtimeResolution(searchPaths: searchPaths) {
|
{
|
||||||
case let .success(runtime):
|
let cmd = CommandResolver.makeRuntimeCommand(
|
||||||
let cmd = CommandResolver.makeRuntimeCommand(
|
runtime: runtime,
|
||||||
runtime: runtime,
|
entrypoint: entry,
|
||||||
entrypoint: entry,
|
subcommand: "gateway-daemon",
|
||||||
subcommand: "gateway-daemon",
|
extraArgs: ["--port", "\(port)", "--bind", bind])
|
||||||
extraArgs: ["--port", "\(port)", "--bind", bind])
|
return .success(cmd)
|
||||||
return .success(cmd)
|
|
||||||
case .failure:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .failure(.cliNotFound)
|
return .failure(.message("clawdbot CLI not found in PATH; install the CLI."))
|
||||||
}
|
}
|
||||||
|
|
||||||
static func isLoaded() async -> Bool {
|
static func isLoaded() async -> Bool {
|
||||||
@@ -82,7 +77,7 @@ enum GatewayLaunchAgentManager {
|
|||||||
static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? {
|
static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? {
|
||||||
_ = bundlePath
|
_ = bundlePath
|
||||||
if enabled, self.isLaunchAgentWriteDisabled() {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
if enabled {
|
if enabled {
|
||||||
@@ -98,14 +93,13 @@ enum GatewayLaunchAgentManager {
|
|||||||
token: desiredToken,
|
token: desiredToken,
|
||||||
password: desiredPassword)
|
password: desiredPassword)
|
||||||
let programArgumentsResult = self.gatewayProgramArguments(port: port, bind: desiredBind)
|
let programArgumentsResult = self.gatewayProgramArguments(port: port, bind: desiredBind)
|
||||||
let programArguments: [String]
|
guard case let .success(programArguments) = programArgumentsResult else {
|
||||||
switch programArgumentsResult {
|
if case let .failure(error) = programArgumentsResult {
|
||||||
case let .success(args):
|
let message = error.localizedDescription
|
||||||
programArguments = args
|
self.logger.error("launchd enable failed: \(message)")
|
||||||
case let .failure(error):
|
return message
|
||||||
let message = error.errorDescription ?? "Failed to resolve gateway CLI"
|
}
|
||||||
self.logger.error("launchd enable failed: \(message)")
|
return "Failed to resolve gateway command."
|
||||||
return message
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If launchd already loaded the job (common on login), avoid `bootout` unless we must
|
// If launchd already loaded the job (common on login), avoid `bootout` unless we must
|
||||||
@@ -336,9 +330,6 @@ enum GatewayLaunchAgentManager {
|
|||||||
|
|
||||||
extension GatewayLaunchAgentManager {
|
extension GatewayLaunchAgentManager {
|
||||||
private static func isLaunchAgentWriteDisabled() -> Bool {
|
private static func isLaunchAgentWriteDisabled() -> Bool {
|
||||||
if UserDefaults.standard.bool(forKey: attachExistingGatewayOnlyKey) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
let marker = FileManager.default.homeDirectoryForCurrentUser
|
let marker = FileManager.default.homeDirectoryForCurrentUser
|
||||||
.appendingPathComponent(self.disableLaunchAgentMarker)
|
.appendingPathComponent(self.disableLaunchAgentMarker)
|
||||||
return FileManager.default.fileExists(atPath: marker.path)
|
return FileManager.default.fileExists(atPath: marker.path)
|
||||||
|
|||||||
Reference in New Issue
Block a user