@ai-sdk/cartesia 3.0.45 → 3.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1052 +1,903 @@
1
- // src/cartesia-provider.ts
2
- import {
3
- NoSuchModelError
4
- } from "@ai-sdk/provider";
5
- import {
6
- loadApiKey,
7
- withUserAgentSuffix
8
- } from "@ai-sdk/provider-utils";
9
-
10
- // src/cartesia-transcription-model.ts
11
- import {
12
- InvalidArgumentError,
13
- UnsupportedFunctionalityError
14
- } from "@ai-sdk/provider";
15
- import {
16
- combineHeaders,
17
- connectToWebSocket,
18
- convertBase64ToUint8Array,
19
- createJsonResponseHandler,
20
- mediaTypeToExtension,
21
- parseProviderOptions,
22
- postFormDataToApi,
23
- postJsonToApi,
24
- safeParseJSON,
25
- serializeModelOptions,
26
- toWebSocketUrl,
27
- waitForWebSocketBufferDrain,
28
- WORKFLOW_SERIALIZE,
29
- WORKFLOW_DESERIALIZE
30
- } from "@ai-sdk/provider-utils";
31
- import { z as z3 } from "zod/v4";
32
-
33
- // src/cartesia-error.ts
1
+ import { InvalidArgumentError, NoSuchModelError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
2
+ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertBase64ToUint8Array, createBinaryResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, loadApiKey, mediaTypeToExtension, parseProviderOptions, postFormDataToApi, postJsonToApi, safeParseJSON, serializeModelOptions, toWebSocketUrl, waitForWebSocketBufferDrain, withUserAgentSuffix } from "@ai-sdk/provider-utils";
34
3
  import { z } from "zod/v4";
