Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/soniox-stt-server-errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@livekit/agents-plugin-soniox': patch
---

Surface Soniox STT server error frames as API status errors.
2 changes: 1 addition & 1 deletion plugins/soniox/src/_internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface SonioxMessage {
tokens?: SonioxToken[];
total_audio_proc_ms?: number;
finished?: boolean;
error_code?: string;
error_code?: string | number;
error_message?: string;
}

Expand Down
21 changes: 18 additions & 3 deletions plugins/soniox/src/stt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import {
type APIConnectOptions,
APIConnectionError,
APIError,
APIStatusError,
APITimeoutError,
type AudioBuffer,
log,
Expand Down Expand Up @@ -143,7 +145,7 @@ export class SpeechStream extends stt.SpeechStream {
ws = await this.#connectWS();
await this.#runWS(ws);
} catch (error) {
if (error instanceof APITimeoutError || error instanceof APIConnectionError) {
if (error instanceof APIError) {
throw error;
}
throw new APIConnectionError({
Expand Down Expand Up @@ -228,9 +230,16 @@ export class SpeechStream extends stt.SpeechStream {
this.#put(event);
}
if (content.error_code || content.error_message) {
this.#logger.error(
`WebSocket error: ${content.error_code ?? ''} - ${content.error_message ?? ''}`,
const statusCode = parseStatusCode(content.error_code);
const errorMessage = content.error_message ?? 'Unknown Soniox STT error';
this.#logger.error(`WebSocket error: ${content.error_code ?? ''} - ${errorMessage}`);
reject(
new APIStatusError({
message: `Soniox STT error: ${content.error_code ?? ''} - ${errorMessage}`,
options: { statusCode, body: content },
}),
);
return;
}
if (content.finished) {
resolve();
Expand Down Expand Up @@ -302,3 +311,9 @@ const serializeTranslation = (translation: TranslationConfig): Record<string, st
language_b: translation.languageB,
};
};

const parseStatusCode = (errorCode: string | number | undefined): number => {
if (typeof errorCode === 'number') return Number.isInteger(errorCode) ? errorCode : -1;
if (typeof errorCode === 'string' && /^\d+$/.test(errorCode)) return Number(errorCode);
return -1;
};