openclaw/apps/macos/Sources/Clawdbot/VoiceWakeForwarder.swift

74 lines
2.5 KiB
Swift
Raw Permalink Normal View History

2025-12-07 01:53:33 +01:00
import Foundation
import OSLog
enum VoiceWakeForwarder {
2026-01-04 14:32:47 +00:00
private static let logger = Logger(subsystem: "com.clawdbot", category: "voicewake.forward")
2025-12-07 04:12:54 +01:00
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
}
}
}
2025-12-12 16:09:31 +00:00
struct ForwardOptions: Sendable {
var sessionKey: String = "main"
2025-12-12 16:09:31 +00:00
var thinking: String = "low"
var deliver: Bool = true
var to: String?
2026-01-13 08:11:59 +00:00
var channel: GatewayAgentChannel = .last
2025-12-12 16:09:31 +00:00
}
2025-12-07 15:00:02 +01:00
@discardableResult
2025-12-07 16:35:58 +01:00
static func forward(
transcript: String,
2025-12-12 16:09:31 +00:00
options: ForwardOptions = ForwardOptions()) async -> Result<Void, VoiceWakeForwardError>
2025-12-07 16:35:58 +01:00
{
let payload = Self.prefixedTranscript(transcript)
2026-01-13 08:11:59 +00:00
let deliver = options.channel.shouldDeliver(options.deliver)
let result = await GatewayConnection.shared.sendAgent(GatewayAgentInvocation(
message: payload,
sessionKey: options.sessionKey,
thinking: options.thinking,
deliver: deliver,
to: options.to,
2026-01-13 08:11:59 +00:00
channel: options.channel))
if result.ok {
self.logger.info("voice wake forward ok")
2025-12-07 15:00:02 +01:00
return .success(())
}
let message = result.error ?? "agent rpc unavailable"
self.logger.error("voice wake forward failed: \(message, privacy: .public)")
return .failure(.rpcFailed(message))
2025-12-07 01:53:33 +01:00
}
2025-12-12 16:09:31 +00:00
static func checkConnection() async -> Result<Void, VoiceWakeForwardError> {
let status = await GatewayConnection.shared.status()
if status.ok { return .success(()) }
return .failure(.rpcFailed(status.error ?? "agent rpc unreachable"))
2025-12-07 01:53:33 +01:00
}
}