fix(voice): 30 s and Manual outlast silent Web Speech runs

_onWebSpeechEnd counted every run that ended without a result toward the
two-retry cap, however long the run lasted. Under 30 s or Manual, each
no-speech window of the engine is one silent run, so the third ended the
recording at about 18 s of silence, before the deadline, and Manual
stopped on its own. Both recognition.start() sites now stamp the run start;
an empty run counts toward the cap only when it ended within a second of
starting (a recognizer that cannot listen), and any other run resets it.
The 250 ms backoff is unchanged.

The vm harness in test/voice-silence-timeout.test.ts now passes the test's
Date into the context, whose own Date ignores fake timers.

Also from review: the VoiceInput stubs of the four settings-ui.js tests
carry SILENCE_TIMEOUT_SECONDS; Settings-Reference lists Stop after silence;
the touchscreen Linux fallback leaves out ChromeOS and says a touch Linux
laptop still matches; the dead _webSpeechStream teardown is gone; the two
voice tests use vitest expect instead of node:assert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ludo FourrageandClaude Opus 5.5 committed 2026-11-09 07:57:14 -08:00
1 parent 2d7cd46565
commit 308de1fd4d
11 files changed
+139 -98

No files matched your search

+4 -2
View File
@@ -87,8 +87,10 @@ Speech. Final transcript events no longer stop Deepgram or Web Speech immediatel
they wait for the configured silence deadline. The timeout counts from the latest
transcript update. A browser can still end its native recognition run; extended
and Manual dictation restart it while preserving the text and silence deadline.
Connection failures, microphone errors, or repeated empty recognition runs can
still end a recording.
A silent run that lasts its full length never ends one, so 30 seconds and Manual
survive long pauses. Connection failures, microphone errors, or a recognizer that
keeps ending within a second of starting without hearing anything can still end
a recording.
On Chrome for Android, live words replace earlier partial results without repeating
them in the input. The browser microphone bars indicate speech activity; streaming
+3 -2
View File
@@ -247,8 +247,9 @@ Discord group for the two-way bot (token, IDs, thread and ping options; see
### Voice
Active provider and the engine behind it, insert mode, language, domain keywords to bias
recognition, the Deepgram API key, and the opt-in switch for transcribing through this
server's Claude login, with its live credential status. See
recognition, **Stop after silence** (provider default, 3, 6, 15 or 30 seconds, or Manual),
the Deepgram API key, and the opt-in switch for transcribing through this server's Claude
login, with its live credential status. See
[Input And Voice](Input-And-Voice).
### Shortcuts