mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(ios): start incremental speech at soft boundaries (#33305)
Merged via squash.
Prepared head SHA: d1acf72317
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
This commit is contained in:
@@ -1682,6 +1682,8 @@ final class TalkModeManager: NSObject {
|
||||
}
|
||||
|
||||
private struct IncrementalSpeechBuffer {
|
||||
private static let softBoundaryMinChars = 72
|
||||
|
||||
private(set) var latestText: String = ""
|
||||
private(set) var directive: TalkDirective?
|
||||
private var spokenOffset: Int = 0
|
||||
@@ -1774,8 +1776,9 @@ private struct IncrementalSpeechBuffer {
|
||||
}
|
||||
|
||||
if !inCodeBlock {
|
||||
buffer.append(chars[idx])
|
||||
if Self.isBoundary(chars[idx]) {
|
||||
let currentChar = chars[idx]
|
||||
buffer.append(currentChar)
|
||||
if Self.isBoundary(currentChar) || Self.isSoftBoundary(currentChar, bufferedChars: buffer.count) {
|
||||
lastBoundary = idx + 1
|
||||
bufferAtBoundary = buffer
|
||||
inCodeBlockAtBoundary = inCodeBlock
|
||||
@@ -1802,6 +1805,10 @@ private struct IncrementalSpeechBuffer {
|
||||
private static func isBoundary(_ ch: Character) -> Bool {
|
||||
ch == "." || ch == "!" || ch == "?" || ch == "\n"
|
||||
}
|
||||
|
||||
private static func isSoftBoundary(_ ch: Character, bufferedChars: Int) -> Bool {
|
||||
bufferedChars >= Self.softBoundaryMinChars && ch.isWhitespace
|
||||
}
|
||||
}
|
||||
|
||||
extension TalkModeManager {
|
||||
|
||||
28
apps/ios/Tests/TalkModeIncrementalSpeechBufferTests.swift
Normal file
28
apps/ios/Tests/TalkModeIncrementalSpeechBufferTests.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
import Testing
|
||||
@testable import OpenClaw
|
||||
|
||||
@MainActor
|
||||
@Suite struct TalkModeIncrementalSpeechBufferTests {
|
||||
@Test func emitsSoftBoundaryBeforeTerminalPunctuation() {
|
||||
let manager = TalkModeManager(allowSimulatorCapture: true)
|
||||
manager._test_incrementalReset()
|
||||
|
||||
let partial =
|
||||
"We start speaking earlier by splitting this long stream chunk at a whitespace boundary before punctuation arrives"
|
||||
let segments = manager._test_incrementalIngest(partial, isFinal: false)
|
||||
|
||||
#expect(segments.count == 1)
|
||||
#expect(segments[0].count >= 72)
|
||||
#expect(segments[0].count < partial.count)
|
||||
}
|
||||
|
||||
@Test func keepsShortChunkBufferedWithoutPunctuation() {
|
||||
let manager = TalkModeManager(allowSimulatorCapture: true)
|
||||
manager._test_incrementalReset()
|
||||
|
||||
let short = "short chunk without punctuation"
|
||||
let segments = manager._test_incrementalIngest(short, isFinal: false)
|
||||
|
||||
#expect(segments.isEmpty)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user