Files
openclaw/apps/macos/Tests/OpenClawIPCTests/TalkModeRuntimeSpeechTests.swift
Vincent Koc 96b1be10f5 feat(macos): keep MLX TTS model resident (#104200)
* test(macos): cover MLX helper packaging

* feat(macos): define framed MLX TTS protocol

* feat(macos): keep MLX TTS model resident

* feat(macos): reuse MLX TTS helper transport

* fix(macos): preserve MLX TTS fallback lifecycle

* chore(swift): lint MLX TTS protocol sources

* fix(macos): keep MLX helper input nonblocking

* test(macos): cover forced MLX helper shutdown

* fix(macos): fall back after MLX memory eviction

* fix(macos): discard canceled MLX audio
2026-07-11 13:45:27 +08:00

93 lines
4.0 KiB
Swift

import OpenClawKit
import Speech
import Testing
@testable import OpenClaw
struct TalkModeRuntimeSpeechTests {
@Test func `speech request uses dictation defaults`() {
let request = SFSpeechAudioBufferRecognitionRequest()
TalkModeRuntime.configureRecognitionRequest(request)
#expect(request.shouldReportPartialResults)
#expect(request.taskHint == .dictation)
}
@Test func `playback plan routes unsupported local providers through gateway speak`() {
let elevenLabsPlan = TalkModeRuntime.playbackPlan(
provider: "elevenlabs",
apiKey: "key",
voiceId: "voice")
let missingKeyPlan = TalkModeRuntime.playbackPlan(
provider: "elevenlabs",
apiKey: nil,
voiceId: "voice")
let missingVoicePlan = TalkModeRuntime.playbackPlan(
provider: "elevenlabs",
apiKey: "key",
voiceId: nil)
let blankKeyPlan = TalkModeRuntime.playbackPlan(
provider: "elevenlabs",
apiKey: "",
voiceId: "voice")
let openAIPlan = TalkModeRuntime.playbackPlan(provider: "openai", apiKey: nil, voiceId: "onyx")
let customPlan = TalkModeRuntime.playbackPlan(provider: "acme-speech", apiKey: nil, voiceId: nil)
let mlxPlan = TalkModeRuntime.playbackPlan(provider: "mlx", apiKey: nil, voiceId: nil)
let systemPlan = TalkModeRuntime.playbackPlan(provider: "system", apiKey: nil, voiceId: nil)
#expect(elevenLabsPlan == .elevenLabsThenSystemVoice(apiKey: "key", voiceId: "voice"))
#expect(missingKeyPlan == .systemVoiceOnly)
#expect(missingVoicePlan == .systemVoiceOnly)
#expect(blankKeyPlan == .systemVoiceOnly)
#expect(openAIPlan == .gatewayTalkSpeakThenSystemVoice)
#expect(customPlan == .gatewayTalkSpeakThenSystemVoice)
#expect(mlxPlan == .mlxThenSystemVoice)
#expect(systemPlan == .systemVoiceOnly)
}
@Test func `mlx cancellation stops while failures preserve system fallback`() {
#expect(TalkModeRuntime.mlxFailureDisposition(
TalkMLXSpeechSynthesizer.SynthesizeError.canceled) == .canceled)
#expect(TalkModeRuntime.mlxFailureDisposition(
TalkMLXSpeechSynthesizer.SynthesizeError.audioGenerationFailed) == .fallback)
#expect(TalkModeRuntime.mlxFailureDisposition(
TalkMLXSpeechSynthesizer.SynthesizeError.modelLoadFailed("missing")) == .fallback)
}
@Test func `talk speak params carry resolved voice and directive overrides`() {
let params = TalkModeRuntime.makeTalkSpeakParams(
text: "hello",
voiceId: "voice-123",
modelId: "eleven_v3",
outputFormat: "mp3_44100_128",
directive: TalkDirective(
modelId: "eleven_turbo_v2_5",
speed: 1.1,
rateWPM: 180,
stability: 0.4,
similarity: 0.7,
style: 0.2,
speakerBoost: true,
seed: 42,
normalize: "auto",
language: "en",
outputFormat: "mp3_44100_128",
latencyTier: 3))
#expect(params["text"]?.value as? String == "hello")
#expect(params["voiceId"]?.value as? String == "voice-123")
#expect(params["modelId"]?.value as? String == "eleven_turbo_v2_5")
#expect(params["outputFormat"]?.value as? String == "mp3_44100_128")
#expect(params["speed"]?.value as? Double == 1.1)
#expect(params["rateWpm"]?.value as? Int == 180)
#expect(params["stability"]?.value as? Double == 0.4)
#expect(params["similarity"]?.value as? Double == 0.7)
#expect(params["style"]?.value as? Double == 0.2)
#expect(params["speakerBoost"]?.value as? Bool == true)
#expect(params["seed"]?.value as? Int == 42)
#expect(params["normalize"]?.value as? String == "auto")
#expect(params["language"]?.value as? String == "en")
#expect(params["latencyTier"]?.value as? Int == 3)
}
}