@@ -24,6 +24,7 @@ export async function serveOnSessionBus(daemon) {
|
||||
PushToTalk(pressed) { daemon.setPushToTalk?.(Boolean(pressed)); }
|
||||
async Say(text) { await daemon.say?.(text); }
|
||||
async Ask(text) { await daemon.ask(text); }
|
||||
async ResetContext() { await daemon.resetContext(); }
|
||||
Cancel() { daemon.cancel(); }
|
||||
SetMode(mode) { daemon.mode = mode; daemon.emit('ModeChanged', mode); }
|
||||
GetState() { return daemon.state; }
|
||||
@@ -66,6 +67,7 @@ export async function serveOnSessionBus(daemon) {
|
||||
PushToTalk: { inSignature: 'b', outSignature: '', method: 'PushToTalk' },
|
||||
Say: { inSignature: 's', outSignature: '', method: 'Say' },
|
||||
Ask: { inSignature: 's', outSignature: '', method: 'Ask' },
|
||||
ResetContext: { inSignature: '', outSignature: '', method: 'ResetContext' },
|
||||
Cancel: { inSignature: '', outSignature: '', method: 'Cancel' },
|
||||
SetMode: { inSignature: 's', outSignature: '', method: 'SetMode' },
|
||||
GetState: { inSignature: '', outSignature: 's', method: 'GetState' },
|
||||
@@ -82,6 +84,7 @@ export async function serveOnSessionBus(daemon) {
|
||||
},
|
||||
signals: {
|
||||
StateChanged: { signature: 's' },
|
||||
ContextReset: { signature: '' },
|
||||
Reply: { signature: 's' },
|
||||
Token: { signature: 's' },
|
||||
Error: { signature: 'ss' },
|
||||
@@ -139,7 +142,7 @@ export async function serveOnSessionBus(daemon) {
|
||||
daemon.on('Token', (token) => iface.Token(token));
|
||||
daemon.on('Error', (code, message) => iface.Error(code, message));
|
||||
daemon.on('ConfirmationRequired', (event) => iface.ConfirmationRequired(event?.tool || 'action', JSON.stringify(event?.args || {}), event?.pattern || 'explicit confirmation required'));
|
||||
for (const signal of ['WakeHeard', 'PartialTranscript', 'FinalTranscript', 'SpeakingLevel', 'ListeningLevel', 'ChipOffered', 'JobProgress', 'ComputerStep', 'ComputerHighlight', 'Thinking', 'ToolCall', 'ToolResult']) {
|
||||
for (const signal of ['ContextReset', 'WakeHeard', 'PartialTranscript', 'FinalTranscript', 'SpeakingLevel', 'ListeningLevel', 'ChipOffered', 'JobProgress', 'ComputerStep', 'ComputerHighlight', 'Thinking', 'ToolCall', 'ToolResult']) {
|
||||
daemon.on(signal, (...args) => iface[signal](...args));
|
||||
}
|
||||
return bus;
|
||||
|
||||
@@ -64,6 +64,12 @@ export class HarnessBridge extends EventEmitter {
|
||||
|
||||
cancel() { this.session?.cancel(); }
|
||||
|
||||
async resetContext() {
|
||||
this.session?.cancel?.();
|
||||
await this.session?.dispose?.();
|
||||
this.session = null;
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this.session?.dispose();
|
||||
releaseQvac();
|
||||
|
||||
+19
-1
@@ -35,6 +35,7 @@ export class JarvisDaemon extends EventEmitter {
|
||||
this.locked = false;
|
||||
this.lastReply = '';
|
||||
this.voiceLoop = null;
|
||||
this._activeAsk = null;
|
||||
this._idleTimer = setInterval(() => this.tickIdle(), 30_000);
|
||||
this._idleTimer.unref?.();
|
||||
this.telemetry = new RuntimeTelemetry();
|
||||
@@ -61,13 +62,30 @@ export class JarvisDaemon extends EventEmitter {
|
||||
this.voiceLoop?.interrupt?.();
|
||||
try {
|
||||
this.voice.typedUtterance(); this.setState('THINKING');
|
||||
const startedAt = Date.now(); const reply = await this.scheduler.run(() => this.harness.ask(text), { lane: 'voice' }); this.telemetry.record('llm', startedAt, { success: true });
|
||||
const startedAt = Date.now();
|
||||
const job = this.scheduler.run(() => this.harness.ask(text), { lane: 'voice' });
|
||||
this._activeAsk = job;
|
||||
const reply = await job;
|
||||
this.telemetry.record('llm', startedAt, { success: true });
|
||||
const spoken = spokenReply(reply);
|
||||
this._beginSpeech(); this.lastReply = spoken; this.emit('Reply', spoken); this._speakReply(spoken); return spoken;
|
||||
} catch (error) {
|
||||
this.telemetry.record('llm', Date.now(), { success: false }); this.emit('Error', 'QVAC', error.message); this.voice.cancel(); this.setState('ARMED'); throw error;
|
||||
} finally {
|
||||
this._activeAsk = null;
|
||||
}
|
||||
}
|
||||
async resetContext() {
|
||||
this.harness.cancel();
|
||||
this.scheduler.cancelQueued((job) => job.lane === 'voice');
|
||||
await this._activeAsk?.catch?.(() => {});
|
||||
await this.harness.resetContext();
|
||||
this.lastReply = '';
|
||||
this.voiceLoop?.interrupt?.();
|
||||
this.voice.cancel();
|
||||
this.setState('ARMED');
|
||||
this.emit('ContextReset');
|
||||
}
|
||||
_beginSpeech() {
|
||||
try {
|
||||
if (this.voice.state === 'ARMED' || this.voice.state === 'SLEEPING') this.voice.wake();
|
||||
|
||||
Reference in New Issue
Block a user