35
- import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
36
- var cartesiaErrorDataSchema = z.object({
37
- error_code: z.string().nullish(),
38
- title: z.string(),
39
- message: z.string(),
40
- request_id: z.string(),
41
- doc_url: z.string().optional()
4
+ //#region src/cartesia-error.ts
5
+ const cartesiaErrorDataSchema = z.object({
6
+ error_code: z.string().nullish(),
7
+ title: z.string(),
8
+ message: z.string(),
9
+ request_id: z.string(),
10
+ doc_url: z.string().optional()
42
11
  });
43
- var cartesiaFailedResponseHandler = createJsonErrorResponseHandler({
44
- errorSchema: cartesiaErrorDataSchema,
45
- errorToMessage: (data) => `${data.title}: ${data.message}`
12
+ const cartesiaFailedResponseHandler = createJsonErrorResponseHandler({
13
+ errorSchema: cartesiaErrorDataSchema,
14
+ errorToMessage: (data) => `${data.title}: ${data.message}`
46
15
  });
47
-
48
- // src/cartesia-transcription-model-options.ts
49
- import { z as z2 } from "zod/v4";
50
- var cartesiaStreamingEncodingSchema = z2.enum([
51
- "pcm_alaw",
52
- "pcm_f16le",
53
- "pcm_f32le",
54
- "pcm_mulaw",
55
- "pcm_s16le",
56
- "pcm_s32le"
16
+ //#endregion
17
+ //#region src/cartesia-transcription-model-options.ts
18
+ /** Raw audio encodings accepted by Ink 2 streaming transcription. */
19
+ const cartesiaStreamingEncodingSchema = z.enum([
20
+ "pcm_alaw",
21
+ "pcm_f16le",
22
+ "pcm_f32le",
23
+ "pcm_mulaw",
24
+ "pcm_s16le",
25
+ "pcm_s32le"
57
26
  ]);
58
- var cartesiaTranscriptionModelOptionsSchema = z2.object({
59
- /** The language of the audio (ISO 639-1 code). Defaults to English. */
60
- language: z2.string().nullish(),
61
- /** The timestamp granularities to populate. Currently only `word` is supported. */
62
- timestampGranularities: z2.array(z2.enum(["word"])).nullish(),
63
- /** Options for realtime Ink 2 transcription over WebSocket. */
64
- streaming: z2.object({
65
- /**
66
- * Raw audio encoding sent to Ink 2. Defaults to the encoding inferred
67
- * from `inputAudioFormat.type`.
68
- */
69
- encoding: cartesiaStreamingEncodingSchema.optional(),
70
- /**
71
- * Use Cartesia's native turn detection endpoint. Defaults to true.
72
- * Disable this to finalize the transcript only when the audio stream ends.
73
- */
74
- turnDetection: z2.boolean().optional()
75
- }).optional()
27
+ const cartesiaTranscriptionModelOptionsSchema = z.object({
28
+ /** The language of the audio (ISO 639-1 code). Defaults to English. */
29
+ language: z.string().nullish(),
30
+ /** The timestamp granularities to populate. Currently only `word` is supported. */
31
+ timestampGranularities: z.array(z.enum(["word"])).nullish(),
32
+ /** Options for realtime Ink 2 transcription over WebSocket. */
33
+ streaming: z.object({
34
+ /**
35
+ * Raw audio encoding sent to Ink 2. Defaults to the encoding inferred
36
+ * from `inputAudioFormat.type`.
37
+ */
38
+ encoding: cartesiaStreamingEncodingSchema.optional(),
39
+ /**
40
+ * Use Cartesia's native turn detection endpoint. Defaults to true.
41
+ * Disable this to finalize the transcript only when the audio stream ends.
42
+ */
43
+ turnDetection: z.boolean().optional()
44
+ }).optional()
76
45
  });
77
-
78
- // src/cartesia-transcription-model.ts
79
- var CartesiaTranscriptionModel = class _CartesiaTranscriptionModel {
80
- constructor(modelId, config) {
81
- this.modelId = modelId;
82
- this.config = config;
83
- this.specificationVersion = "v4";
84
- }
85
- get provider() {
86
- return this.config.provider;
87
- }
88
- static [WORKFLOW_SERIALIZE](model) {
89
- return serializeModelOptions({
90
- modelId: model.modelId,
91
- config: model.config
92
- });
93
- }
94
- static [WORKFLOW_DESERIALIZE](options) {
95
- return new _CartesiaTranscriptionModel(options.modelId, options.config);
96
- }
97
- async getArgs({
98
- audio,
99
- mediaType,
100
- providerOptions
101
- }) {
102
- const warnings = [];
103
- const cartesiaOptions = await parseProviderOptions({
104
- provider: "cartesia",
105
- providerOptions,
106
- schema: cartesiaTranscriptionModelOptionsSchema
107
- });
108
- if (cartesiaOptions?.streaming != null) {
109
- warnings.push({
110
- type: "unsupported",
111
- feature: "providerOptions.cartesia.streaming",
112
- details: "Cartesia batch transcription does not support streaming options."
113
- });
114
- }
115
- const formData = new FormData();
116
- const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
117
- const fileExtension = mediaTypeToExtension(mediaType);
118
- formData.append("model", this.modelId);
119
- formData.append(
120
- "file",
121
- new File([blob], "audio", { type: mediaType }),
122
- `audio.${fileExtension}`
123
- );
124
- if (cartesiaOptions) {
125
- if (cartesiaOptions.language != null) {
126
- formData.set("language", cartesiaOptions.language);
127
- }
128
- if (cartesiaOptions.timestampGranularities != null) {
129
- for (const granularity of cartesiaOptions.timestampGranularities) {
130
- formData.append("timestamp_granularities[]", granularity);
131
- }
132
- }
133
- }
134
- return {
135
- formData,
136
- warnings
137
- };
138
- }
139
- async doGenerate(options) {
140
- if (isStreamingTranscriptionModelId(this.modelId)) {
141
- throw new UnsupportedFunctionalityError({
142
- functionality: `non-streaming transcription with ${this.modelId}`
143
- });
144
- }
145
- const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
146
- const { formData, warnings } = await this.getArgs(options);
147
- const {
148
- value: response,
149
- responseHeaders,
150
- rawValue: rawResponse
151
- } = await postFormDataToApi({
152
- url: this.config.url({
153
- path: "/stt",
154
- modelId: this.modelId
155
- }),
156
- headers: combineHeaders(this.config.headers?.(), options.headers),
157
- formData,
158
- failedResponseHandler: cartesiaFailedResponseHandler,
159
- successfulResponseHandler: createJsonResponseHandler(
160
- cartesiaTranscriptionResponseSchema
161
- ),
162
- abortSignal: options.abortSignal,
163
- fetch: this.config.fetch
164
- });
165
- return {
166
- text: response.text,
167
- segments: response.words?.map((word) => ({
168
- text: word.word,
169
- startSecond: word.start,
170
- endSecond: word.end
171
- })) ?? [],
172
- language: response.language ?? void 0,
173
- durationInSeconds: response.duration ?? void 0,
174
- warnings,
175
- response: {
176
- timestamp: currentDate,
177
- modelId: this.modelId,
178
- headers: responseHeaders,
179
- body: rawResponse
180
- }
181
- };
182
- }
183
- async doStream(options) {
184
- if (!isStreamingTranscriptionModelId(this.modelId)) {
185
- throw new UnsupportedFunctionalityError({
186
- functionality: `streaming transcription with ${this.modelId}`
187
- });
188
- }
189
- const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
190
- const warnings = [];
191
- const cartesiaOptions = await parseProviderOptions({
192
- provider: "cartesia",
193
- providerOptions: options.providerOptions,
194
- schema: cartesiaTranscriptionModelOptionsSchema
195
- });
196
- if (cartesiaOptions?.language != null && cartesiaOptions.language !== "en") {
197
- throw new InvalidArgumentError({
198
- argument: "providerOptions",
199
- message: "Cartesia Ink 2 currently supports English only."
200
- });
201
- }
202
- if (cartesiaOptions?.timestampGranularities != null) {
203
- warnings.push({
204
- type: "unsupported",
205
- feature: "providerOptions.cartesia.timestampGranularities",
206
- details: "Cartesia streaming transcription does not support timestamp granularities."
207
- });
208
- }
209
- const inferredEncoding = cartesiaEncodingFromInputAudioFormat(
210
- options.inputAudioFormat.type
211
- );
212
- const encoding = cartesiaOptions?.streaming?.encoding ?? inferredEncoding;
213
- if (encoding !== inferredEncoding && !(inferredEncoding === "pcm_s16le" && LINEAR_PCM_STREAMING_ENCODINGS.has(encoding))) {
214
- warnings.push({
215
- type: "other",
216
- message: `providerOptions.cartesia.streaming.encoding '${encoding}' contradicts inputAudioFormat.type '${options.inputAudioFormat.type}' (inferred '${inferredEncoding}'); sending '${encoding}'.`
217
- });
218
- }
219
- const token = await this.createStreamingAccessToken(options);
220
- const useTurnDetection = cartesiaOptions?.streaming?.turnDetection !== false;
221
- const url = buildCartesiaStreamingTranscriptionUrl({
222
- baseURL: this.config.url({ path: "/", modelId: this.modelId }),
223
- version: this.config.version ?? "2026-03-01",
224
- modelId: this.modelId,
225
- encoding,
226
- inputAudioFormat: options.inputAudioFormat,
227
- providerOptions: cartesiaOptions,
228
- token,
229
- useTurnDetection
230
- });
231
- const requestUrl = new URL(url);
232
- requestUrl.searchParams.delete("access_token");
233
- return {
234
- request: { body: requestUrl.toString() },
235
- response: {
236
- timestamp: currentDate,
237
- modelId: this.modelId
238
- },
239
- stream: createCartesiaStreamingTranscriptionStream({
240
- webSocket: this.config.webSocket,
241
- url,
242
- warnings,
243
- language: cartesiaOptions?.language ?? "en",
244
- useTurnDetection,
245
- audio: options.audio,
246
- abortSignal: options.abortSignal,
247
- includeRawChunks: options.includeRawChunks
248
- })
249
- };
250
- }
251
- async createStreamingAccessToken(options) {
252
- const { value } = await postJsonToApi({
253
- url: this.config.url({ path: "/access-token", modelId: this.modelId }),
254
- headers: combineHeaders(this.config.headers?.(), options.headers),
255
- body: { grants: { stt: true } },
256
- failedResponseHandler: cartesiaFailedResponseHandler,
257
- successfulResponseHandler: createJsonResponseHandler(
258
- cartesiaAccessTokenResponseSchema
259
- ),
260
- abortSignal: options.abortSignal,
261
- fetch: this.config.fetch
262
- });
263
- return value.token;
264
- }
46
+ //#endregion
47
+ //#region src/cartesia-transcription-model.ts
48
+ var CartesiaTranscriptionModel = class CartesiaTranscriptionModel {
49
+ get provider() {
50
+ return this.config.provider;
51
+ }
52
+ static [WORKFLOW_SERIALIZE](model) {
53
+ return serializeModelOptions({
54
+ modelId: model.modelId,
55
+ config: model.config
56
+ });
57
+ }
58
+ static [WORKFLOW_DESERIALIZE](options) {
59
+ return new CartesiaTranscriptionModel(options.modelId, options.config);
60
+ }
61
+ constructor(modelId, config) {
62
+ this.modelId = modelId;
63
+ this.config = config;
64
+ this.specificationVersion = "v4";
65
+ }
66
+ async getArgs({ audio, mediaType, providerOptions }) {
67
+ const warnings = [];
68
+ const cartesiaOptions = await parseProviderOptions({
69
+ provider: "cartesia",
70
+ providerOptions,
71
+ schema: cartesiaTranscriptionModelOptionsSchema
72
+ });
73
+ if (cartesiaOptions?.streaming != null) warnings.push({
74
+ type: "unsupported",
75
+ feature: "providerOptions.cartesia.streaming",
76
+ details: "Cartesia batch transcription does not support streaming options."
77
+ });
78
+ const formData = new FormData();
79
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
80
+ const fileExtension = mediaTypeToExtension(mediaType);
81
+ formData.append("model", this.modelId);
82
+ formData.append("file", new File([blob], "audio", { type: mediaType }), `audio.${fileExtension}`);
83
+ if (cartesiaOptions) {
84
+ if (cartesiaOptions.language != null) formData.set("language", cartesiaOptions.language);
85
+ if (cartesiaOptions.timestampGranularities != null) for (const granularity of cartesiaOptions.timestampGranularities) formData.append("timestamp_granularities[]", granularity);
86
+ }
87
+ return {
88
+ formData,
89
+ warnings
90
+ };
91
+ }
92
+ async doGenerate(options) {
93
+ if (isStreamingTranscriptionModelId(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `non-streaming transcription with ${this.modelId}` });
94
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
95
+ const { formData, warnings } = await this.getArgs(options);
96
+ const { value: response, responseHeaders, rawValue: rawResponse } = await postFormDataToApi({
97
+ url: this.config.url({
98
+ path: "/stt",
99
+ modelId: this.modelId
100
+ }),
101
+ headers: combineHeaders(this.config.headers?.(), options.headers),
102
+ formData,
103
+ failedResponseHandler: cartesiaFailedResponseHandler,
104
+ successfulResponseHandler: createJsonResponseHandler(cartesiaTranscriptionResponseSchema),
105
+ abortSignal: options.abortSignal,
106
+ fetch: this.config.fetch
107
+ });
108
+ return {
109
+ text: response.text,
110
+ segments: response.words?.map((word) => ({
111
+ text: word.word,
112
+ startSecond: word.start,
113
+ endSecond: word.end
114
+ })) ?? [],
115
+ language: response.language ?? void 0,
116
+ durationInSeconds: response.duration ?? void 0,
117
+ warnings,
118
+ response: {
119
+ timestamp: currentDate,
120
+ modelId: this.modelId,
121
+ headers: responseHeaders,
122
+ body: rawResponse
123
+ }
124
+ };
125
+ }
126
+ async doStream(options) {
127
+ if (!isStreamingTranscriptionModelId(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `streaming transcription with ${this.modelId}` });
128
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
129
+ const warnings = [];
130
+ const cartesiaOptions = await parseProviderOptions({
131
+ provider: "cartesia",
132
+ providerOptions: options.providerOptions,
133
+ schema: cartesiaTranscriptionModelOptionsSchema
134
+ });
135
+ if (cartesiaOptions?.language != null && cartesiaOptions.language !== "en") throw new InvalidArgumentError({
136
+ argument: "providerOptions",
137
+ message: "Cartesia Ink 2 currently supports English only."
138
+ });
139
+ if (cartesiaOptions?.timestampGranularities != null) warnings.push({
140
+ type: "unsupported",
141
+ feature: "providerOptions.cartesia.timestampGranularities",
142
+ details: "Cartesia streaming transcription does not support timestamp granularities."
143
+ });
144
+ const inferredEncoding = cartesiaEncodingFromInputAudioFormat(options.inputAudioFormat.type);
145
+ const encoding = cartesiaOptions?.streaming?.encoding ?? inferredEncoding;
146
+ if (encoding !== inferredEncoding && !(inferredEncoding === "pcm_s16le" && LINEAR_PCM_STREAMING_ENCODINGS.has(encoding))) warnings.push({
147
+ type: "other",
148
+ message: `providerOptions.cartesia.streaming.encoding '${encoding}' contradicts inputAudioFormat.type '${options.inputAudioFormat.type}' (inferred '${inferredEncoding}'); sending '${encoding}'.`
149
+ });
150
+ const token = await this.createStreamingAccessToken(options);
151
+ const useTurnDetection = cartesiaOptions?.streaming?.turnDetection !== false;
152
+ const url = buildCartesiaStreamingTranscriptionUrl({
153
+ baseURL: this.config.url({
154
+ path: "/",
155
+ modelId: this.modelId
156
+ }),
157
+ version: this.config.version ?? "2026-03-01",
158
+ modelId: this.modelId,
159
+ encoding,
160
+ inputAudioFormat: options.inputAudioFormat,
161
+ providerOptions: cartesiaOptions,
162
+ token,
163
+ useTurnDetection
164
+ });
165
+ const requestUrl = new URL(url);
166
+ requestUrl.searchParams.delete("access_token");
167
+ return {
168
+ request: { body: requestUrl.toString() },
169
+ response: {
170
+ timestamp: currentDate,
171
+ modelId: this.modelId
172
+ },
173
+ stream: createCartesiaStreamingTranscriptionStream({
174
+ webSocket: this.config.webSocket,
175
+ url,
176
+ warnings,
177
+ language: cartesiaOptions?.language ?? "en",
178
+ useTurnDetection,
179
+ audio: options.audio,
180
+ abortSignal: options.abortSignal,
181
+ includeRawChunks: options.includeRawChunks
182
+ })
183
+ };
184
+ }
185
+ async createStreamingAccessToken(options) {
186
+ const { value } = await postJsonToApi({
187
+ url: this.config.url({
188
+ path: "/access-token",
189
+ modelId: this.modelId
190
+ }),
191
+ headers: combineHeaders(this.config.headers?.(), options.headers),
192
+ body: { grants: { stt: true } },
193
+ failedResponseHandler: cartesiaFailedResponseHandler,
194
+ successfulResponseHandler: createJsonResponseHandler(cartesiaAccessTokenResponseSchema),
195
+ abortSignal: options.abortSignal,
196
+ fetch: this.config.fetch
197
+ });
198
+ return value.token;
199
+ }
265
200
  };
266
- function createCartesiaStreamingTranscriptionStream({
267
- webSocket,
268
- url,
269
- warnings,
270
- language,
271
- useTurnDetection,
272
- audio,
273
- abortSignal,
274
- includeRawChunks
275
- }) {
276
- let finished = false;
277
- let cleanup = () => {
278
- };
279
- return new ReadableStream({
280
- start: (controller) => {
281
- const finalTexts = [];
282
- let durationInSeconds = 0;
283
- let audioReader;
284
- let connection;
285
- cleanup = (closeCode) => {
286
- if (audioReader != null) {
287
- void audioReader.cancel().catch(() => {
288
- });
289
- } else {
290
- void audio.cancel().catch(() => {
291
- });
292
- }
293
- connection?.close(closeCode);
294
- };
295
- const finishWithError = (error) => {
296
- if (finished) return;
297
- finished = true;
298
- cleanup();
299
- controller.error(error);
300
- };
301
- const finish = () => {
302
- if (finished) return;
303
- finished = true;
304
- controller.enqueue({
305
- type: "finish",
306
- text: finalTexts.join(useTurnDetection ? " " : ""),
307
- segments: [],
308
- language,
309
- ...durationInSeconds > 0 ? { durationInSeconds } : {}
310
- });
311
- controller.close();
312
- cleanup(1e3);
313
- };
314
- const sendAudio = async (socket) => {
315
- audioReader = audio.getReader();
316
- try {
317
- while (true) {
318
- const { done, value } = await audioReader.read();
319
- if (done || finished) break;
320
- socket.send(
321
- value instanceof Uint8Array ? value : convertBase64ToUint8Array(value)
322
- );
323
- await waitForWebSocketBufferDrain(socket);
324
- }
325
- } finally {
326
- audioReader.releaseLock();
327
- audioReader = void 0;
328
- }
329
- if (!finished) {
330
- socket.send(
331
- useTurnDetection ? JSON.stringify({ type: "close" }) : "finalize"
332
- );
333
- }
334
- };
335
- connection = connectToWebSocket({
336
- url,
337
- webSocket,
338
- abortSignal,
339
- onAbort: finishWithError,
340
- onProcessingError: finishWithError,
341
- onOpen: (socket) => {
342
- controller.enqueue({ type: "stream-start", warnings });
343
- void sendAudio(socket).catch(finishWithError);
344
- },
345
- onMessageText: async (text) => {
346
- const parsed = await safeParseJSON({ text });
347
- if (!parsed.success) return;
348
- const raw = parsed.value;
349
- if (includeRawChunks) {
350
- controller.enqueue({ type: "raw", rawValue: raw });
351
- }
352
- switch (raw.type) {
353
- case "turn.update":
354
- case "turn.eager_end": {
355
- controller.enqueue({
356
- type: "transcript-partial",
357
- id: raw.request_id,
358
- text: raw.transcript ?? ""
359
- });
360
- break;
361
- }
362
- case "turn.end": {
363
- const text2 = raw.transcript ?? "";
364
- finalTexts.push(text2);
365
- controller.enqueue({
366
- type: "transcript-final",
367
- id: raw.request_id,
368
- text: text2
369
- });
370
- break;
371
- }
372
- case "transcript": {
373
- const transcript = raw.text ?? "";
374
- if (raw.is_final === true) {
375
- finalTexts.push(transcript);
376
- durationInSeconds += raw.duration ?? 0;
377
- controller.enqueue({
378
- type: "transcript-final",
379
- id: raw.request_id,
380
- text: transcript
381
- });
382
- } else {
383
- controller.enqueue({
384
- type: "transcript-partial",
385
- id: raw.request_id,
386
- text: transcript,
387
- ...raw.duration != null ? { durationInSeconds: raw.duration } : {}
388
- });
389
- }
390
- break;
391
- }
392
- case "flush_done": {
393
- connection?.socket?.send("close");
394
- break;
395
- }
396
- case "done": {
397
- finish();
398
- break;
399
- }
400
- case "error": {
401
- finishWithError(
402
- new Error(
403
- raw.message ?? raw.error_code ?? "Cartesia streaming transcription error"
404
- )
405
- );
406
- break;
407
- }
408
- }
409
- },
410
- onSocketError: () => {
411
- finishWithError(new Error("Cartesia streaming transcription error"));
412
- },
413
- onClose: () => {
414
- if (!finished) finish();
415
- }
416
- });
417
- },
418
- cancel: () => {
419
- if (finished) return;
420
- finished = true;
421
- cleanup();
422
- }
423
- });
201
+ function createCartesiaStreamingTranscriptionStream({ webSocket, url, warnings, language, useTurnDetection, audio, abortSignal, includeRawChunks }) {
202
+ let finished = false;
203
+ let cleanup = () => {};
204
+ return new ReadableStream({
205
+ start: (controller) => {
206
+ const finalTexts = [];
207
+ let durationInSeconds = 0;
208
+ let audioReader;
209
+ let connection;
210
+ cleanup = (closeCode) => {
211
+ if (audioReader != null) audioReader.cancel().catch(() => {});
212
+ else audio.cancel().catch(() => {});
213
+ connection?.close(closeCode);
214
+ };
215
+ const finishWithError = (error) => {
216
+ if (finished) return;
217
+ finished = true;
218
+ cleanup();
219
+ controller.error(error);
220
+ };
221
+ const finish = () => {
222
+ if (finished) return;
223
+ finished = true;
224
+ controller.enqueue({
225
+ type: "finish",
226
+ text: finalTexts.join(useTurnDetection ? " " : ""),
227
+ segments: [],
228
+ language,
229
+ ...durationInSeconds > 0 ? { durationInSeconds } : {}
230
+ });
231
+ controller.close();
232
+ cleanup(1e3);
233
+ };
234
+ const sendAudio = async (socket) => {
235
+ audioReader = audio.getReader();
236
+ try {
237
+ while (true) {
238
+ const { done, value } = await audioReader.read();
239
+ if (done || finished) break;
240
+ socket.send(value instanceof Uint8Array ? value : convertBase64ToUint8Array(value));
241
+ await waitForWebSocketBufferDrain(socket);
242
+ }
243
+ } finally {
244
+ audioReader.releaseLock();
245
+ audioReader = void 0;
246
+ }
247
+ if (!finished) socket.send(useTurnDetection ? JSON.stringify({ type: "close" }) : "finalize");
248
+ };
249
+ connection = connectToWebSocket({
250
+ url,
251
+ webSocket,
252
+ abortSignal,
253
+ onAbort: finishWithError,
254
+ onProcessingError: finishWithError,
255
+ onOpen: (socket) => {
256
+ controller.enqueue({
257
+ type: "stream-start",
258
+ warnings
259
+ });
260
+ sendAudio(socket).catch(finishWithError);
261
+ },
262
+ onMessageText: async (text) => {
263
+ const parsed = await safeParseJSON({ text });
264
+ if (!parsed.success) return;
265
+ const raw = parsed.value;
266
+ if (includeRawChunks) controller.enqueue({
267
+ type: "raw",
268
+ rawValue: raw
269
+ });
270
+ switch (raw.type) {
271
+ case "turn.update":
272
+ case "turn.eager_end":
273
+ controller.enqueue({
274
+ type: "transcript-partial",
275
+ id: raw.request_id,
276
+ text: raw.transcript ?? ""
277
+ });
278
+ break;
279
+ case "turn.end": {
280
+ const text = raw.transcript ?? "";
281
+ finalTexts.push(text);
282
+ controller.enqueue({
283
+ type: "transcript-final",
284
+ id: raw.request_id,
285
+ text
286
+ });
287
+ break;
288
+ }
289
+ case "transcript": {
290
+ const transcript = raw.text ?? "";
291
+ if (raw.is_final === true) {
292
+ finalTexts.push(transcript);
293
+ durationInSeconds += raw.duration ?? 0;
294
+ controller.enqueue({
295
+ type: "transcript-final",
296
+ id: raw.request_id,
297
+ text: transcript
298
+ });
299
+ } else controller.enqueue({
300
+ type: "transcript-partial",
301
+ id: raw.request_id,
302
+ text: transcript,
303
+ ...raw.duration != null ? { durationInSeconds: raw.duration } : {}
304
+ });
305
+ break;
306
+ }
307
+ case "flush_done":
308
+ connection?.socket?.send("close");
309
+ break;
310
+ case "done":
311
+ finish();
312
+ break;
313
+ case "error": finishWithError(new Error(raw.message ?? raw.error_code ?? "Cartesia streaming transcription error"));
314
+ }
315
+ },
316
+ onSocketError: () => {
317
+ finishWithError(/* @__PURE__ */ new Error("Cartesia streaming transcription error"));
318
+ },
319
+ onClose: () => {
320
+ if (!finished) finish();
321
+ }
322
+ });
323
+ },
324
+ cancel: () => {
325
+ if (finished) return;
326
+ finished = true;
327
+ cleanup();
328
+ }
329
+ });
424
330
  }
425
- var G711_STREAMING_ENCODINGS = /* @__PURE__ */ new Set([
426
- "pcm_mulaw",
427
- "pcm_alaw"
428
- ]);
429
- var LINEAR_PCM_STREAMING_ENCODINGS = new Set(
430
- cartesiaStreamingEncodingSchema.options.filter(
431
- (encoding) => !G711_STREAMING_ENCODINGS.has(encoding)
432
- )
433
- );
434
- function buildCartesiaStreamingTranscriptionUrl({
435
- baseURL,
436
- version,
437
- modelId,
438
- encoding,
439
- inputAudioFormat,
440
- providerOptions,
441
- token,
442
- useTurnDetection
443
- }) {
444
- const url = toWebSocketUrl(
445
- new URL(
446
- useTurnDetection ? "/stt/turns/websocket" : "/stt/websocket",
447
- baseURL
448
- )
449
- );
450
- url.searchParams.set("model", modelId);
451
- url.searchParams.set("encoding", encoding);
452
- url.searchParams.set("sample_rate", String(inputAudioFormat.rate ?? 24e3));
453
- url.searchParams.set("cartesia_version", version);
454
- url.searchParams.set("access_token", token);
455
- if (!useTurnDetection && providerOptions?.language != null) {
456
- url.searchParams.set("language", providerOptions.language);
457
- }
458
- return url;
331
+ /** G.711 companding laws — the only non-linear members of the encoding enum. */
332
+ const G711_STREAMING_ENCODINGS = /* @__PURE__ */ new Set(["pcm_mulaw", "pcm_alaw"]);
333
+ /**
334
+ * Linear PCM encodings that legitimately widen generic `audio/pcm` input.
335
+ * Derived from the option enum so a future linear encoding added there is
336
+ * treated as widening-compatible by default; G.711 is a closed set (the
337
+ * standard defines exactly two companding laws), so it is the hardcoded half.
338
+ */
339
+ const LINEAR_PCM_STREAMING_ENCODINGS = new Set(cartesiaStreamingEncodingSchema.options.filter((encoding) => !G711_STREAMING_ENCODINGS.has(encoding)));
340
+ function buildCartesiaStreamingTranscriptionUrl({ baseURL, version, modelId, encoding, inputAudioFormat, providerOptions, token, useTurnDetection }) {
341
+ const url = toWebSocketUrl(new URL(useTurnDetection ? "/stt/turns/websocket" : "/stt/websocket", baseURL));
342
+ url.searchParams.set("model", modelId);
343
+ url.searchParams.set("encoding", encoding);
344
+ url.searchParams.set("sample_rate", String(inputAudioFormat.rate ?? 24e3));
345
+ url.searchParams.set("cartesia_version", version);
346
+ url.searchParams.set("access_token", token);
347
+ if (!useTurnDetection && providerOptions?.language != null) url.searchParams.set("language", providerOptions.language);
348
+ return url;
459
349
  }
460
350
  function cartesiaEncodingFromInputAudioFormat(type) {
461
- switch (type) {
462
- case "audio/pcm":
463
- return "pcm_s16le";
464
- case "audio/pcmu":
465
- return "pcm_mulaw";
466
- case "audio/pcma":
467
- return "pcm_alaw";
468
- default:
469
- throw new InvalidArgumentError({
470
- argument: "inputAudioFormat",
471
- message: `Unsupported Cartesia streaming audio format: ${type}`
472
- });
473
- }
351
+ switch (type) {
352
+ case "audio/pcm": return "pcm_s16le";
353
+ case "audio/pcmu": return "pcm_mulaw";
354
+ case "audio/pcma": return "pcm_alaw";
355
+ default: throw new InvalidArgumentError({
356
+ argument: "inputAudioFormat",
357
+ message: `Unsupported Cartesia streaming audio format: ${type}`
358
+ });
359
+ }
474
360
  }
475
361
  function isStreamingTranscriptionModelId(modelId) {
476
- return modelId === "ink-2" || modelId.startsWith("ink-2-");
362
+ return modelId === "ink-2" || modelId.startsWith("ink-2-");
477
363
  }
478
- var cartesiaTranscriptionResponseSchema = z3.object({
479
- text: z3.string(),
480
- language: z3.string().nullish(),
481
- duration: z3.number().nullish(),
482
- words: z3.array(
483
- z3.object({
484
- word: z3.string(),
485
- start: z3.number(),
486
- end: z3.number()
487
- })
488
- ).nullish()
489
- });
490
- var cartesiaAccessTokenResponseSchema = z3.object({
491
- token: z3.string().min(1)
364
+ const cartesiaTranscriptionResponseSchema = z.object({
365
+ text: z.string(),
366
+ language: z.string().nullish(),
367
+ duration: z.number().nullish(),
368
+ words: z.array(z.object({
369
+ word: z.string(),
370
+ start: z.number(),
371
+ end: z.number()
372
+ })).nullish()
492
373
  });
493
-
494
- // src/cartesia-speech-model.ts
495
- import {
496
- combineHeaders as combineHeaders2,
497
- createBinaryResponseHandler,
498
- parseProviderOptions as parseProviderOptions2,
499
- postJsonToApi as postJsonToApi2,
500
- serializeModelOptions as serializeModelOptions2,
501
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2,
502
- WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2
503
- } from "@ai-sdk/provider-utils";
504
-
505
- // src/cartesia-speech-model-options.ts
506
- import { z as z4 } from "zod/v4";
507
- var cartesiaSpeechModelOptionsSchema = z4.object({
508
- /** Container format for the output audio (raw, wav, mp3). */
509
- container: z4.enum(["raw", "wav", "mp3"]).nullish(),
510
- /** Encoding type for the audio output (pcm_f32le, pcm_s16le, pcm_mulaw, pcm_alaw). */
511
- encoding: z4.enum(["pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw"]).nullish(),
512
- /** Sample rate for the output audio in Hz (e.g. 8000, 16000, 22050, 24000, 44100, 48000). */
513
- sampleRate: z4.union([
514
- z4.literal(8e3),
515
- z4.literal(16e3),
516
- z4.literal(22050),
517
- z4.literal(24e3),
518
- z4.literal(44100),
519
- z4.literal(48e3)
520
- ]).nullish(),
521
- /** Bitrate for mp3 output in bits per second (e.g. 32000, 64000, 128000, 192000). */
522
- bitRate: z4.union([
523
- z4.literal(32e3),
524
- z4.literal(64e3),
525
- z4.literal(96e3),
526
- z4.literal(128e3),
527
- z4.literal(192e3)
528
- ]).nullish(),
529
- /** Controls the speed of the generated speech. */
530
- speed: z4.number().min(0.6).max(1.5).nullish(),
531
- /** The language to generate speech in (ISO 639-1 code). */
532
- language: z4.string().nullish()
374
+ const cartesiaAccessTokenResponseSchema = z.object({ token: z.string().min(1) });
375
+ //#endregion
376
+ //#region src/cartesia-speech-model-options.ts
377
+ const cartesiaSpeechModelOptionsSchema = z.object({
378
+ /** Container format for the output audio (raw, wav, mp3). */
379
+ container: z.enum([
380
+ "raw",
381
+ "wav",
382
+ "mp3"
383
+ ]).nullish(),
384
+ /** Encoding type for the audio output (pcm_f32le, pcm_s16le, pcm_mulaw, pcm_alaw). */
385
+ encoding: z.enum([
386
+ "pcm_f32le",
387
+ "pcm_s16le",
388
+ "pcm_mulaw",
389
+ "pcm_alaw"
390
+ ]).nullish(),
391
+ /** Sample rate for the output audio in Hz (e.g. 8000, 16000, 22050, 24000, 44100, 48000). */
392
+ sampleRate: z.union([
393
+ z.literal(8e3),
394
+ z.literal(16e3),
395
+ z.literal(22050),
396
+ z.literal(24e3),
397
+ z.literal(44100),
398
+ z.literal(48e3)
399
+ ]).nullish(),
400
+ /** Bitrate for mp3 output in bits per second (e.g. 32000, 64000, 128000, 192000). */
401
+ bitRate: z.union([
402
+ z.literal(32e3),
403
+ z.literal(64e3),
404
+ z.literal(96e3),
405
+ z.literal(128e3),
406
+ z.literal(192e3)
407
+ ]).nullish(),
408
+ /** Controls the speed of the generated speech. */
409
+ speed: z.number().min(.6).max(1.5).nullish(),
410
+ /** The language to generate speech in (ISO 639-1 code). */
411
+ language: z.string().nullish()
533
412
  });
534
-
535
- // src/cartesia-speech-model.ts
536
- var DEFAULT_OUTPUT_FORMAT = {
537
- container: "mp3",
538
- sample_rate: 44100,
539
- bit_rate: 128e3
413
+ //#endregion
414
+ //#region src/cartesia-speech-model.ts
415
+ const DEFAULT_OUTPUT_FORMAT = {
416
+ container: "mp3",
417
+ sample_rate: 44100,
418
+ bit_rate: 128e3
540
419
  };
541
- var OUTPUT_FORMATS = {
542
- alaw: { container: "raw", encoding: "pcm_alaw", sample_rate: 8e3 },
543
- mp3: DEFAULT_OUTPUT_FORMAT,
544
- mulaw: { container: "raw", encoding: "pcm_mulaw", sample_rate: 8e3 },
545
- pcm: { container: "raw", encoding: "pcm_f32le", sample_rate: 44100 },
546
- raw: { container: "raw", encoding: "pcm_f32le", sample_rate: 44100 },
547
- wav: { container: "wav", encoding: "pcm_s16le", sample_rate: 44100 }
420
+ const OUTPUT_FORMATS = {
421
+ alaw: {
422
+ container: "raw",
423
+ encoding: "pcm_alaw",
424
+ sample_rate: 8e3
425
+ },
426
+ mp3: DEFAULT_OUTPUT_FORMAT,
427
+ mulaw: {
428
+ container: "raw",
429
+ encoding: "pcm_mulaw",
430
+ sample_rate: 8e3
431
+ },
432
+ pcm: {
433
+ container: "raw",
434
+ encoding: "pcm_f32le",
435
+ sample_rate: 44100
436
+ },
437
+ raw: {
438
+ container: "raw",
439
+ encoding: "pcm_f32le",
440
+ sample_rate: 44100
441
+ },
442
+ wav: {
443
+ container: "wav",
444
+ encoding: "pcm_s16le",
445
+ sample_rate: 44100
446
+ }
548
447
  };
549
- var SAMPLE_RATES = [8e3, 16e3, 22050, 24e3, 44100, 48e3];
448
+ const SAMPLE_RATES = [
449
+ 8e3,
450
+ 16e3,
451
+ 22050,
452
+ 24e3,
453
+ 44100,
454
+ 48e3
455
+ ];
550
456
  function isSampleRate(value) {
551
- return SAMPLE_RATES.includes(value);
457
+ return SAMPLE_RATES.includes(value);
552
458
  }
553
- function resolveOutputFormat({
554
- outputFormat,
555
- providerOptions,
556
- warnings
557
- }) {
558
- const [formatName, sampleRateText, ...extraParts] = outputFormat.toLowerCase().split("_");
559
- const mapped = OUTPUT_FORMATS[formatName];
560
- let resolved = mapped ? { ...mapped } : { ...DEFAULT_OUTPUT_FORMAT };
561
- if (!mapped) {
562
- warnings.push({
563
- type: "unsupported",
564
- feature: "outputFormat",
565
- details: `Unknown output format "${outputFormat}". Falling back to mp3. Use providerOptions.cartesia to configure container, encoding, and sampleRate directly.`
566
- });
567
- } else if (sampleRateText != null) {
568
- const parsedRate = Number(sampleRateText);
569
- if (extraParts.length === 0 && Number.isInteger(parsedRate) && isSampleRate(parsedRate)) {
570
- resolved.sample_rate = parsedRate;
571
- } else {
572
- warnings.push({
573
- type: "unsupported",
574
- feature: "outputFormat",
575
- details: `Unsupported Cartesia sample rate in output format "${outputFormat}". Using ${resolved.sample_rate} Hz instead.`
576
- });
577
- }
578
- }
579
- const container = providerOptions?.container ?? resolved.container;
580
- const sampleRate = providerOptions?.sampleRate ?? resolved.sample_rate;
581
- if (container === "mp3") {
582
- if (providerOptions?.encoding != null) {
583
- warnings.push({
584
- type: "unsupported",
585
- feature: "providerOptions.cartesia.encoding",
586
- details: "Cartesia MP3 output does not accept an encoding. The encoding option was ignored."
587
- });
588
- }
589
- return {
590
- container,
591
- sample_rate: sampleRate,
592
- bit_rate: providerOptions?.bitRate ?? (resolved.container === "mp3" ? resolved.bit_rate : 128e3)
593
- };
594
- }
595
- if (providerOptions?.bitRate != null) {
596
- warnings.push({
597
- type: "unsupported",
598
- feature: "providerOptions.cartesia.bitRate",
599
- details: "Cartesia raw and WAV output do not accept a bit rate. The bitRate option was ignored."
600
- });
601
- }
602
- return {
603
- container,
604
- encoding: providerOptions?.encoding ?? (resolved.container === "mp3" ? container === "wav" ? "pcm_s16le" : "pcm_f32le" : resolved.encoding),
605
- sample_rate: sampleRate
606
- };
459
+ function resolveOutputFormat({ outputFormat, providerOptions, warnings }) {
460
+ const [formatName, sampleRateText, ...extraParts] = outputFormat.toLowerCase().split("_");
461
+ const mapped = OUTPUT_FORMATS[formatName];
462
+ let resolved = mapped ? { ...mapped } : { ...DEFAULT_OUTPUT_FORMAT };
463
+ if (!mapped) warnings.push({
464
+ type: "unsupported",
465
+ feature: "outputFormat",
466
+ details: `Unknown output format "${outputFormat}". Falling back to mp3. Use providerOptions.cartesia to configure container, encoding, and sampleRate directly.`
467
+ });
468
+ else if (sampleRateText != null) {
469
+ const parsedRate = Number(sampleRateText);
470
+ if (extraParts.length === 0 && Number.isInteger(parsedRate) && isSampleRate(parsedRate)) resolved.sample_rate = parsedRate;
471
+ else warnings.push({
472
+ type: "unsupported",
473
+ feature: "outputFormat",
474
+ details: `Unsupported Cartesia sample rate in output format "${outputFormat}". Using ${resolved.sample_rate} Hz instead.`
475
+ });
476
+ }
477
+ const container = providerOptions?.container ?? resolved.container;
478
+ const sampleRate = providerOptions?.sampleRate ?? resolved.sample_rate;
479
+ if (container === "mp3") {
480
+ if (providerOptions?.encoding != null) warnings.push({
481
+ type: "unsupported",
482
+ feature: "providerOptions.cartesia.encoding",
483
+ details: "Cartesia MP3 output does not accept an encoding. The encoding option was ignored."
484
+ });
485
+ return {
486
+ container,
487
+ sample_rate: sampleRate,
488
+ bit_rate: providerOptions?.bitRate ?? (resolved.container === "mp3" ? resolved.bit_rate : 128e3)
489
+ };
490
+ }
491
+ if (providerOptions?.bitRate != null) warnings.push({
492
+ type: "unsupported",
493
+ feature: "providerOptions.cartesia.bitRate",
494
+ details: "Cartesia raw and WAV output do not accept a bit rate. The bitRate option was ignored."
495
+ });
496
+ return {
497
+ container,
498
+ encoding: providerOptions?.encoding ?? (resolved.container === "mp3" ? container === "wav" ? "pcm_s16le" : "pcm_f32le" : resolved.encoding),
499
+ sample_rate: sampleRate
500
+ };
607
501
  }
608
- var CartesiaSpeechModel = class _CartesiaSpeechModel {
609
- constructor(modelId, config) {
610
- this.modelId = modelId;
611
- this.config = config;
612
- this.specificationVersion = "v4";
613
- }
614
- get provider() {
615
- return this.config.provider;
616
- }
617
- static [WORKFLOW_SERIALIZE2](model) {
618
- return serializeModelOptions2({
619
- modelId: model.modelId,
620
- config: model.config
621
- });
622
- }
623
- static [WORKFLOW_DESERIALIZE2](options) {
624
- return new _CartesiaSpeechModel(options.modelId, options.config);
625
- }
626
- async getArgs({
627
- text,
628
- voice,
629
- outputFormat = "mp3",
630
- instructions,
631
- language,
632
- speed,
633
- providerOptions
634
- }) {
635
- const warnings = [];
636
- const cartesiaOptions = await parseProviderOptions2({
637
- provider: "cartesia",
638
- providerOptions,
639
- schema: cartesiaSpeechModelOptionsSchema
640
- });
641
- if (!voice) {
642
- throw new Error("Cartesia speech models require a `voice` to be set.");
643
- }
644
- const outputFormatObject = resolveOutputFormat({
645
- outputFormat,
646
- providerOptions: cartesiaOptions,
647
- warnings
648
- });
649
- const requestBody = {
650
- model_id: this.modelId,
651
- transcript: text,
652
- voice: {
653
- mode: "id",
654
- id: voice
655
- },
656
- output_format: outputFormatObject
657
- };
658
- if (language) {
659
- requestBody.language = language;
660
- }
661
- if (cartesiaOptions) {
662
- if (cartesiaOptions.language != null) {
663
- requestBody.language = cartesiaOptions.language;
664
- }
665
- }
666
- const resolvedSpeed = cartesiaOptions?.speed ?? speed;
667
- if (resolvedSpeed != null) {
668
- if (resolvedSpeed >= 0.6 && resolvedSpeed <= 1.5) {
669
- requestBody.generation_config = { speed: resolvedSpeed };
670
- } else {
671
- warnings.push({
672
- type: "unsupported",
673
- feature: "speed",
674
- details: "Cartesia speed must be between 0.6 and 1.5. The speed option was ignored."
675
- });
676
- }
677
- }
678
- if (instructions) {
679
- warnings.push({
680
- type: "unsupported",
681
- feature: "instructions",
682
- details: `Cartesia speech models do not support instructions. Instructions parameter was ignored.`
683
- });
684
- }
685
- return {
686
- requestBody,
687
- warnings
688
- };
689
- }
690
- async doGenerate(options) {
691
- const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
692
- const { requestBody, warnings } = await this.getArgs(options);
693
- const {
694
- value: audio,
695
- responseHeaders,
696
- rawValue: rawResponse
697
- } = await postJsonToApi2({
698
- url: this.config.url({
699
- path: "/tts/bytes",
700
- modelId: this.modelId
701
- }),
702
- headers: combineHeaders2(this.config.headers?.(), options.headers),
703
- body: requestBody,
704
- failedResponseHandler: cartesiaFailedResponseHandler,
705
- successfulResponseHandler: createBinaryResponseHandler(),
706
- abortSignal: options.abortSignal,
707
- fetch: this.config.fetch
708
- });
709
- return {
710
- audio,
711
- warnings,
712
- request: {
713
- body: JSON.stringify(requestBody)
714
- },
715
- response: {
716
- timestamp: currentDate,
717
- modelId: this.modelId,
718
- headers: responseHeaders,
719
- body: rawResponse
720
- }
721
- };
722
- }
502
+ var CartesiaSpeechModel = class CartesiaSpeechModel {
503
+ get provider() {
504
+ return this.config.provider;
505
+ }
506
+ static [WORKFLOW_SERIALIZE](model) {
507
+ return serializeModelOptions({
508
+ modelId: model.modelId,
509
+ config: model.config
510
+ });
511
+ }
512
+ static [WORKFLOW_DESERIALIZE](options) {
513
+ return new CartesiaSpeechModel(options.modelId, options.config);
514
+ }
515
+ constructor(modelId, config) {
516
+ this.modelId = modelId;
517
+ this.config = config;
518
+ this.specificationVersion = "v4";
519
+ }
520
+ async getArgs({ text, voice, outputFormat = "mp3", instructions, language, speed, providerOptions }) {
521
+ const warnings = [];
522
+ const cartesiaOptions = await parseProviderOptions({
523
+ provider: "cartesia",
524
+ providerOptions,
525
+ schema: cartesiaSpeechModelOptionsSchema
526
+ });
527
+ if (!voice) throw new Error("Cartesia speech models require a `voice` to be set.");
528
+ const outputFormatObject = resolveOutputFormat({
529
+ outputFormat,
530
+ providerOptions: cartesiaOptions,
531
+ warnings
532
+ });
533
+ const requestBody = {
534
+ model_id: this.modelId,
535
+ transcript: text,
536
+ voice: {
537
+ mode: "id",
538
+ id: voice
539
+ },
540
+ output_format: outputFormatObject
541
+ };
542
+ if (language) requestBody.language = language;
543
+ if (cartesiaOptions) {
544
+ if (cartesiaOptions.language != null) requestBody.language = cartesiaOptions.language;
545
+ }
546
+ const resolvedSpeed = cartesiaOptions?.speed ?? speed;
547
+ if (resolvedSpeed != null) {
548
+ if (resolvedSpeed >= .6 && resolvedSpeed <= 1.5) requestBody.generation_config = { speed: resolvedSpeed };
549
+ else warnings.push({
550
+ type: "unsupported",
551
+ feature: "speed",
552
+ details: "Cartesia speed must be between 0.6 and 1.5. The speed option was ignored."
553
+ });
554
+ }
555
+ if (instructions) warnings.push({
556
+ type: "unsupported",
557
+ feature: "instructions",
558
+ details: `Cartesia speech models do not support instructions. Instructions parameter was ignored.`
559
+ });
560
+ return {
561
+ requestBody,
562
+ warnings
563
+ };
564
+ }
565
+ async doGenerate(options) {
566
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
567
+ const { requestBody, warnings } = await this.getArgs(options);
568
+ const { value: audio, responseHeaders, rawValue: rawResponse } = await postJsonToApi({
569
+ url: this.config.url({
570
+ path: "/tts/bytes",
571
+ modelId: this.modelId
572
+ }),
573
+ headers: combineHeaders(this.config.headers?.(), options.headers),
574
+ body: requestBody,
575
+ failedResponseHandler: cartesiaFailedResponseHandler,
576
+ successfulResponseHandler: createBinaryResponseHandler(),
577
+ abortSignal: options.abortSignal,
578
+ fetch: this.config.fetch
579
+ });
580
+ return {
581
+ audio,
582
+ warnings,
583
+ request: { body: JSON.stringify(requestBody) },
584
+ response: {
585
+ timestamp: currentDate,
586
+ modelId: this.modelId,
587
+ headers: responseHeaders,
588
+ body: rawResponse
589
+ }
590
+ };
591
+ }
723
592
  };
724
-
725
- // src/cartesia-realtime-model.ts
726
- import {
727
- convertBase64ToUint8Array as convertBase64ToUint8Array2
728
- } from "@ai-sdk/provider-utils";
593
+ //#endregion
594
+ //#region src/cartesia-realtime-model.ts
595
+ /**
596
+ * Realtime Ink model using Cartesia's STT WebSocket APIs.
597
+ */
729
598
  var CartesiaRealtimeModel = class {
730
- constructor(modelId, config) {
731
- this.specificationVersion = "v4";
732
- this.manualTranscript = {
733
- duration: 0,
734
- events: [],
735
- text: ""
736
- };
737
- this.sessionCreated = false;
738
- this.useTurnDetection = true;
739
- this.modelId = modelId;
740
- this.provider = config.provider;
741
- this.config = config;
742
- }
743
- async doCreateClientSecret(options) {
744
- const expiresIn = options.expiresAfterSeconds;
745
- if (expiresIn != null && (!Number.isInteger(expiresIn) || expiresIn <= 0 || expiresIn > 3600)) {
746
- throw new Error(
747
- "Cartesia realtime client secrets must expire between 1 and 3600 seconds."
748
- );
749
- }
750
- const sessionConfig = options.sessionConfig;
751
- const language = sessionConfig?.inputAudioTranscription?.language;
752
- if (language != null && language !== "en") {
753
- throw new Error("Cartesia Ink 2 currently supports English only.");
754
- }
755
- const fetchFn = this.config.fetch ?? fetch;
756
- const response = await fetchFn(`${this.config.baseURL}/access-token`, {
757
- method: "POST",
758
- headers: {
759
- ...this.config.headers(),
760
- "Content-Type": "application/json"
761
- },
762
- body: JSON.stringify({
763
- grants: { stt: true },
764
- ...expiresIn != null ? { expires_in: expiresIn } : {}
765
- })
766
- });
767
- if (!response.ok) {
768
- const text = await response.text();
769
- throw new Error(
770
- `Cartesia realtime client secret request failed: ${response.status} ${text}`
771
- );
772
- }
773
- const data = await response.json();
774
- if (typeof data.token !== "string" || data.token.length === 0) {
775
- throw new Error(
776
- "Cartesia realtime client secret response did not include a token."
777
- );
778
- }
779
- const turnDetection = sessionConfig?.turnDetection;
780
- const useTurnDetection = turnDetection === void 0 || turnDetection !== null && turnDetection.type !== "disabled";
781
- const inputAudioFormat = sessionConfig?.inputAudioFormat;
782
- const url = new URL(
783
- useTurnDetection ? `${this.config.baseURL}/stt/turns/websocket` : `${this.config.baseURL}/stt/websocket`
784
- );
785
- url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
786
- url.searchParams.set("model", this.modelId);
787
- url.searchParams.set(
788
- "encoding",
789
- resolveCartesiaEncoding(inputAudioFormat?.type)
790
- );
791
- url.searchParams.set(
792
- "sample_rate",
793
- String(inputAudioFormat?.rate ?? 24e3)
794
- );
795
- url.searchParams.set("cartesia_version", this.config.version);
796
- if (!useTurnDetection && language != null) {
797
- url.searchParams.set("language", language);
798
- }
799
- return {
800
- token: data.token,
801
- url: url.toString(),
802
- ...expiresIn != null ? {
803
- expiresAt: Math.floor(
804
- (this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date()).getTime() / 1e3
805
- ) + expiresIn
806
- } : {}
807
- };
808
- }
809
- getWebSocketConfig(options) {
810
- const url = new URL(options.url);
811
- this.useTurnDetection = url.pathname.includes("/stt/turns/websocket");
812
- url.searchParams.set("access_token", options.token);
813
- return { url: url.toString() };
814
- }
815
- parseServerEvent(raw) {
816
- const event = raw;
817
- const requestId = event.request_id ?? "cartesia-realtime";
818
- let mapped;
819
- switch (event.type) {
820
- case "connected":
821
- this.sessionCreated = true;
822
- return {
823
- type: "session-created",
824
- sessionId: event.request_id,
825
- raw
826
- };
827
- case "turn.start":
828
- mapped = { type: "speech-started", itemId: requestId, raw };
829
- break;
830
- case "turn.resume":
831
- mapped = [
832
- { type: "speech-started", itemId: requestId, raw },
833
- { type: "custom", rawType: event.type, raw }
834
- ];
835
- break;
836
- case "turn.end":
837
- mapped = [
838
- { type: "speech-stopped", itemId: requestId, raw },
839
- {
840
- type: "input-transcription-completed",
841
- itemId: requestId,
842
- transcript: event.transcript ?? "",
843
- raw
844
- }
845
- ];
846
- break;
847
- case "transcript":
848
- if (event.is_final === true) {
849
- this.manualTranscript.text += event.text ?? "";
850
- this.manualTranscript.duration += event.duration ?? 0;
851
- this.manualTranscript.events.push(event);
852
- }
853
- mapped = { type: "custom", rawType: event.type, raw };
854
- break;
855
- case "flush_done":
856
- mapped = this.finishManualTranscript(event, raw);
857
- break;
858
- case "done": {
859
- if (this.manualTranscript.text.length > 0) {
860
- const completed = this.finishManualTranscript(event, raw);
861
- mapped = Array.isArray(completed) ? [...completed, { type: "custom", rawType: event.type, raw }] : [completed, { type: "custom", rawType: event.type, raw }];
862
- } else {
863
- mapped = { type: "custom", rawType: event.type, raw };
864
- }
865
- break;
866
- }
867
- case "error":
868
- mapped = {
869
- type: "error",
870
- message: event.message ?? "Unknown Cartesia realtime error",
871
- code: event.error_code,
872
- raw
873
- };
874
- break;
875
- default:
876
- mapped = { type: "custom", rawType: event.type, raw };
877
- break;
878
- }
879
- return this.withSessionCreated(mapped, requestId, raw);
880
- }
881
- serializeClientEvent(event) {
882
- switch (event.type) {
883
- case "session-update":
884
- case "input-audio-clear":
885
- case "response-create":
886
- return null;
887
- case "input-audio-append":
888
- return convertBase64ToUint8Array2(event.audio);
889
- case "input-audio-commit":
890
- return this.useTurnDetection ? null : "finalize";
891
- default:
892
- throw new Error(
893
- `Cartesia Ink 2 does not support realtime client event "${event.type}".`
894
- );
895
- }
896
- }
897
- buildSessionConfig(_config) {
898
- return null;
899
- }
900
- finishManualTranscript(event, raw) {
901
- const state = this.manualTranscript;
902
- this.manualTranscript = { duration: 0, events: [], text: "" };
903
- if (state.text.length === 0) {
904
- return { type: "custom", rawType: event.type, raw };
905
- }
906
- return [
907
- {
908
- type: "audio-committed",
909
- itemId: event.request_id,
910
- raw
911
- },
912
- {
913
- type: "input-transcription-completed",
914
- itemId: event.request_id ?? "cartesia-realtime",
915
- transcript: state.text,
916
- raw: {
917
- event,
918
- transcriptEvents: state.events,
919
- duration: state.duration
920
- }
921
- }
922
- ];
923
- }
924
- withSessionCreated(event, sessionId, raw) {
925
- if (this.sessionCreated) {
926
- return event;
927
- }
928
- this.sessionCreated = true;
929
- const created = {
930
- type: "session-created",
931
- sessionId,
932
- raw
933
- };
934
- return Array.isArray(event) ? [created, ...event] : [created, event];
935
- }
599
+ constructor(modelId, config) {
600
+ this.specificationVersion = "v4";
601
+ this.manualTranscript = {
602
+ duration: 0,
603
+ events: [],
604
+ text: ""
605
+ };
606
+ this.sessionCreated = false;
607
+ this.useTurnDetection = true;
608
+ this.modelId = modelId;
609
+ this.provider = config.provider;
610
+ this.config = config;
611
+ }
612
+ async doCreateClientSecret(options) {
613
+ const expiresIn = options.expiresAfterSeconds;
614
+ if (expiresIn != null && (!Number.isInteger(expiresIn) || expiresIn <= 0 || expiresIn > 3600)) throw new Error("Cartesia realtime client secrets must expire between 1 and 3600 seconds.");
615
+ const sessionConfig = options.sessionConfig;
616
+ const language = sessionConfig?.inputAudioTranscription?.language;
617
+ if (language != null && language !== "en") throw new Error("Cartesia Ink 2 currently supports English only.");
618
+ const response = await (this.config.fetch ?? fetch)(`${this.config.baseURL}/access-token`, {
619
+ method: "POST",
620
+ headers: {
621
+ ...this.config.headers(),
622
+ "Content-Type": "application/json"
623
+ },
624
+ body: JSON.stringify({
625
+ grants: { stt: true },
626
+ ...expiresIn != null ? { expires_in: expiresIn } : {}
627
+ })
628
+ });
629
+ if (!response.ok) {
630
+ const text = await response.text();
631
+ throw new Error(`Cartesia realtime client secret request failed: ${response.status} ${text}`);
632
+ }
633
+ const data = await response.json();
634
+ if (typeof data.token !== "string" || data.token.length === 0) throw new Error("Cartesia realtime client secret response did not include a token.");
635
+ const turnDetection = sessionConfig?.turnDetection;
636
+ const useTurnDetection = turnDetection === void 0 || turnDetection !== null && turnDetection.type !== "disabled";
637
+ const inputAudioFormat = sessionConfig?.inputAudioFormat;
638
+ const url = new URL(useTurnDetection ? `${this.config.baseURL}/stt/turns/websocket` : `${this.config.baseURL}/stt/websocket`);
639
+ url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
640
+ url.searchParams.set("model", this.modelId);
641
+ url.searchParams.set("encoding", resolveCartesiaEncoding(inputAudioFormat?.type));
642
+ url.searchParams.set("sample_rate", String(inputAudioFormat?.rate ?? 24e3));
643
+ url.searchParams.set("cartesia_version", this.config.version);
644
+ if (!useTurnDetection && language != null) url.searchParams.set("language", language);
645
+ return {
646
+ token: data.token,
647
+ url: url.toString(),
648
+ ...expiresIn != null ? { expiresAt: Math.floor((this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date()).getTime() / 1e3) + expiresIn } : {}
649
+ };
650
+ }
651
+ getWebSocketConfig(options) {
652
+ const url = new URL(options.url);
653
+ this.useTurnDetection = url.pathname.includes("/stt/turns/websocket");
654
+ url.searchParams.set("access_token", options.token);
655
+ return { url: url.toString() };
656
+ }
657
+ parseServerEvent(raw) {
658
+ const event = raw;
659
+ const requestId = event.request_id ?? "cartesia-realtime";
660
+ let mapped;
661
+ switch (event.type) {
662
+ case "connected":
663
+ this.sessionCreated = true;
664
+ return {
665
+ type: "session-created",
666
+ sessionId: event.request_id,
667
+ raw
668
+ };
669
+ case "turn.start":
670
+ mapped = {
671
+ type: "speech-started",
672
+ itemId: requestId,
673
+ raw
674
+ };
675
+ break;
676
+ case "turn.resume":
677
+ mapped = [{
678
+ type: "speech-started",
679
+ itemId: requestId,
680
+ raw
681
+ }, {
682
+ type: "custom",
683
+ rawType: event.type,
684
+ raw
685
+ }];
686
+ break;
687
+ case "turn.end":
688
+ mapped = [{
689
+ type: "speech-stopped",
690
+ itemId: requestId,
691
+ raw
692
+ }, {
693
+ type: "input-transcription-completed",
694
+ itemId: requestId,
695
+ transcript: event.transcript ?? "",
696
+ raw
697
+ }];
698
+ break;
699
+ case "transcript":
700
+ if (event.is_final === true) {
701
+ this.manualTranscript.text += event.text ?? "";
702
+ this.manualTranscript.duration += event.duration ?? 0;
703
+ this.manualTranscript.events.push(event);
704
+ }
705
+ mapped = {
706
+ type: "custom",
707
+ rawType: event.type,
708
+ raw
709
+ };
710
+ break;
711
+ case "flush_done":
712
+ mapped = this.finishManualTranscript(event, raw);
713
+ break;
714
+ case "done":
715
+ if (this.manualTranscript.text.length > 0) {
716
+ const completed = this.finishManualTranscript(event, raw);
717
+ mapped = Array.isArray(completed) ? [...completed, {
718
+ type: "custom",
719
+ rawType: event.type,
720
+ raw
721
+ }] : [completed, {
722
+ type: "custom",
723
+ rawType: event.type,
724
+ raw
725
+ }];
726
+ } else mapped = {
727
+ type: "custom",
728
+ rawType: event.type,
729
+ raw
730
+ };
731
+ break;
732
+ case "error":
733
+ mapped = {
734
+ type: "error",
735
+ message: event.message ?? "Unknown Cartesia realtime error",
736
+ code: event.error_code,
737
+ raw
738
+ };
739
+ break;
740
+ default: mapped = {
741
+ type: "custom",
742
+ rawType: event.type,
743
+ raw
744
+ };
745
+ }
746
+ return this.withSessionCreated(mapped, requestId, raw);
747
+ }
748
+ serializeClientEvent(event) {
749
+ switch (event.type) {
750
+ case "session-update":
751
+ case "input-audio-clear":
752
+ case "response-create": return null;
753
+ case "input-audio-append": return convertBase64ToUint8Array(event.audio);
754
+ case "input-audio-commit": return this.useTurnDetection ? null : "finalize";
755
+ default: throw new Error(`Cartesia Ink 2 does not support realtime client event "${event.type}".`);
756
+ }
757
+ }
758
+ buildSessionConfig(_config) {
759
+ return null;
760
+ }
761
+ finishManualTranscript(event, raw) {
762
+ const state = this.manualTranscript;
763
+ this.manualTranscript = {
764
+ duration: 0,
765
+ events: [],
766
+ text: ""
767
+ };
768
+ if (state.text.length === 0) return {
769
+ type: "custom",
770
+ rawType: event.type,
771
+ raw
772
+ };
773
+ return [{
774
+ type: "audio-committed",
775
+ itemId: event.request_id,
776
+ raw
777
+ }, {
778
+ type: "input-transcription-completed",
779
+ itemId: event.request_id ?? "cartesia-realtime",
780
+ transcript: state.text,
781
+ raw: {
782
+ event,
783
+ transcriptEvents: state.events,
784
+ duration: state.duration
785
+ }
786
+ }];
787
+ }
788
+ withSessionCreated(event, sessionId, raw) {
789
+ if (this.sessionCreated) return event;
790
+ this.sessionCreated = true;
791
+ const created = {
792
+ type: "session-created",
793
+ sessionId,
794
+ raw
795
+ };
796
+ return Array.isArray(event) ? [created, ...event] : [created, event];
797
+ }
936
798
  };
937
799
  function resolveCartesiaEncoding(type) {
938
- switch (type) {
939
- case void 0:
940
- case "audio/pcm":
941
- return "pcm_s16le";
942
- case "audio/pcmu":
943
- return "pcm_mulaw";
944
- case "audio/pcma":
945
- return "pcm_alaw";
946
- default:
947
- throw new Error(`Unsupported Cartesia realtime audio format: ${type}`);
948
- }
800
+ switch (type) {
801
+ case void 0:
802
+ case "audio/pcm": return "pcm_s16le";
803
+ case "audio/pcmu": return "pcm_mulaw";
804
+ case "audio/pcma": return "pcm_alaw";
805
+ default: throw new Error(`Unsupported Cartesia realtime audio format: ${type}`);
806
+ }
949
807
  }
950
-
951
- // src/version.ts
952
- var VERSION = true ? "3.0.45" : "0.0.0-test";
953
-
954
- // src/cartesia-provider.ts
955
- var CARTESIA_API_VERSION = "2026-03-01";
808
+ //#endregion
809
+ //#region src/version.ts
810
+ const VERSION = "3.0.47";
811
+ //#endregion
812
+ //#region src/cartesia-provider.ts
813
+ /**
814
+ * The Cartesia API version sent with every request via the `Cartesia-Version`
815
+ * header. See https://docs.cartesia.ai/api-reference/api-versioning
816
+ */
817
+ const CARTESIA_API_VERSION = "2026-03-01";
818
+ /**
819
+ * Create a Cartesia provider instance.
820
+ */
956
821
  function createCartesia(options = {}) {
957
- const getHeaders = () => withUserAgentSuffix(
958
- {
959
- Authorization: `Bearer ${loadApiKey({
960
- apiKey: options.apiKey,
961
- environmentVariableName: "CARTESIA_API_KEY",
962
- description: "Cartesia"
963
- })}`,
964
- "Cartesia-Version": options.version ?? CARTESIA_API_VERSION,
965
- ...options.headers
966
- },
967
- `ai-sdk/cartesia/${VERSION}`
968
- );
969
- const createTranscriptionModel = (modelId) => new CartesiaTranscriptionModel(modelId, {
970
- provider: `cartesia.transcription`,
971
- url: ({ path }) => `https://api.cartesia.ai${path}`,
972
- headers: getHeaders,
973
- fetch: options.fetch,
974
- version: options.version ?? CARTESIA_API_VERSION,
975
- webSocket: options.webSocket
976
- });
977
- const createSpeechModel = (modelId) => new CartesiaSpeechModel(modelId, {
978
- provider: `cartesia.speech`,
979
- url: ({ path }) => `https://api.cartesia.ai${path}`,
980
- headers: getHeaders,
981
- fetch: options.fetch
982
- });
983
- const createRealtimeModel = (modelId) => new CartesiaRealtimeModel(modelId, {
984
- provider: `cartesia.realtime`,
985
- baseURL: "https://api.cartesia.ai",
986
- version: options.version ?? CARTESIA_API_VERSION,
987
- headers: getHeaders,
988
- fetch: options.fetch
989
- });
990
- const experimentalRealtimeFactory = Object.assign(
991
- (modelId) => createRealtimeModel(modelId),
992
- {
993
- getToken: async (tokenOptions) => {
994
- const secret = await createRealtimeModel(
995
- tokenOptions.model
996
- ).doCreateClientSecret({
997
- sessionConfig: tokenOptions.sessionConfig,
998
- expiresAfterSeconds: tokenOptions.expiresAfterSeconds
999
- });
1000
- return {
1001
- token: secret.token,
1002
- url: secret.url,
1003
- expiresAt: secret.expiresAt
1004
- };
1005
- }
1006
- }
1007
- );
1008
- const provider = function(modelId) {
1009
- return {
1010
- speech: createSpeechModel(modelId)
1011
- };
1012
- };
1013
- provider.specificationVersion = "v4";
1014
- provider.transcription = createTranscriptionModel;
1015
- provider.transcriptionModel = createTranscriptionModel;
1016
- provider.speech = createSpeechModel;
1017
- provider.speechModel = createSpeechModel;
1018
- provider.experimental_realtime = experimentalRealtimeFactory;
1019
- provider.languageModel = (modelId) => {
1020
- throw new NoSuchModelError({
1021
- modelId,
1022
- modelType: "languageModel",
1023
- message: "Cartesia does not provide language models"
1024
- });
1025
- };
1026
- provider.embeddingModel = (modelId) => {
1027
- throw new NoSuchModelError({
1028
- modelId,
1029
- modelType: "embeddingModel",
1030
- message: "Cartesia does not provide embedding models"
1031
- });
1032
- };
1033
- provider.textEmbeddingModel = provider.embeddingModel;
1034
- provider.imageModel = (modelId) => {
1035
- throw new NoSuchModelError({
1036
- modelId,
1037
- modelType: "imageModel",
1038
- message: "Cartesia does not provide image models"
1039
- });
1040
- };
1041
- return provider;
822
+ const getHeaders = () => withUserAgentSuffix({
823
+ Authorization: `Bearer ${loadApiKey({
824
+ apiKey: options.apiKey,
825
+ environmentVariableName: "CARTESIA_API_KEY",
826
+ description: "Cartesia"
827
+ })}`,
828
+ "Cartesia-Version": options.version ?? CARTESIA_API_VERSION,
829
+ ...options.headers
830
+ }, `ai-sdk-cartesia/${VERSION}`);
831
+ const createTranscriptionModel = (modelId) => new CartesiaTranscriptionModel(modelId, {
832
+ provider: `cartesia.transcription`,
833
+ url: ({ path }) => `https://api.cartesia.ai${path}`,
834
+ headers: getHeaders,
835
+ fetch: options.fetch,
836
+ version: options.version ?? CARTESIA_API_VERSION,
837
+ webSocket: options.webSocket
838
+ });
839
+ const createSpeechModel = (modelId) => new CartesiaSpeechModel(modelId, {
840
+ provider: `cartesia.speech`,
841
+ url: ({ path }) => `https://api.cartesia.ai${path}`,
842
+ headers: getHeaders,
843
+ fetch: options.fetch
844
+ });
845
+ const createRealtimeModel = (modelId) => new CartesiaRealtimeModel(modelId, {
846
+ provider: `cartesia.realtime`,
847
+ baseURL: "https://api.cartesia.ai",
848
+ version: options.version ?? CARTESIA_API_VERSION,
849
+ headers: getHeaders,
850
+ fetch: options.fetch
851
+ });
852
+ const experimentalRealtimeFactory = Object.assign((modelId) => createRealtimeModel(modelId), { getToken: async (tokenOptions) => {
853
+ const secret = await createRealtimeModel(tokenOptions.model).doCreateClientSecret({
854
+ sessionConfig: tokenOptions.sessionConfig,
855
+ expiresAfterSeconds: tokenOptions.expiresAfterSeconds
856
+ });
857
+ return {
858
+ token: secret.token,
859
+ url: secret.url,
860
+ expiresAt: secret.expiresAt
861
+ };
862
+ } });
863
+ const provider = function(modelId) {
864
+ return { speech: createSpeechModel(modelId) };
865
+ };
866
+ provider.specificationVersion = "v4";
867
+ provider.transcription = createTranscriptionModel;
868
+ provider.transcriptionModel = createTranscriptionModel;
869
+ provider.speech = createSpeechModel;
870
+ provider.speechModel = createSpeechModel;
871
+ provider.experimental_realtime = experimentalRealtimeFactory;
872
+ provider.languageModel = (modelId) => {
873
+ throw new NoSuchModelError({
874
+ modelId,
875
+ modelType: "languageModel",
876
+ message: "Cartesia does not provide language models"
877
+ });
878
+ };
879
+ provider.embeddingModel = (modelId) => {
880
+ throw new NoSuchModelError({
881
+ modelId,
882
+ modelType: "embeddingModel",
883
+ message: "Cartesia does not provide embedding models"
884
+ });
885
+ };
886
+ provider.textEmbeddingModel = provider.embeddingModel;
887
+ provider.imageModel = (modelId) => {
888
+ throw new NoSuchModelError({
889
+ modelId,
890
+ modelType: "imageModel",
891
+ message: "Cartesia does not provide image models"
892
+ });
893
+ };
894
+ return provider;
1042
895
  }
1043
- var cartesia = createCartesia();
1044
- export {
1045
- CartesiaRealtimeModel,
1046
- CartesiaSpeechModel,
1047
- CartesiaTranscriptionModel,
1048
- VERSION,
1049
- cartesia,
1050
- createCartesia
1051
- };
896
+ /**
897
+ * Default Cartesia provider instance.
898
+ */
899
+ const cartesia = createCartesia();
900
+ //#endregion
901
+ export { CartesiaRealtimeModel, CartesiaSpeechModel, CartesiaTranscriptionModel, VERSION, cartesia, createCartesia };
902
+
1052
903
  //# sourceMappingURL=index.js.map