fix(macos): prevent Voice Wake crash on CJK trigger transcripts (openclaw#11052) thanks @Flash-LHR

Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Flash-LHR <47357603+Flash-LHR@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
Flash-LHR
2026-02-13 10:36:14 +08:00
committed by GitHub
parent 585c9a7265
commit c32b92b7a5
3 changed files with 19 additions and 5 deletions

View File

@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Onboarding/CLI: restore terminal state without resuming paused `stdin`, so onboarding exits cleanly after choosing Web UI and the installer returns instead of appearing stuck.
- macOS Voice Wake: fix a crash in trigger trimming for CJK/Unicode transcripts by matching and slicing on original-string ranges instead of transformed-string indices. (#11052) Thanks @Flash-LHR.
## 2026.2.12

View File

@@ -735,12 +735,13 @@ actor VoiceWakeRuntime {
}
private static func trimmedAfterTrigger(_ text: String, triggers: [String]) -> String {
let lower = text.lowercased()
for trigger in triggers {
let token = trigger.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
guard !token.isEmpty, let range = lower.range(of: token) else { continue }
let after = range.upperBound
let trimmed = text[after...].trimmingCharacters(in: .whitespacesAndNewlines)
let token = trigger.trimmingCharacters(in: .whitespacesAndNewlines)
guard !token.isEmpty else { continue }
guard let range = text.range(
of: token,
options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive]) else { continue }
let trimmed = text[range.upperBound...].trimmingCharacters(in: .whitespacesAndNewlines)
return String(trimmed)
}
return text

View File

@@ -35,6 +35,18 @@ import Testing
#expect(VoiceWakeRuntime._testHasContentAfterTrigger(text, triggers: triggers))
}
@Test func trimsAfterChineseTriggerKeepsPostSpeech() {
let triggers = ["小爪", "openclaw"]
let text = "嘿 小爪 帮我打开设置"
#expect(VoiceWakeRuntime._testTrimmedAfterTrigger(text, triggers: triggers) == "帮我打开设置")
}
@Test func trimsAfterTriggerHandlesWidthInsensitiveForms() {
let triggers = ["openclaw"]
let text = " 请帮我"
#expect(VoiceWakeRuntime._testTrimmedAfterTrigger(text, triggers: triggers) == "请帮我")
}
@Test func gateRequiresGapBetweenTriggerAndCommand() {
let transcript = "hey openclaw do thing"
let segments = makeSegments(