fix: delay logic waits for post-trigger content
parent
912a7a1781
commit
a5fbfa3748
|
|
@ -144,8 +144,9 @@ actor VoiceWakeRuntime {
|
||||||
if !transcript.isEmpty {
|
if !transcript.isEmpty {
|
||||||
self.lastHeard = now
|
self.lastHeard = now
|
||||||
if self.isCapturing {
|
if self.isCapturing {
|
||||||
self.capturedTranscript = Self.trimmedAfterTrigger(transcript, triggers: config.triggers)
|
let trimmed = Self.trimmedAfterTrigger(transcript, triggers: config.triggers)
|
||||||
self.updateHeardBeyondTrigger(with: transcript)
|
self.capturedTranscript = trimmed
|
||||||
|
self.updateHeardBeyondTrigger(withTrimmed: trimmed)
|
||||||
let snapshot = self.capturedTranscript
|
let snapshot = self.capturedTranscript
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
VoiceWakeOverlayController.shared.showPartial(transcript: snapshot)
|
VoiceWakeOverlayController.shared.showPartial(transcript: snapshot)
|
||||||
|
|
@ -176,10 +177,11 @@ actor VoiceWakeRuntime {
|
||||||
|
|
||||||
private func beginCapture(transcript: String, config: RuntimeConfig) async {
|
private func beginCapture(transcript: String, config: RuntimeConfig) async {
|
||||||
self.isCapturing = true
|
self.isCapturing = true
|
||||||
self.capturedTranscript = Self.trimmedAfterTrigger(transcript, triggers: config.triggers)
|
let trimmed = Self.trimmedAfterTrigger(transcript, triggers: config.triggers)
|
||||||
|
self.capturedTranscript = trimmed
|
||||||
self.captureStartedAt = Date()
|
self.captureStartedAt = Date()
|
||||||
self.cooldownUntil = nil
|
self.cooldownUntil = nil
|
||||||
self.heardBeyondTrigger = self.textHasBeyondTriggerContent(transcript)
|
self.heardBeyondTrigger = !trimmed.isEmpty
|
||||||
|
|
||||||
let snapshot = self.capturedTranscript
|
let snapshot = self.capturedTranscript
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
|
@ -236,15 +238,8 @@ actor VoiceWakeRuntime {
|
||||||
|
|
||||||
await MainActor.run { AppStateStore.shared.stopVoiceEars() }
|
await MainActor.run { AppStateStore.shared.stopVoiceEars() }
|
||||||
|
|
||||||
guard !finalTranscript.isEmpty else {
|
|
||||||
await MainActor.run { VoiceWakeOverlayController.shared.dismiss(reason: .empty) }
|
|
||||||
self.cooldownUntil = Date().addingTimeInterval(self.debounceAfterSend)
|
|
||||||
self.restartRecognizer()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let forwardConfig = await MainActor.run { AppStateStore.shared.voiceWakeForwardConfig }
|
let forwardConfig = await MainActor.run { AppStateStore.shared.voiceWakeForwardConfig }
|
||||||
let delay: TimeInterval = heardBeyondTrigger ? 1.0 : 3.0
|
let delay: TimeInterval = (heardBeyondTrigger && !finalTranscript.isEmpty) ? 1.0 : 3.0
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
VoiceWakeOverlayController.shared.presentFinal(
|
VoiceWakeOverlayController.shared.presentFinal(
|
||||||
transcript: finalTranscript,
|
transcript: finalTranscript,
|
||||||
|
|
@ -265,13 +260,8 @@ actor VoiceWakeRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func textHasBeyondTriggerContent(_ text: String) -> Bool {
|
private func updateHeardBeyondTrigger(withTrimmed trimmed: String) {
|
||||||
let words = text.split(whereSeparator: { $0.isWhitespace })
|
if !self.heardBeyondTrigger, !trimmed.isEmpty {
|
||||||
return words.count > 1
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateHeardBeyondTrigger(with transcript: String) {
|
|
||||||
if !self.heardBeyondTrigger, self.textHasBeyondTriggerContent(transcript) {
|
|
||||||
self.heardBeyondTrigger = true
|
self.heardBeyondTrigger = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -292,6 +282,10 @@ actor VoiceWakeRuntime {
|
||||||
static func _testTrimmedAfterTrigger(_ text: String, triggers: [String]) -> String {
|
static func _testTrimmedAfterTrigger(_ text: String, triggers: [String]) -> String {
|
||||||
self.trimmedAfterTrigger(text, triggers: triggers)
|
self.trimmedAfterTrigger(text, triggers: triggers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func _testHasContentAfterTrigger(_ text: String, triggers: [String]) -> Bool {
|
||||||
|
!self.trimmedAfterTrigger(text, triggers: triggers).isEmpty
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
|
||||||
|
|
@ -35,4 +35,16 @@ import Testing
|
||||||
let text = "hello buddy this is after trigger claude also here"
|
let text = "hello buddy this is after trigger claude also here"
|
||||||
#expect(VoiceWakeRuntime._testTrimmedAfterTrigger(text, triggers: triggers) == "this is after trigger claude also here")
|
#expect(VoiceWakeRuntime._testTrimmedAfterTrigger(text, triggers: triggers) == "this is after trigger claude also here")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test func hasContentAfterTriggerFalseWhenOnlyTrigger() {
|
||||||
|
let triggers = ["clawd"]
|
||||||
|
let text = "hey clawd"
|
||||||
|
#expect(!VoiceWakeRuntime._testHasContentAfterTrigger(text, triggers: triggers))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func hasContentAfterTriggerTrueWhenSpeechContinues() {
|
||||||
|
let triggers = ["claude"]
|
||||||
|
let text = "claude write a note"
|
||||||
|
#expect(VoiceWakeRuntime._testHasContentAfterTrigger(text, triggers: triggers))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue