From e25a5cab6bdc43b9a82b4523d80ec74731acbef0 Mon Sep 17 00:00:00 2001 From: Noa Flaherty Date: Tue, 24 Feb 2026 23:31:29 -0500 Subject: [PATCH] fix: address review feedback on voice barge-in and guardian greeting Co-Authored-By: Claude --- assistant/src/calls/call-controller.ts | 3 +-- assistant/src/calls/voice-session-bridge.ts | 1 + assistant/src/runtime/run-orchestrator.ts | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/assistant/src/calls/call-controller.ts b/assistant/src/calls/call-controller.ts index 07db8dbf194..77eac4e6f3a 100644 --- a/assistant/src/calls/call-controller.ts +++ b/assistant/src/calls/call-controller.ts @@ -637,8 +637,7 @@ export class CallController { private isExpectedAbortError(err: unknown): boolean { if (!(err instanceof Error)) return false; return err.name === 'AbortError' - || err.name === 'APIUserAbortError' - || err.message === 'Session is already processing a message'; + || err.name === 'APIUserAbortError'; } private isCurrentRun(runVersion: number): boolean { diff --git a/assistant/src/calls/voice-session-bridge.ts b/assistant/src/calls/voice-session-bridge.ts index ca82352f0b3..6451f91f6b0 100644 --- a/assistant/src/calls/voice-session-bridge.ts +++ b/assistant/src/calls/voice-session-bridge.ts @@ -236,6 +236,7 @@ export async function startVoiceTurn(opts: VoiceTurnOptions): Promise { // Block inbound content that contains secrets — mirrors the IPC check in sessions.ts const ingressCheck = checkIngressForSecrets(content); @@ -200,13 +201,21 @@ export class RunOrchestrator { if (session.isProcessing()) { // Voice barge-in can race with turn teardown. Wait briefly for the // previous run to finish aborting before giving up. + // The caller can pass an AbortSignal so superseded turns bail out + // of this wait early instead of occupying the session. const maxWaitMs = 3000; const pollIntervalMs = 50; let waited = 0; while (session.isProcessing() && waited < maxWaitMs) { + if (signal?.aborted) { + throw new Error('Run aborted while waiting for session'); + } await new Promise(resolve => setTimeout(resolve, pollIntervalMs)); waited += pollIntervalMs; } + if (signal?.aborted) { + throw new Error('Run aborted while waiting for session'); + } if (session.isProcessing()) { throw new Error('Session is already processing a message'); }