118 lines
3.5 KiB
JavaScript
118 lines
3.5 KiB
JavaScript
import { TranscriptionErrorCode as TranscriptionErrorCode$1 } from "@copilotkitnext/shared";
|
|
|
|
//#region src/lib/transcription-client.ts
|
|
/**
|
|
* Convert a Blob to a base64 string
|
|
*/
|
|
async function blobToBase64(blob) {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onloadend = () => {
|
|
const base64 = reader.result.split(",")[1];
|
|
resolve(base64 ?? "");
|
|
};
|
|
reader.onerror = () => reject(/* @__PURE__ */ new Error("Failed to read audio data"));
|
|
reader.readAsDataURL(blob);
|
|
});
|
|
}
|
|
/**
|
|
* Check if an error response matches our expected format
|
|
*/
|
|
function isTranscriptionErrorResponse(data) {
|
|
return typeof data === "object" && data !== null && "error" in data && "message" in data && typeof data.error === "string" && typeof data.message === "string";
|
|
}
|
|
/**
|
|
* Parse error info from a transcription error response
|
|
*/
|
|
function parseTranscriptionError(response) {
|
|
return {
|
|
code: response.error,
|
|
message: response.message,
|
|
retryable: response.retryable ?? false
|
|
};
|
|
}
|
|
/**
|
|
* Custom error type for transcription failures.
|
|
* Extends Error with transcription-specific info for contextual error handling.
|
|
*/
|
|
var TranscriptionError = class extends Error {
|
|
info;
|
|
constructor(info) {
|
|
super(info.message);
|
|
this.name = "TranscriptionError";
|
|
this.info = info;
|
|
}
|
|
};
|
|
/**
|
|
* Transcribe an audio blob using the CopilotKit runtime
|
|
*
|
|
* Supports both REST mode (multipart/form-data) and single-endpoint mode (base64 JSON)
|
|
*
|
|
* @throws {TranscriptionError} When transcription fails with typed error information
|
|
*/
|
|
async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
|
|
const runtimeUrl = core.runtimeUrl;
|
|
if (!runtimeUrl) throw new TranscriptionError({
|
|
code: TranscriptionErrorCode$1.INVALID_REQUEST,
|
|
message: "Runtime URL is not configured",
|
|
retryable: false
|
|
});
|
|
const headers = { ...core.headers };
|
|
let response;
|
|
try {
|
|
if (core.runtimeTransport === "single") {
|
|
const base64Audio = await blobToBase64(audioBlob);
|
|
headers["Content-Type"] = "application/json";
|
|
response = await fetch(runtimeUrl, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify({
|
|
method: "transcribe",
|
|
body: {
|
|
audio: base64Audio,
|
|
mimeType: audioBlob.type || "audio/webm",
|
|
filename
|
|
}
|
|
})
|
|
});
|
|
} else {
|
|
delete headers["Content-Type"];
|
|
const formData = new FormData();
|
|
formData.append("audio", audioBlob, filename);
|
|
response = await fetch(`${runtimeUrl}/transcribe`, {
|
|
method: "POST",
|
|
headers,
|
|
body: formData
|
|
});
|
|
}
|
|
} catch (error) {
|
|
throw new TranscriptionError({
|
|
code: TranscriptionErrorCode$1.NETWORK_ERROR,
|
|
message: error instanceof Error ? error.message : "Network request failed",
|
|
retryable: true
|
|
});
|
|
}
|
|
if (!response.ok) {
|
|
let errorData;
|
|
try {
|
|
errorData = await response.json();
|
|
} catch {
|
|
throw new TranscriptionError({
|
|
code: TranscriptionErrorCode$1.PROVIDER_ERROR,
|
|
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
retryable: response.status >= 500
|
|
});
|
|
}
|
|
if (isTranscriptionErrorResponse(errorData)) throw new TranscriptionError(parseTranscriptionError(errorData));
|
|
throw new TranscriptionError({
|
|
code: TranscriptionErrorCode$1.PROVIDER_ERROR,
|
|
message: typeof errorData === "object" && errorData !== null && "message" in errorData ? String(errorData.message) : "Transcription failed",
|
|
retryable: response.status >= 500
|
|
});
|
|
}
|
|
return await response.json();
|
|
}
|
|
|
|
//#endregion
|
|
export { TranscriptionError, transcribeAudio };
|
|
//# sourceMappingURL=transcription-client.mjs.map
|