import Foundation import OSLog enum VoiceWakeForwarder { private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "voicewake.forward") static func prefixedTranscript(_ transcript: String, machineName: String? = nil) -> String { let resolvedMachine = machineName .flatMap { name -> String? in let trimmed = name.trimmingCharacters(in: .whitespacesAndNewlines) return trimmed.isEmpty ? nil : trimmed } ?? Host.current().localizedName ?? ProcessInfo.processInfo.hostName let safeMachine = resolvedMachine.isEmpty ? "this Mac" : resolvedMachine return """ User talked via voice recognition on \(safeMachine) - repeat prompt first \ + remember some words might be incorrectly transcribed. \(transcript) """ } enum VoiceWakeForwardError: LocalizedError, Equatable { case rpcFailed(String) var errorDescription: String? { switch self { case let .rpcFailed(message): message } } } struct ForwardOptions: Sendable { var sessionKey: String = "main" var thinking: String = "low" var deliver: Bool = true var to: String? var channel: String = "last" } @discardableResult static func forward( transcript: String, options: ForwardOptions = ForwardOptions()) async -> Result { let payload = Self.prefixedTranscript(transcript) let channel = options.channel.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() let deliver = options.deliver && channel != "webchat" let result = await AgentRPC.shared.send( text: payload, thinking: options.thinking, sessionKey: options.sessionKey, deliver: deliver, to: options.to, channel: channel) if result.ok { self.logger.info("voice wake forward ok") return .success(()) } let message = result.error ?? "agent rpc unavailable" self.logger.error("voice wake forward failed: \(message, privacy: .public)") return .failure(.rpcFailed(message)) } static func checkConnection() async -> Result { let status = await AgentRPC.shared.status() if status.ok { return .success(()) } return .failure(.rpcFailed(status.error ?? "agent rpc unreachable")) } }