Updates
Rolling release / release (push) Successful in 6m40s

This commit is contained in:
2026-09-12 07:22:47 -04:00
parent e4546f8e95
commit e9040d110a
30 changed files with 1688 additions and 444 deletions
+34 -1
View File
@@ -7,13 +7,19 @@ import { pcmS16le } from '../daemon/voice-adapters.js';
import { WakeEngine } from '../daemon/wake-engine.js';
import { VadSegmenter } from '../daemon/vad.js';
import { PipeWireCapture, pcmRms } from '../daemon/audio-pipewire.js';
import { SentenceBuffer, isMeaningfulTranscript, isSpeakable } from '../daemon/transcript.js';
import { SentenceBuffer, isMeaningfulTranscript, isSpeakable, speakableForTts } from '../daemon/transcript.js';
test('Phase 4 transcript filtering and sentence buffering are deterministic', () => {
assert.equal(isMeaningfulTranscript('[BLANK_AUDIO]'), false);
assert.equal(isMeaningfulTranscript('hi'), false);
assert.equal(isSpeakable('OK.'), true);
assert.equal(isSpeakable('[object Object]'), false);
assert.equal(speakableForTts('Using `run_terminal_cmd`'), "Using 'run terminal cmd'");
assert.equal(speakableForTts('Your IP is 192.168.0.1'), 'Your I P is 192 168 0 1');
assert.equal(
speakableForTts('QVAC fetched https://example.com/ip'),
'Quantum Verse Automatic Computer fetched example dot com slash I P'
);
assert.equal(isMeaningfulTranscript('what time is it'), true);
const out = []; const buffer = new SentenceBuffer({ onSentence: (s) => out.push(s) });
buffer.push('First sentence. Second'); buffer.push(' sentence!'); buffer.flush();
@@ -71,6 +77,33 @@ test('empty TTS still leaves the daemon listening', async () => {
assert.equal(daemon.finished, true);
});
test('multi-sentence speech returns to listening once', async () => {
const daemon = new EventEmitter();
const states = [];
daemon.state = 'SPEAKING';
daemon.voice = {
finishSpeaking() {
daemon.finished = (daemon.finished || 0) + 1;
},
};
daemon.setState = (state) => { daemon.state = state; states.push(state); };
const capture = new EventEmitter(); capture.start = () => {}; capture.stop = () => {};
const wake = new WakeEngine({ detect: () => null });
const loop = new VoiceLoop({
daemon,
capture,
wake,
vad: new VadSegmenter(),
tts: { speak: async () => ({ samples: new Int16Array(2) }) },
playback: { play: async () => {}, stop() {} },
});
loop.status.tts = true;
await loop.speak('Hello there. How are you today?');
assert.equal(daemon.state, 'LISTENING');
assert.equal(daemon.finished, 1);
assert.deepEqual(states, ['LISTENING']);
});
test('PCM packing uses even s16le sample pairs', () => {
const buf = Buffer.alloc(4);
buf.writeInt16LE(256, 0);