+33
-3
@@ -102,13 +102,40 @@ export class JarvisDaemon extends EventEmitter {
|
||||
if (this.state === 'SPEAKING') this.setState('LISTENING');
|
||||
}
|
||||
_speakReply(spoken) {
|
||||
const playing = this.voiceLoop?.speak?.(spoken);
|
||||
if (!playing) { this._finishSpeech(); return; }
|
||||
Promise.resolve(playing).catch((error) => {
|
||||
const play = async () => {
|
||||
await this.ensureTts();
|
||||
const playing = this.voiceLoop?.speak?.(spoken);
|
||||
if (!playing) {
|
||||
const reason = this.voiceLoop?.status?.errors?.tts;
|
||||
if (reason && reason !== 'Spoken replies are disabled') this.emit('Error', 'TTS', reason);
|
||||
this._finishSpeech();
|
||||
return;
|
||||
}
|
||||
await playing;
|
||||
};
|
||||
Promise.resolve(play()).catch((error) => {
|
||||
this.emit('Error', 'TTS', error.message);
|
||||
if (this.state === 'SPEAKING') this._finishSpeech();
|
||||
});
|
||||
}
|
||||
async ensureTts() {
|
||||
if (!this.voiceLoop) return;
|
||||
const settings = voiceSettings();
|
||||
if (!settings.ttsEnabled) return;
|
||||
if (this.voiceLoop.status.tts) return;
|
||||
if (!this.voiceLoop.tts) this.voiceLoop.tts = new QvacVoiceAdapter({ role: 'tts' });
|
||||
try {
|
||||
await this.voiceLoop.tts.start();
|
||||
this.voiceLoop.status.tts = true;
|
||||
delete this.voiceLoop.status.errors.tts;
|
||||
console.log('jarvisd: voice: TTS ready');
|
||||
} catch (error) {
|
||||
const message = String(error?.message || error);
|
||||
this.voiceLoop.status.errors.tts = message;
|
||||
console.error(`jarvisd: voice: TTS: ${message}`);
|
||||
this.emit('Error', 'TTS', message);
|
||||
}
|
||||
}
|
||||
cancel() { this.voiceLoop?.interrupt?.(); this.harness.cancel(); this.scheduler.cancelQueued((job) => job.lane === 'voice'); this.computer.revoke(); this.voice.cancel(); this.setState('ARMED'); cancelQvac().catch((error) => this.emit('Error', 'QVAC_CANCEL', error.message)); }
|
||||
computerGrant(persist = false) { const result = this.computer.grant({ persist }); this.emit('ComputerStep', JSON.stringify({ action: 'grant', ...result })); this.input.grant({ persist }).then((backend) => { this.computer.setBackend(backend.backend); this.emit('ComputerStep', JSON.stringify({ action: 'backend', ...backend })); }).catch((error) => this.emit('Error', 'CU_GRANT', error.message)); return result; }
|
||||
computerRevoke() { this.input.revoke(); this.computer.revoke(); this.emit('ComputerStep', JSON.stringify({ action: 'revoke' })); }
|
||||
@@ -117,12 +144,15 @@ export class JarvisDaemon extends EventEmitter {
|
||||
const settings = voiceSettings();
|
||||
const asr = new QvacVoiceAdapter({ role: 'asr' });
|
||||
const tts = settings.ttsEnabled ? new QvacVoiceAdapter({ role: 'tts' }) : null;
|
||||
if (!settings.ttsEnabled) console.log('jarvisd: voice: TTS disabled in config.json');
|
||||
const loop = new VoiceLoop({ daemon: this, wake: createWakeEngine(settings), asr, tts });
|
||||
loop.on('error', (error) => { console.error(`jarvisd: voice: ${error.message}`); this.emit('Error', 'VOICE', error.message); });
|
||||
this.voiceLoop = loop;
|
||||
try { await loop.start(); this.emit('StateChanged', this.state); } catch (error) {
|
||||
this.voiceLoop = null; await loop.stop?.().catch(() => {}); this.emit('Error', 'VOICE_UNAVAILABLE', error.message); throw error;
|
||||
}
|
||||
if (loop.status.tts) console.log('jarvisd: voice: TTS ready');
|
||||
else if (loop.status.errors.tts) console.error(`jarvisd: voice: TTS: ${loop.status.errors.tts}`);
|
||||
}
|
||||
setPushToTalk(pressed) { this.voiceLoop?.setPushToTalk(pressed); this.emit('PushToTalk', Boolean(pressed)); }
|
||||
runtimeStatus() { return JSON.stringify({ local: true, qvac: qvacStatus(), scheduler: this.scheduler.status(), scheduler_metrics: this.scheduler.metrics(), telemetry: this.telemetry.snapshot(), computer: this.computer.status(), voice: this.voiceLoop ? { ...this.voiceLoop.metrics.snapshot(), ...this.voiceLoop.status } : null, p2p: { enabled: process.env.JARVIS_P2P_ENABLE === '1', inference: false, memorySync: false } }); }
|
||||
|
||||
Reference in New Issue
Block a user