fix(#388): address PR review findings — fix WebSocket/REST bugs, improve error handling, fix types and comments
All checks were successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful

Critical fixes:
- Fix FormData field name mismatch (audio -> file) to match backend FileInterceptor
- Add /speech namespace to WebSocket connection URL
- Pass auth token in WebSocket handshake options
- Wrap audio.play() in try-catch for NotAllowedError and DOMException handling
- Replace bare catch block with named error parameter and descriptive message
- Add connect_error and disconnect event handlers to WebSocket
- Update JSDoc to accurately describe batch transcription (not real-time partial)

Important fixes:
- Emit transcription-error before disconnect in gateway auth failures
- Capture MediaRecorder error details and clean up media tracks on error
- Change TtsDefaultConfig.format type from string to AudioFormat
- Define canonical SPEECH_TIERS and AUDIO_FORMATS arrays as single source of truth
- Fix voice count from 54 to 53 in provider, AGENTS.md, and docs
- Fix inaccurate comments (Piper formats, tier prop, SpeachesProvider, TextValidationPipe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 03:44:33 -06:00
parent dcbc8d1053
commit af9c5799af
14 changed files with 91 additions and 53 deletions

View File

@@ -100,6 +100,9 @@ export class SpeechGateway implements OnGatewayConnection, OnGatewayDisconnect {
const timeoutId = setTimeout(() => {
if (!authenticatedClient.data.userId) {
this.logger.warn(`Client ${authenticatedClient.id} timed out during authentication`);
authenticatedClient.emit("transcription-error", {
message: "Authentication timed out.",
});
authenticatedClient.disconnect();
}
}, this.CONNECTION_TIMEOUT_MS);
@@ -109,6 +112,9 @@ export class SpeechGateway implements OnGatewayConnection, OnGatewayDisconnect {
if (!token) {
this.logger.warn(`Client ${authenticatedClient.id} connected without token`);
authenticatedClient.emit("transcription-error", {
message: "Authentication failed: no token provided.",
});
authenticatedClient.disconnect();
clearTimeout(timeoutId);
return;
@@ -118,6 +124,9 @@ export class SpeechGateway implements OnGatewayConnection, OnGatewayDisconnect {
if (!sessionData) {
this.logger.warn(`Client ${authenticatedClient.id} has invalid token`);
authenticatedClient.emit("transcription-error", {
message: "Authentication failed: invalid or expired token.",
});
authenticatedClient.disconnect();
clearTimeout(timeoutId);
return;
@@ -133,6 +142,9 @@ export class SpeechGateway implements OnGatewayConnection, OnGatewayDisconnect {
if (!workspaceMembership) {
this.logger.warn(`User ${userId} has no workspace access`);
authenticatedClient.emit("transcription-error", {
message: "Authentication failed: no workspace access.",
});
authenticatedClient.disconnect();
clearTimeout(timeoutId);
return;
@@ -151,6 +163,9 @@ export class SpeechGateway implements OnGatewayConnection, OnGatewayDisconnect {
`Authentication failed for speech client ${authenticatedClient.id}:`,
error instanceof Error ? error.message : "Unknown error"
);
authenticatedClient.emit("transcription-error", {
message: "Authentication failed: an unexpected error occurred.",
});
authenticatedClient.disconnect();
}
}