diff --git a/apps/macos/Sources/Clawdis/Constants.swift b/apps/macos/Sources/Clawdis/Constants.swift index 2eea34b27..89723312a 100644 --- a/apps/macos/Sources/Clawdis/Constants.swift +++ b/apps/macos/Sources/Clawdis/Constants.swift @@ -22,6 +22,7 @@ let voiceWakeForwardCommandKey = "clawdis.voiceWakeForwardCommand" let modelCatalogPathKey = "clawdis.modelCatalogPath" let modelCatalogReloadKey = "clawdis.modelCatalogReload" let voiceWakeSupported: Bool = ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 26 +let cliHelperSearchPaths = ["/usr/local/bin", "/opt/homebrew/bin"] let defaultVoiceWakeForwardCommand = "clawdis-mac agent --message \"${text}\" --thinking low" let defaultVoiceWakeForwardPort = 22 let defaultVoiceWakeForwardTimeout: TimeInterval = 6 diff --git a/apps/macos/Sources/Clawdis/Utilities.swift b/apps/macos/Sources/Clawdis/Utilities.swift index cf7b2f215..6a04960ed 100644 --- a/apps/macos/Sources/Clawdis/Utilities.swift +++ b/apps/macos/Sources/Clawdis/Utilities.swift @@ -97,7 +97,7 @@ enum CLIInstaller { return } - let targets = ["/usr/local/bin/clawdis-mac", "/opt/homebrew/bin/clawdis-mac"] + let targets = cliHelperSearchPaths.map { "\($0)/clawdis-mac" } let result = await self.privilegedSymlink(source: helper.path, targets: targets) await statusHandler(result) } diff --git a/apps/macos/Sources/Clawdis/VoiceWakeForwarder.swift b/apps/macos/Sources/Clawdis/VoiceWakeForwarder.swift index 4348c767b..ae8b8d589 100644 --- a/apps/macos/Sources/Clawdis/VoiceWakeForwarder.swift +++ b/apps/macos/Sources/Clawdis/VoiceWakeForwarder.swift @@ -11,6 +11,11 @@ struct VoiceWakeForwardConfig: Sendable { enum VoiceWakeForwarder { private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "voicewake.forward") + private static let cliPathPrefix = "PATH=\(cliHelperSearchPaths.joined(separator: ":")):$PATH" + + static func commandWithCliPath(_ command: String) -> String { + "\(self.cliPathPrefix); \(command)" + } enum VoiceWakeForwardError: LocalizedError, Equatable { case invalidTarget @@ -57,7 +62,7 @@ enum VoiceWakeForwarder { args.append(userHost) let rendered = self.renderedCommand(template: config.commandTemplate, transcript: transcript) - args.append(contentsOf: ["sh", "-c", rendered]) + args.append(contentsOf: ["sh", "-c", self.commandWithCliPath(rendered)]) self.logger.info("voice wake forward starting host=\(userHost, privacy: .public)") @@ -134,7 +139,8 @@ enum VoiceWakeForwarder { // Stage 2: ensure remote clawdis-mac is present and responsive. var checkArgs = baseArgs - checkArgs.append(contentsOf: [userHost, "clawdis-mac", "status"]) + let statusCommand = self.commandWithCliPath("clawdis-mac status") + checkArgs.append(contentsOf: [userHost, "sh", "-c", statusCommand]) let checkProc = Process() checkProc.executableURL = URL(fileURLWithPath: "/usr/bin/ssh") checkProc.arguments = checkArgs diff --git a/apps/macos/Tests/ClawdisIPCTests/VoiceWakeForwarderTests.swift b/apps/macos/Tests/ClawdisIPCTests/VoiceWakeForwarderTests.swift index c343dbaaa..e3626bffe 100644 --- a/apps/macos/Tests/ClawdisIPCTests/VoiceWakeForwarderTests.swift +++ b/apps/macos/Tests/ClawdisIPCTests/VoiceWakeForwarderTests.swift @@ -29,4 +29,11 @@ import Testing let command = VoiceWakeForwarder.renderedCommand(template: template, transcript: "ignored") #expect(command == template) } + + @Test func commandPrefersCliInstallPaths() { + let command = VoiceWakeForwarder.commandWithCliPath("clawdis-mac status") + let prefix = "PATH=\(cliHelperSearchPaths.joined(separator: ":")):$PATH; " + #expect(command.hasPrefix(prefix)) + #expect(command.contains("clawdis-mac status")) + } }