Очки: разграничение SttCancel (user/timeout) — выход из режима при тишине 30с, микрофон закрывается при потере фокуса

This commit is contained in:
2026-08-23 21:17:43 +03:00
parent eaca47c443
commit e24caaa684
7 changed files with 129 additions and 17 deletions
@@ -91,10 +91,14 @@ data class SttPhrase(val phrase: String, val full: String) : HostToGlasses
@SerialName("stt_done")
data class SttDone(val full: String) : HostToGlasses
/** Распознавание отменено (двойной клик или 30 с тишины) — текст не выводится. */
/**
* Распознавание отменено — текст не выводится.
* reason="user" — отмена/пустой клик пользователя: очки возвращаются в «слушаю»;
* reason="timeout" — авто-отмена по тишине 30с: очки ВЫХОДЯТ из режима.
*/
@Serializable
@SerialName("stt_cancel")
class SttCancel : HostToGlasses
class SttCancel(val reason: String = "user") : HostToGlasses
/** Один элемент истории сессии (только user/assistant — tool/calls очкам не нужны). */
@Serializable
@@ -221,6 +221,25 @@ class HostToGlassesTest {
assertEquals("""{"type":"stt_cancel"}""", text)
val decoded = json.decodeFromString(HostToGlasses.serializer(), text)
assertIs<SttCancel>(decoded)
assertEquals("user", decoded.reason)
}
@Test
fun sttCancelTimeoutRoundTrip() {
val msg: HostToGlasses = SttCancel(reason = "timeout")
val text = json.encodeToString(HostToGlasses.serializer(), msg)
assertEquals("""{"type":"stt_cancel","reason":"timeout"}""", text)
val decoded = json.decodeFromString(HostToGlasses.serializer(), text)
assertIs<SttCancel>(decoded)
assertEquals("timeout", decoded.reason)
}
@Test
fun sttCancelBackwardCompatibleDefault() {
// Старое сообщение без поля reason десериализуется как "user".
val decoded = json.decodeFromString(HostToGlasses.serializer(), """{"type":"stt_cancel"}""")
assertIs<SttCancel>(decoded)
assertEquals("user", decoded.reason)
}
@Test